This commit is contained in:
2026-05-14 09:27:48 +08:00
parent 1100043d73
commit f8ae30583d
17 changed files with 1007 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <unistd.h>
#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 consumed_count = 0;
int total_items;
sem_t count_mutex;
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) {
/* Put poison back for other consumers, then exit */
sbuf_insert(ca->sp, POISON);
break;
}
sem_wait(&sum_mutex);
consumed_sum += item;
sem_post(&sum_mutex);
sem_wait(&count_mutex);
consumed_count++;
sem_post(&count_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 <k_producers> <items_per_producer> <m_consumers> <N_buffer>\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);
sem_init(&count_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]);
}
/* Wait for all producers to finish */
for (int i = 0; i < k; i++) {
pthread_join(producers[i], NULL);
}
/* Insert one poison pill to start the termination chain */
sbuf_insert(&buf, POISON);
/* Wait for all consumers to finish */
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);
sem_destroy(&count_mutex);
return 0;
}