Producer Consumer Multi Threading
Producer Consumer Multi Threading
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sched.h>
#define SUMSIZE 1861
#define BUFSIZE 8
#define SPIN 1000000
int sum = 0;
pthread_cond_t slots = PTHREAD_COND_INITIALIZER;
pthread_cond_t items = PTHREAD_COND_INITIALIZER;
pthread_mutex_t slot_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t item_lock = PTHREAD_MUTEX_INITIALIZER;
int nslots = BUFSIZE;
int producer_done = 0;
int nitems = 0;
int totalproduced = 0;
int producer_shutdown = 0;
void spinit(void)
{
int i;
for (i = 0; i < SPIN; i++) ;
}
sigemptyset(&intmask);
sigaddset(&intmask, SIGUSR1);
sigwait(&intmask,&sig);
fprintf(stderr, "sigusr1_thread returned from sigwait\n");
pthread_mutex_lock(&slot_lock);
producer_shutdown = 1;
pthread_cond_broadcast(&slots);
pthread_mutex_unlock(&slot_lock);
return NULL;
}
for (i = 1; ; i++) {
spinit();
pthread_mutex_lock(&slot_lock); /* acquire right to a slot */
while ((nslots <= 0) && (!producer_shutdown))
pthread_cond_wait (&slots, &slot_lock);
if (producer_shutdown) {
pthread_mutex_unlock(&slot_lock);
break;
}
nslots--;
pthread_mutex_unlock(&slot_lock);
spinit();
put_item(i*i);
pthread_mutex_lock(&item_lock); /* release right to an item */
nitems++;
pthread_cond_signal(&items);
pthread_mutex_unlock(&item_lock);
spinit();
totalproduced = i;
}
pthread_mutex_lock(&item_lock);
producer_done = 1;
pthread_cond_broadcast(&items);
pthread_mutex_unlock(&item_lock);
return NULL;
}
for ( ; ; ) {
pthread_mutex_lock(&item_lock); /* acquire right to an item */
while ((nitems <=0) && !producer_done)
pthread_cond_wait(&items, &item_lock);
if ((nitems <= 0) && producer_done) {
pthread_mutex_unlock(&item_lock);
break;
}
nitems--;
pthread_mutex_unlock(&item_lock);
get_item(&myitem);
sum += myitem;
pthread_mutex_lock(&slot_lock); /* release right to a slot */
nslots++;
pthread_cond_signal(&slots);
pthread_mutex_unlock(&slot_lock);
}
return NULL;
}
void main(void)
{
pthread_t prodtid;
pthread_t constid;
pthread_t sighandid;
double total;
double tp;
sigset_t set;
pthread_attr_t high_prio_attr;
struct sched_param param;
fprintf(stderr, "Process ID is %ld\n", (long)getpid());
/* block the signal */
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
fprintf(stderr, "Signal blocked\n");
/* create threads */
pthread_attr_init(&high_prio_attr);
pthread_attr_getschedparam(&high_prio_attr, ¶m);
param.sched_priority++;
pthread_attr_setschedparam(&high_prio_attr, ¶m);
pthread_create(&sighandid, &high_prio_attr, sigusr1_thread, NULL);
pthread_create(&prodtid, NULL, producer, NULL);
pthread_create(&constid, NULL, consumer, NULL);
/* wait for the threads to finish */
pthread_join(prodtid, NULL);
pthread_join(constid, NULL);
printf("The threads produced the sum %d\n", sum);
/* show correct value */
tp = (double) totalproduced;
total = tp*(tp + 1)*(2*tp + 1)/6.0;
if (tp > SUMSIZE)
fprintf(stderr, "*** Overflow occurs for more than %d items\n",
SUMSIZE);
printf("The checksum for %4d items is %1.0f\n",
totalproduced, total);
exit(0);
}