#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 40
#define OPS 5
#define TEST_CASES 3
int BUFFER = 0;
sem_t buffer_sem;
sem_t read_count_sem;
sem_t password_sem;
int read_count = 0;
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;
unsigned long hash_val;
} ThreadInfo;
unsigned long hash_pthread_t(pthread_t thread_id) {
return (unsigned long)(uintptr_t)thread_id;
}
void register_thread(unsigned long hash_val) {
sem_wait(&password_sem);
password_table[table_size++] = hash_val;
sem_post(&password_sem);
}
int is_valid_thread(unsigned long hash_val) {
sem_wait(&password_sem);
for (int i = 0; i < table_size; i++) {
if (password_table[i] == hash_val) {
sem_post(&password_sem);
return 1;
}
}
sem_post(&password_sem);
return 0;
}
void log_action(int case_id, int thread_no, unsigned long hash_val, 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_val;
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;
info->hash_val = hash_pthread_t(pthread_self());
if (info->is_real)
register_thread(info->hash_val);
for (int i = 0; i < OPS; i++) {
sleep(1);
if (!is_valid_thread(info->hash_val)) {
log_action(info->test_case, info->thread_no, info->hash_val, 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, info->hash_val, 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;
info->hash_val = hash_pthread_t(pthread_self());
if (info->is_real)
register_thread(info->hash_val);
for (int i = 0; i < OPS; i++) {
sleep(1);
if (!is_valid_thread(info->hash_val)) {
log_action(info->test_case, info->thread_no, info->hash_val, info->is_real, 0, -1);
continue;
}
sem_wait(&buffer_sem);
int val
= rand() % 10000; BUFFER = val;
log_action(info->test_case, info->thread_no, info->hash_val, 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+CiNpbmNsdWRlIDxzdGRpbnQuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgoKI2RlZmluZSBNQVhfVEhSRUFEUyA0MAojZGVmaW5lIE9QUyA1CiNkZWZpbmUgVEVTVF9DQVNFUyAzCgppbnQgQlVGRkVSID0gMDsKCnNlbV90IGJ1ZmZlcl9zZW07CnNlbV90IHJlYWRfY291bnRfc2VtOwpzZW1fdCBwYXNzd29yZF9zZW07CgppbnQgcmVhZF9jb3VudCA9IDA7Cgp1bnNpZ25lZCBsb25nIHBhc3N3b3JkX3RhYmxlW01BWF9USFJFQURTXTsKaW50IHRhYmxlX3NpemUgPSAwOwoKdHlwZWRlZiBzdHJ1Y3QgewogICAgaW50IHRocmVhZF9ubzsKICAgIHVuc2lnbmVkIGxvbmcgaGFzaF92YWw7CiAgICBjaGFyIHZhbGlkaXR5WzhdOwogICAgY2hhciByb2xlWzhdOwogICAgaW50IHZhbHVlOwp9IGxvZ19lbnRyeV90OwoKbG9nX2VudHJ5X3QgbG9nc1tURVNUX0NBU0VTXVs0MF07CmludCBsb2dfcG9zW1RFU1RfQ0FTRVNdID0gezB9OwoKdHlwZWRlZiBzdHJ1Y3QgewogICAgaW50IHRocmVhZF9ubzsKICAgIGludCBpc19yZWFkZXI7CiAgICBpbnQgaXNfcmVhbDsKICAgIGludCB0ZXN0X2Nhc2U7CiAgICB1bnNpZ25lZCBsb25nIGhhc2hfdmFsOwp9IFRocmVhZEluZm87Cgp1bnNpZ25lZCBsb25nIGhhc2hfcHRocmVhZF90KHB0aHJlYWRfdCB0aHJlYWRfaWQpIHsKICAgIHJldHVybiAodW5zaWduZWQgbG9uZykodWludHB0cl90KXRocmVhZF9pZDsKfQoKdm9pZCByZWdpc3Rlcl90aHJlYWQodW5zaWduZWQgbG9uZyBoYXNoX3ZhbCkgewogICAgc2VtX3dhaXQoJnBhc3N3b3JkX3NlbSk7CiAgICBwYXNzd29yZF90YWJsZVt0YWJsZV9zaXplKytdID0gaGFzaF92YWw7CiAgICBzZW1fcG9zdCgmcGFzc3dvcmRfc2VtKTsKfQoKaW50IGlzX3ZhbGlkX3RocmVhZCh1bnNpZ25lZCBsb25nIGhhc2hfdmFsKSB7CiAgICBzZW1fd2FpdCgmcGFzc3dvcmRfc2VtKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgdGFibGVfc2l6ZTsgaSsrKSB7CiAgICAgICAgaWYgKHBhc3N3b3JkX3RhYmxlW2ldID09IGhhc2hfdmFsKSB7CiAgICAgICAgICAgIHNlbV9wb3N0KCZwYXNzd29yZF9zZW0pOwogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICB9CiAgICBzZW1fcG9zdCgmcGFzc3dvcmRfc2VtKTsKICAgIHJldHVybiAwOwp9Cgp2b2lkIGxvZ19hY3Rpb24oaW50IGNhc2VfaWQsIGludCB0aHJlYWRfbm8sIHVuc2lnbmVkIGxvbmcgaGFzaF92YWwsIGludCBpc19yZWFsLCBpbnQgaXNfcmVhZGVyLCBpbnQgdmFsdWUpIHsKICAgIGxvZ19lbnRyeV90ICplbnRyeSA9ICZsb2dzW2Nhc2VfaWRdW2xvZ19wb3NbY2FzZV9pZF0rK107CiAgICBlbnRyeS0+dGhyZWFkX25vID0gdGhyZWFkX25vOwogICAgZW50cnktPmhhc2hfdmFsID0gaGFzaF92YWw7CiAgICBzdHJjcHkoZW50cnktPnZhbGlkaXR5LCBpc19yZWFsID8gInJlYWwiIDogImR1bW15Iik7CiAgICBzdHJjcHkoZW50cnktPnJvbGUsIGlzX3JlYWRlciA/ICJyZWFkZXIiIDogIndyaXRlciIpOwogICAgZW50cnktPnZhbHVlID0gdmFsdWU7Cn0KCnZvaWQgKnJlYWRlcl9mdW5jKHZvaWQgKmFyZykgewogICAgVGhyZWFkSW5mbyAqaW5mbyA9IChUaHJlYWRJbmZvICopYXJnOwogICAgaW5mby0+aGFzaF92YWwgPSBoYXNoX3B0aHJlYWRfdChwdGhyZWFkX3NlbGYoKSk7CiAgICBzcmFuZCh0aW1lKE5VTEwpIF4gaW5mby0+aGFzaF92YWwpOwoKICAgIGlmIChpbmZvLT5pc19yZWFsKQogICAgICAgIHJlZ2lzdGVyX3RocmVhZChpbmZvLT5oYXNoX3ZhbCk7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBPUFM7IGkrKykgewogICAgICAgIHNsZWVwKDEpOwogICAgICAgIGlmICghaXNfdmFsaWRfdGhyZWFkKGluZm8tPmhhc2hfdmFsKSkgewogICAgICAgICAgICBsb2dfYWN0aW9uKGluZm8tPnRlc3RfY2FzZSwgaW5mby0+dGhyZWFkX25vLCBpbmZvLT5oYXNoX3ZhbCwgaW5mby0+aXNfcmVhbCwgMSwgLTEpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHNlbV93YWl0KCZyZWFkX2NvdW50X3NlbSk7CiAgICAgICAgcmVhZF9jb3VudCsrOwogICAgICAgIGlmIChyZWFkX2NvdW50ID09IDEpCiAgICAgICAgICAgIHNlbV93YWl0KCZidWZmZXJfc2VtKTsKICAgICAgICBzZW1fcG9zdCgmcmVhZF9jb3VudF9zZW0pOwoKICAgICAgICBsb2dfYWN0aW9uKGluZm8tPnRlc3RfY2FzZSwgaW5mby0+dGhyZWFkX25vLCBpbmZvLT5oYXNoX3ZhbCwgaW5mby0+aXNfcmVhbCwgMSwgQlVGRkVSKTsKCiAgICAgICAgc2VtX3dhaXQoJnJlYWRfY291bnRfc2VtKTsKICAgICAgICByZWFkX2NvdW50LS07CiAgICAgICAgaWYgKHJlYWRfY291bnQgPT0gMCkKICAgICAgICAgICAgc2VtX3Bvc3QoJmJ1ZmZlcl9zZW0pOwogICAgICAgIHNlbV9wb3N0KCZyZWFkX2NvdW50X3NlbSk7CiAgICB9CgogICAgZnJlZShpbmZvKTsKICAgIHJldHVybiBOVUxMOwp9Cgp2b2lkICp3cml0ZXJfZnVuYyh2b2lkICphcmcpIHsKICAgIFRocmVhZEluZm8gKmluZm8gPSAoVGhyZWFkSW5mbyAqKWFyZzsKICAgIGluZm8tPmhhc2hfdmFsID0gaGFzaF9wdGhyZWFkX3QocHRocmVhZF9zZWxmKCkpOwogICAgc3JhbmQodGltZShOVUxMKSBeIGluZm8tPmhhc2hfdmFsKTsKCiAgICBpZiAoaW5mby0+aXNfcmVhbCkKICAgICAgICByZWdpc3Rlcl90aHJlYWQoaW5mby0+aGFzaF92YWwpOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgT1BTOyBpKyspIHsKICAgICAgICBzbGVlcCgxKTsKICAgICAgICBpZiAoIWlzX3ZhbGlkX3RocmVhZChpbmZvLT5oYXNoX3ZhbCkpIHsKICAgICAgICAgICAgbG9nX2FjdGlvbihpbmZvLT50ZXN0X2Nhc2UsIGluZm8tPnRocmVhZF9ubywgaW5mby0+aGFzaF92YWwsIGluZm8tPmlzX3JlYWwsIDAsIC0xKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICBzZW1fd2FpdCgmYnVmZmVyX3NlbSk7CiAgICAgICAgaW50IHZhbCA9IHJhbmQoKSAlIDEwMDAwOwogICAgICAgIEJVRkZFUiA9IHZhbDsKICAgICAgICBsb2dfYWN0aW9uKGluZm8tPnRlc3RfY2FzZSwgaW5mby0+dGhyZWFkX25vLCBpbmZvLT5oYXNoX3ZhbCwgaW5mby0+aXNfcmVhbCwgMCwgdmFsKTsKICAgICAgICBzZW1fcG9zdCgmYnVmZmVyX3NlbSk7CiAgICB9CgogICAgZnJlZShpbmZvKTsKICAgIHJldHVybiBOVUxMOwp9Cgp2b2lkIHByaW50X2xvZyhpbnQgY2FzZV9pZCkgewogICAgcHJpbnRmKCI9PT09PSBUZXN0IENhc2UgJWQgPT09PT1cbiIsIGNhc2VfaWQgKyAxKTsKICAgIHByaW50ZigiVGhyZWFkX05vIHwgSGFzaF9WYWx1ZSAgICAgICB8IFZhbGlkaXR5IHwgUm9sZSAgIHwgVmFsdWVcbiIpOwogICAgcHJpbnRmKCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IGxvZ19wb3NbY2FzZV9pZF07IGkrKykgewogICAgICAgIHByaW50ZigiJTlkIHwgJTAxNmx4IHwgJTdzICB8ICU2cyB8ICU1ZFxuIiwKICAgICAgICAgICAgICAgbG9nc1tjYXNlX2lkXVtpXS50aHJlYWRfbm8sCiAgICAgICAgICAgICAgIGxvZ3NbY2FzZV9pZF1baV0uaGFzaF92YWwsCiAgICAgICAgICAgICAgIGxvZ3NbY2FzZV9pZF1baV0udmFsaWRpdHksCiAgICAgICAgICAgICAgIGxvZ3NbY2FzZV9pZF1baV0ucm9sZSwKICAgICAgICAgICAgICAgbG9nc1tjYXNlX2lkXVtpXS52YWx1ZSk7CiAgICB9CiAgICBwcmludGYoIlxuIik7Cn0KCmludCBtYWluKCkgewogICAgc3JhbmQodGltZShOVUxMKSk7CgogICAgc2VtX2luaXQoJmJ1ZmZlcl9zZW0sIDAsIDEpOwogICAgc2VtX2luaXQoJnJlYWRfY291bnRfc2VtLCAwLCAxKTsKICAgIHNlbV9pbml0KCZwYXNzd29yZF9zZW0sIDAsIDEpOwoKICAgIGludCB0ZXN0X2Nhc2VzWzNdWzJdID0ge3syLCAyfSwgezMsIDF9LCB7MSwgNH19OwogICAgcHRocmVhZF90IHRocmVhZHNbNDBdOwogICAgaW50IHRjb3VudCA9IDA7CgogICAgZm9yIChpbnQgdCA9IDA7IHQgPCBURVNUX0NBU0VTOyB0KyspIHsKICAgICAgICBpbnQgcmVhZGVycyA9IHRlc3RfY2FzZXNbdF1bMF07CiAgICAgICAgaW50IHdyaXRlcnMgPSB0ZXN0X2Nhc2VzW3RdWzFdOwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHJlYWRlcnM7IGkrKykgewogICAgICAgICAgICBUaHJlYWRJbmZvICppbmZvID0gbWFsbG9jKHNpemVvZihUaHJlYWRJbmZvKSk7CiAgICAgICAgICAgICppbmZvID0gKFRocmVhZEluZm8pey50aHJlYWRfbm8gPSB0Y291bnQgKyAxLCAuaXNfcmVhZGVyID0gMSwgLmlzX3JlYWwgPSAxLCAudGVzdF9jYXNlID0gdH07CiAgICAgICAgICAgIHB0aHJlYWRfY3JlYXRlKCZ0aHJlYWRzW3Rjb3VudF0sIE5VTEwsIHJlYWRlcl9mdW5jLCBpbmZvKTsKICAgICAgICAgICAgdGNvdW50Kys7CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgd3JpdGVyczsgaSsrKSB7CiAgICAgICAgICAgIFRocmVhZEluZm8gKmluZm8gPSBtYWxsb2Moc2l6ZW9mKFRocmVhZEluZm8pKTsKICAgICAgICAgICAgKmluZm8gPSAoVGhyZWFkSW5mbyl7LnRocmVhZF9ubyA9IHRjb3VudCArIDEsIC5pc19yZWFkZXIgPSAwLCAuaXNfcmVhbCA9IDEsIC50ZXN0X2Nhc2UgPSB0fTsKICAgICAgICAgICAgcHRocmVhZF9jcmVhdGUoJnRocmVhZHNbdGNvdW50XSwgTlVMTCwgd3JpdGVyX2Z1bmMsIGluZm8pOwogICAgICAgICAgICB0Y291bnQrKzsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByZWFkZXJzOyBpKyspIHsKICAgICAgICAgICAgVGhyZWFkSW5mbyAqaW5mbyA9IG1hbGxvYyhzaXplb2YoVGhyZWFkSW5mbykpOwogICAgICAgICAgICAqaW5mbyA9IChUaHJlYWRJbmZvKXsudGhyZWFkX25vID0gdGNvdW50ICsgMSwgLmlzX3JlYWRlciA9IDEsIC5pc19yZWFsID0gMCwgLnRlc3RfY2FzZSA9IHR9OwogICAgICAgICAgICBwdGhyZWFkX2NyZWF0ZSgmdGhyZWFkc1t0Y291bnRdLCBOVUxMLCByZWFkZXJfZnVuYywgaW5mbyk7CiAgICAgICAgICAgIHRjb3VudCsrOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHdyaXRlcnM7IGkrKykgewogICAgICAgICAgICBUaHJlYWRJbmZvICppbmZvID0gbWFsbG9jKHNpemVvZihUaHJlYWRJbmZvKSk7CiAgICAgICAgICAgICppbmZvID0gKFRocmVhZEluZm8pey50aHJlYWRfbm8gPSB0Y291bnQgKyAxLCAuaXNfcmVhZGVyID0gMCwgLmlzX3JlYWwgPSAwLCAudGVzdF9jYXNlID0gdH07CiAgICAgICAgICAgIHB0aHJlYWRfY3JlYXRlKCZ0aHJlYWRzW3Rjb3VudF0sIE5VTEwsIHdyaXRlcl9mdW5jLCBpbmZvKTsKICAgICAgICAgICAgdGNvdW50Kys7CiAgICAgICAgfQogICAgfQoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgdGNvdW50OyBpKyspIHsKICAgICAgICBwdGhyZWFkX2pvaW4odGhyZWFkc1tpXSwgTlVMTCk7CiAgICB9CgogICAgZm9yIChpbnQgdCA9IDA7IHQgPCBURVNUX0NBU0VTOyB0KyspIHsKICAgICAgICBwcmludF9sb2codCk7CiAgICB9CgogICAgcmV0dXJuIDA7Cn0K