#include #include #include #include #include #define POISON -1 typedef struct { int *buf; int n; int outpos; int inpos; sem_t mutex; sem_t slots; sem_t items; } sbuf_t; long long produced_sum = 0; long long consumed_sum = 0; sem_t sum_mutex; int total_items; void sbuf_init(sbuf_t *sp, int n) { sp->buf = (int *)malloc(n * sizeof(int)); sp->n = n; sp->outpos = 0; sp->inpos = 0; sem_init(&sp->mutex, 0, 1); sem_init(&sp->slots, 0, n); sem_init(&sp->items, 0, 0); } void sbuf_deinit(sbuf_t *sp) { free(sp->buf); sem_destroy(&sp->mutex); sem_destroy(&sp->slots); sem_destroy(&sp->items); } void sbuf_insert(sbuf_t *sp, int item) { sem_wait(&sp->slots); sem_wait(&sp->mutex); sp->buf[sp->inpos] = item; sp->inpos = (sp->inpos + 1) % sp->n; sem_post(&sp->mutex); sem_post(&sp->items); } int sbuf_remove(sbuf_t *sp) { sem_wait(&sp->items); sem_wait(&sp->mutex); int item = sp->buf[sp->outpos]; sp->outpos = (sp->outpos + 1) % sp->n; sem_post(&sp->mutex); sem_post(&sp->slots); return item; } typedef struct { sbuf_t *sp; int num_items; int id; } producer_arg_t; typedef struct { sbuf_t *sp; int id; } consumer_arg_t; void *producer(void *arg) { producer_arg_t *pa = (producer_arg_t *)arg; for (int i = 0; i < pa->num_items; i++) { int val = rand() % 1000; sbuf_insert(pa->sp, val); sem_wait(&sum_mutex); produced_sum += val; sem_post(&sum_mutex); printf("[Producer %d] produced %d\n", pa->id, val); } return NULL; } void *consumer(void *arg) { consumer_arg_t *ca = (consumer_arg_t *)arg; while (1) { int item = sbuf_remove(ca->sp); if (item == POISON) { sbuf_insert(ca->sp, POISON); break; } sem_wait(&sum_mutex); consumed_sum += item; sem_post(&sum_mutex); printf("[Consumer %d] consumed %d\n", ca->id, item); } return NULL; } int main(int argc, char *argv[]) { if (argc != 5) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } int k = atoi(argv[1]); int items_per_producer = atoi(argv[2]); int m = atoi(argv[3]); int N = atoi(argv[4]); total_items = k * items_per_producer; srand(time(NULL)); sem_init(&sum_mutex, 0, 1); sbuf_t buf; sbuf_init(&buf, N); pthread_t *producers = malloc(k * sizeof(pthread_t)); pthread_t *consumers = malloc(m * sizeof(pthread_t)); producer_arg_t *pargs = malloc(k * sizeof(producer_arg_t)); consumer_arg_t *cargs = malloc(m * sizeof(consumer_arg_t)); for (int i = 0; i < k; i++) { pargs[i].sp = &buf; pargs[i].num_items = items_per_producer; pargs[i].id = i + 1; pthread_create(&producers[i], NULL, producer, &pargs[i]); } for (int i = 0; i < m; i++) { cargs[i].sp = &buf; cargs[i].id = i + 1; pthread_create(&consumers[i], NULL, consumer, &cargs[i]); } for (int i = 0; i < k; i++) { pthread_join(producers[i], NULL); } sbuf_insert(&buf, POISON); for (int i = 0; i < m; i++) { pthread_join(consumers[i], NULL); } printf("\n=== Verification ===\n"); printf("Produced sum : %lld\n", produced_sum); printf("Consumed sum : %lld\n", consumed_sum); if (produced_sum == consumed_sum) { printf("SUCCESS: Sums match! Program is correct.\n"); } else { printf("ERROR: Sum mismatch! Difference = %lld\n", produced_sum - consumed_sum); } free(producers); free(consumers); free(pargs); free(cargs); sbuf_deinit(&buf); sem_destroy(&sum_mutex); return 0; }