#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#define MAX_THREADS 10
#define OPS 5
#define TEST_CASES 3
int BUFFER = 0;
// Semaphores
sem_t buffer_sem;
sem_t read_count_sem;
sem_t password_sem;
int read_count = 0;
// Password table
unsigned long password_table[MAX_THREADS];
int table_size = 0;
typedef struct {
int thread_no;
unsigned long hash_val;
char validity[8];
char role[8];
int value;
} log_entry_t;
log_entry_t logs[TEST_CASES][40];
int log_pos[TEST_CASES] = {0};
typedef struct {
int thread_no;
int is_reader;
int is_real;
int test_case;
} ThreadInfo;
unsigned long hash_pthread_t(pthread_t thread_id) {
return (unsigned long)(uintptr_t)thread_id;
}
void register_thread(pthread_t tid) {
sem_wait(&password_sem);
password_table[table_size++] = hash_pthread_t(tid);
sem_post(&password_sem);
}
int is_valid_thread(pthread_t tid) {
unsigned long h = hash_pthread_t(tid);
sem_wait(&password_sem);
for (int i = 0; i < table_size; i++) {
if (password_table[i] == h) {
sem_post(&password_sem);
return 1;
}
}
sem_post(&password_sem);
return 0;
}
void log_action(int case_id, int thread_no, pthread_t tid, int is_real, int is_reader, int value) {
log_entry_t *entry = &logs[case_id][log_pos[case_id]++];
entry->thread_no = thread_no;
entry->hash_val = hash_pthread_t(tid);
strcpy(entry
->validity
, is_real
? "real" : "dummy"); strcpy(entry
->role
, is_reader
? "reader" : "writer"); entry->value = value;
}
void *reader_func(void *arg) {
ThreadInfo *info = (ThreadInfo *)arg;
srand(time(NULL
) ^ (uintptr_t)pthread_self
()); if (info->is_real) register_thread(pthread_self());
for (int i = 0; i < OPS; i++) {
sleep(1);
if (!is_valid_thread(pthread_self())) {
log_action(info->test_case, info->thread_no, pthread_self(), info->is_real, 1, -1);
continue;
}
sem_wait(&read_count_sem);
read_count++;
if (read_count == 1) sem_wait(&buffer_sem);
sem_post(&read_count_sem);
log_action(info->test_case, info->thread_no, pthread_self(), info->is_real, 1, BUFFER);
sem_wait(&read_count_sem);
read_count--;
if (read_count == 0) sem_post(&buffer_sem);
sem_post(&read_count_sem);
}
return NULL;
}
void *writer_func(void *arg) {
ThreadInfo *info = (ThreadInfo *)arg;
srand(time(NULL
) ^ (uintptr_t)pthread_self
()); if (info->is_real) register_thread(pthread_self());
for (int i = 0; i < OPS; i++) {
sleep(1);
if (!is_valid_thread(pthread_self())) {
log_action(info->test_case, info->thread_no, pthread_self(), info->is_real, 0, -1);
continue;
}
sem_wait(&buffer_sem);
int val
= rand() % 10000; BUFFER = val;
log_action(info->test_case, info->thread_no, pthread_self(), info->is_real, 0, val);
sem_post(&buffer_sem);
}
return NULL;
}
void print_log(int case_id) {
printf("===== Test Case %d =====\n", case_id
+ 1); printf("Thread_No | Hash_Value | Validity | Role | Value\n"); printf("--------------------------------------------------------\n"); for (int i = 0; i < log_pos[case_id]; i++) {
printf("%9d | %016lx | %7s | %6s | %5d\n", logs[case_id][i].thread_no,
logs[case_id][i].hash_val,
logs[case_id][i].validity,
logs[case_id][i].role,
logs[case_id][i].value);
}
}
int main() {
sem_init(&buffer_sem, 0, 1);
sem_init(&read_count_sem, 0, 1);
sem_init(&password_sem, 0, 1);
int test_cases[3][2] = {{2, 2}, {3, 1}, {1, 4}};
pthread_t threads[40];
int tcount = 0;
for (int t = 0; t < TEST_CASES; t++) {
int readers = test_cases[t][0];
int writers = test_cases[t][1];
for (int i = 0; i < readers; i++) {
ThreadInfo
*info
= malloc(sizeof(ThreadInfo
)); *info = (ThreadInfo){.thread_no = tcount + 1, .is_reader = 1, .is_real = 1, .test_case = t};
pthread_create(&threads[tcount], NULL, reader_func, info);
tcount++;
}
for (int i = 0; i < writers; i++) {
ThreadInfo
*info
= malloc(sizeof(ThreadInfo
)); *info = (ThreadInfo){.thread_no = tcount + 1, .is_reader = 0, .is_real = 1, .test_case = t};
pthread_create(&threads[tcount], NULL, writer_func, info);
tcount++;
}
for (int i = 0; i < readers; i++) {
ThreadInfo
*info
= malloc(sizeof(ThreadInfo
)); *info = (ThreadInfo){.thread_no = tcount + 1, .is_reader = 1, .is_real = 0, .test_case = t};
pthread_create(&threads[tcount], NULL, reader_func, info);
tcount++;
}
for (int i = 0; i < writers; i++) {
ThreadInfo
*info
= malloc(sizeof(ThreadInfo
)); *info = (ThreadInfo){.thread_no = tcount + 1, .is_reader = 0, .is_real = 0, .test_case = t};
pthread_create(&threads[tcount], NULL, writer_func, info);
tcount++;
}
}
for (int i = 0; i < tcount; i++) {
pthread_join(threads[i], NULL);
}
for (int t = 0; t < TEST_CASES; t++) {
print_log(t);
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHB0aHJlYWQuaD4KI2luY2x1ZGUgPHNlbWFwaG9yZS5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CiNpbmNsdWRlIDxzdGRpbnQuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgoKI2RlZmluZSBNQVhfVEhSRUFEUyAxMAojZGVmaW5lIE9QUyA1CiNkZWZpbmUgVEVTVF9DQVNFUyAzCgppbnQgQlVGRkVSID0gMDsKCi8vIFNlbWFwaG9yZXMKc2VtX3QgYnVmZmVyX3NlbTsKc2VtX3QgcmVhZF9jb3VudF9zZW07CnNlbV90IHBhc3N3b3JkX3NlbTsKCmludCByZWFkX2NvdW50ID0gMDsKCi8vIFBhc3N3b3JkIHRhYmxlCnVuc2lnbmVkIGxvbmcgcGFzc3dvcmRfdGFibGVbTUFYX1RIUkVBRFNdOwppbnQgdGFibGVfc2l6ZSA9IDA7Cgp0eXBlZGVmIHN0cnVjdCB7CiAgICBpbnQgdGhyZWFkX25vOwogICAgdW5zaWduZWQgbG9uZyBoYXNoX3ZhbDsKICAgIGNoYXIgdmFsaWRpdHlbOF07CiAgICBjaGFyIHJvbGVbOF07CiAgICBpbnQgdmFsdWU7Cn0gbG9nX2VudHJ5X3Q7Cgpsb2dfZW50cnlfdCBsb2dzW1RFU1RfQ0FTRVNdWzQwXTsKaW50IGxvZ19wb3NbVEVTVF9DQVNFU10gPSB7MH07Cgp0eXBlZGVmIHN0cnVjdCB7CiAgICBpbnQgdGhyZWFkX25vOwogICAgaW50IGlzX3JlYWRlcjsKICAgIGludCBpc19yZWFsOwogICAgaW50IHRlc3RfY2FzZTsKfSBUaHJlYWRJbmZvOwoKdW5zaWduZWQgbG9uZyBoYXNoX3B0aHJlYWRfdChwdGhyZWFkX3QgdGhyZWFkX2lkKSB7CiAgICByZXR1cm4gKHVuc2lnbmVkIGxvbmcpKHVpbnRwdHJfdCl0aHJlYWRfaWQ7Cn0KCnZvaWQgcmVnaXN0ZXJfdGhyZWFkKHB0aHJlYWRfdCB0aWQpIHsKICAgIHNlbV93YWl0KCZwYXNzd29yZF9zZW0pOwogICAgcGFzc3dvcmRfdGFibGVbdGFibGVfc2l6ZSsrXSA9IGhhc2hfcHRocmVhZF90KHRpZCk7CiAgICBzZW1fcG9zdCgmcGFzc3dvcmRfc2VtKTsKfQoKaW50IGlzX3ZhbGlkX3RocmVhZChwdGhyZWFkX3QgdGlkKSB7CiAgICB1bnNpZ25lZCBsb25nIGggPSBoYXNoX3B0aHJlYWRfdCh0aWQpOwogICAgc2VtX3dhaXQoJnBhc3N3b3JkX3NlbSk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHRhYmxlX3NpemU7IGkrKykgewogICAgICAgIGlmIChwYXNzd29yZF90YWJsZVtpXSA9PSBoKSB7CiAgICAgICAgICAgIHNlbV9wb3N0KCZwYXNzd29yZF9zZW0pOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICB9CiAgICBzZW1fcG9zdCgmcGFzc3dvcmRfc2VtKTsKICAgIHJldHVybiAwOwp9Cgp2b2lkIGxvZ19hY3Rpb24oaW50IGNhc2VfaWQsIGludCB0aHJlYWRfbm8sIHB0aHJlYWRfdCB0aWQsIGludCBpc19yZWFsLCBpbnQgaXNfcmVhZGVyLCBpbnQgdmFsdWUpIHsKICAgIGxvZ19lbnRyeV90ICplbnRyeSA9ICZsb2dzW2Nhc2VfaWRdW2xvZ19wb3NbY2FzZV9pZF0rK107CiAgICBlbnRyeS0+dGhyZWFkX25vID0gdGhyZWFkX25vOwogICAgZW50cnktPmhhc2hfdmFsID0gaGFzaF9wdGhyZWFkX3QodGlkKTsKICAgIHN0cmNweShlbnRyeS0+dmFsaWRpdHksIGlzX3JlYWwgPyAicmVhbCIgOiAiZHVtbXkiKTsKICAgIHN0cmNweShlbnRyeS0+cm9sZSwgaXNfcmVhZGVyID8gInJlYWRlciIgOiAid3JpdGVyIik7CiAgICBlbnRyeS0+dmFsdWUgPSB2YWx1ZTsKfQoKdm9pZCAqcmVhZGVyX2Z1bmModm9pZCAqYXJnKSB7CiAgICBUaHJlYWRJbmZvICppbmZvID0gKFRocmVhZEluZm8gKilhcmc7CiAgICBzcmFuZCh0aW1lKE5VTEwpIF4gKHVpbnRwdHJfdClwdGhyZWFkX3NlbGYoKSk7CiAgICBpZiAoaW5mby0+aXNfcmVhbCkgcmVnaXN0ZXJfdGhyZWFkKHB0aHJlYWRfc2VsZigpKTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IE9QUzsgaSsrKSB7CiAgICAgICAgc2xlZXAoMSk7CiAgICAgICAgaWYgKCFpc192YWxpZF90aHJlYWQocHRocmVhZF9zZWxmKCkpKSB7CiAgICAgICAgICAgIGxvZ19hY3Rpb24oaW5mby0+dGVzdF9jYXNlLCBpbmZvLT50aHJlYWRfbm8sIHB0aHJlYWRfc2VsZigpLCBpbmZvLT5pc19yZWFsLCAxLCAtMSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgc2VtX3dhaXQoJnJlYWRfY291bnRfc2VtKTsKICAgICAgICByZWFkX2NvdW50Kys7CiAgICAgICAgaWYgKHJlYWRfY291bnQgPT0gMSkgc2VtX3dhaXQoJmJ1ZmZlcl9zZW0pOwogICAgICAgIHNlbV9wb3N0KCZyZWFkX2NvdW50X3NlbSk7CgogICAgICAgIGxvZ19hY3Rpb24oaW5mby0+dGVzdF9jYXNlLCBpbmZvLT50aHJlYWRfbm8sIHB0aHJlYWRfc2VsZigpLCBpbmZvLT5pc19yZWFsLCAxLCBCVUZGRVIpOwoKICAgICAgICBzZW1fd2FpdCgmcmVhZF9jb3VudF9zZW0pOwogICAgICAgIHJlYWRfY291bnQtLTsKICAgICAgICBpZiAocmVhZF9jb3VudCA9PSAwKSBzZW1fcG9zdCgmYnVmZmVyX3NlbSk7CiAgICAgICAgc2VtX3Bvc3QoJnJlYWRfY291bnRfc2VtKTsKICAgIH0KCiAgICBmcmVlKGluZm8pOwogICAgcmV0dXJuIE5VTEw7Cn0KCnZvaWQgKndyaXRlcl9mdW5jKHZvaWQgKmFyZykgewogICAgVGhyZWFkSW5mbyAqaW5mbyA9IChUaHJlYWRJbmZvICopYXJnOwogICAgc3JhbmQodGltZShOVUxMKSBeICh1aW50cHRyX3QpcHRocmVhZF9zZWxmKCkpOwogICAgaWYgKGluZm8tPmlzX3JlYWwpIHJlZ2lzdGVyX3RocmVhZChwdGhyZWFkX3NlbGYoKSk7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBPUFM7IGkrKykgewogICAgICAgIHNsZWVwKDEpOwogICAgICAgIGlmICghaXNfdmFsaWRfdGhyZWFkKHB0aHJlYWRfc2VsZigpKSkgewogICAgICAgICAgICBsb2dfYWN0aW9uKGluZm8tPnRlc3RfY2FzZSwgaW5mby0+dGhyZWFkX25vLCBwdGhyZWFkX3NlbGYoKSwgaW5mby0+aXNfcmVhbCwgMCwgLTEpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHNlbV93YWl0KCZidWZmZXJfc2VtKTsKICAgICAgICBpbnQgdmFsID0gcmFuZCgpICUgMTAwMDA7CiAgICAgICAgQlVGRkVSID0gdmFsOwogICAgICAgIGxvZ19hY3Rpb24oaW5mby0+dGVzdF9jYXNlLCBpbmZvLT50aHJlYWRfbm8sIHB0aHJlYWRfc2VsZigpLCBpbmZvLT5pc19yZWFsLCAwLCB2YWwpOwogICAgICAgIHNlbV9wb3N0KCZidWZmZXJfc2VtKTsKICAgIH0KCiAgICBmcmVlKGluZm8pOwogICAgcmV0dXJuIE5VTEw7Cn0KCnZvaWQgcHJpbnRfbG9nKGludCBjYXNlX2lkKSB7CiAgICBwcmludGYoIj09PT09IFRlc3QgQ2FzZSAlZCA9PT09PVxuIiwgY2FzZV9pZCArIDEpOwogICAgcHJpbnRmKCJUaHJlYWRfTm8gfCBIYXNoX1ZhbHVlICAgICAgIHwgVmFsaWRpdHkgfCBSb2xlICAgfCBWYWx1ZVxuIik7CiAgICBwcmludGYoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4iKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbG9nX3Bvc1tjYXNlX2lkXTsgaSsrKSB7CiAgICAgICAgcHJpbnRmKCIlOWQgfCAlMDE2bHggfCAlN3MgIHwgJTZzIHwgJTVkXG4iLAogICAgICAgICAgICAgICBsb2dzW2Nhc2VfaWRdW2ldLnRocmVhZF9ubywKICAgICAgICAgICAgICAgbG9nc1tjYXNlX2lkXVtpXS5oYXNoX3ZhbCwKICAgICAgICAgICAgICAgbG9nc1tjYXNlX2lkXVtpXS52YWxpZGl0eSwKICAgICAgICAgICAgICAgbG9nc1tjYXNlX2lkXVtpXS5yb2xlLAogICAgICAgICAgICAgICBsb2dzW2Nhc2VfaWRdW2ldLnZhbHVlKTsKICAgIH0KICAgIHByaW50ZigiXG4iKTsKfQoKaW50IG1haW4oKSB7CiAgICBzcmFuZCh0aW1lKE5VTEwpKTsKCiAgICBzZW1faW5pdCgmYnVmZmVyX3NlbSwgMCwgMSk7CiAgICBzZW1faW5pdCgmcmVhZF9jb3VudF9zZW0sIDAsIDEpOwogICAgc2VtX2luaXQoJnBhc3N3b3JkX3NlbSwgMCwgMSk7CgogICAgaW50IHRlc3RfY2FzZXNbM11bMl0gPSB7ezIsIDJ9LCB7MywgMX0sIHsxLCA0fX07CiAgICBwdGhyZWFkX3QgdGhyZWFkc1s0MF07CiAgICBpbnQgdGNvdW50ID0gMDsKCiAgICBmb3IgKGludCB0ID0gMDsgdCA8IFRFU1RfQ0FTRVM7IHQrKykgewogICAgICAgIGludCByZWFkZXJzID0gdGVzdF9jYXNlc1t0XVswXTsKICAgICAgICBpbnQgd3JpdGVycyA9IHRlc3RfY2FzZXNbdF1bMV07CgogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcmVhZGVyczsgaSsrKSB7CiAgICAgICAgICAgIFRocmVhZEluZm8gKmluZm8gPSBtYWxsb2Moc2l6ZW9mKFRocmVhZEluZm8pKTsKICAgICAgICAgICAgKmluZm8gPSAoVGhyZWFkSW5mbyl7LnRocmVhZF9ubyA9IHRjb3VudCArIDEsIC5pc19yZWFkZXIgPSAxLCAuaXNfcmVhbCA9IDEsIC50ZXN0X2Nhc2UgPSB0fTsKICAgICAgICAgICAgcHRocmVhZF9jcmVhdGUoJnRocmVhZHNbdGNvdW50XSwgTlVMTCwgcmVhZGVyX2Z1bmMsIGluZm8pOwogICAgICAgICAgICB0Y291bnQrKzsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCB3cml0ZXJzOyBpKyspIHsKICAgICAgICAgICAgVGhyZWFkSW5mbyAqaW5mbyA9IG1hbGxvYyhzaXplb2YoVGhyZWFkSW5mbykpOwogICAgICAgICAgICAqaW5mbyA9IChUaHJlYWRJbmZvKXsudGhyZWFkX25vID0gdGNvdW50ICsgMSwgLmlzX3JlYWRlciA9IDAsIC5pc19yZWFsID0gMSwgLnRlc3RfY2FzZSA9IHR9OwogICAgICAgICAgICBwdGhyZWFkX2NyZWF0ZSgmdGhyZWFkc1t0Y291bnRdLCBOVUxMLCB3cml0ZXJfZnVuYywgaW5mbyk7CiAgICAgICAgICAgIHRjb3VudCsrOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlYWRlcnM7IGkrKykgewogICAgICAgICAgICBUaHJlYWRJbmZvICppbmZvID0gbWFsbG9jKHNpemVvZihUaHJlYWRJbmZvKSk7CiAgICAgICAgICAgICppbmZvID0gKFRocmVhZEluZm8pey50aHJlYWRfbm8gPSB0Y291bnQgKyAxLCAuaXNfcmVhZGVyID0gMSwgLmlzX3JlYWwgPSAwLCAudGVzdF9jYXNlID0gdH07CiAgICAgICAgICAgIHB0aHJlYWRfY3JlYXRlKCZ0aHJlYWRzW3Rjb3VudF0sIE5VTEwsIHJlYWRlcl9mdW5jLCBpbmZvKTsKICAgICAgICAgICAgdGNvdW50Kys7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgd3JpdGVyczsgaSsrKSB7CiAgICAgICAgICAgIFRocmVhZEluZm8gKmluZm8gPSBtYWxsb2Moc2l6ZW9mKFRocmVhZEluZm8pKTsKICAgICAgICAgICAgKmluZm8gPSAoVGhyZWFkSW5mbyl7LnRocmVhZF9ubyA9IHRjb3VudCArIDEsIC5pc19yZWFkZXIgPSAwLCAuaXNfcmVhbCA9IDAsIC50ZXN0X2Nhc2UgPSB0fTsKICAgICAgICAgICAgcHRocmVhZF9jcmVhdGUoJnRocmVhZHNbdGNvdW50XSwgTlVMTCwgd3JpdGVyX2Z1bmMsIGluZm8pOwogICAgICAgICAgICB0Y291bnQrKzsKICAgICAgICB9CiAgICB9CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCB0Y291bnQ7IGkrKykgewogICAgICAgIHB0aHJlYWRfam9pbih0aHJlYWRzW2ldLCBOVUxMKTsKICAgIH0KCiAgICBmb3IgKGludCB0ID0gMDsgdCA8IFRFU1RfQ0FTRVM7IHQrKykgewogICAgICAgIHByaW50X2xvZyh0KTsKICAgIH0KCiAgICByZXR1cm4gMDsKfQ==