Multiple producer & consumer using 3 sempahores - c

With the given shared buffer of size 24,
Here is the below solution, for single producer & consumer using counting semaphore,
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFERSIZE 24
void *producer(void *);
void *consumer(void *);
sem_t mutex; //Controls buffer access
sem_t fullBuffer; //Prevents underflow
sem_t emptyBuffer; // Prevents overflow
char buf[BUFFERSIZE] = {0}; //Shared resource
int main(int argc, char *argv[])
{
pthread_t thread1, thread2;
sem_init(&mutex, 0, 1);
sem_init(&fullBuffer, 0, 0);
sem_init(&emptyBuffer, 0, BUFFERSIZE);
int ret1, ret2;
ret1 = pthread_create(&thread1, NULL, producer, (void *)0);
ret2 = pthread_create(&thread2, NULL, consumer, (void *)0);
printf("Main function after pthread create\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
sem_destroy(&mutex);
sem_destroy(&fullBuffer);
sem_destroy(&emptyBuffer);
return 0;
}
void *producer(void *index)
{
int * startIndex = index;
int currentProduceIndex = *startIndex;
while(1) {
sem_wait(&emptyBuffer); // Prevents overflow, when value is 0
sem_wait(&mutex); // Controls buffer access
buf[currentProduceIndex] = currentProduceIndex;
sem_post(&mutex);
sem_post(&fullBuffer);
currentProduceIndex = (currentProduceIndex+1) % BUFFERSIZE;
}
}
void *consumer(void *index)
{
int *startIndex = index;
int currentConsumeIndex = *startIndex;
while(1) {
sem_wait(&fullBuffer); // Prevents underflow, when value is 0
sem_wait(&mutex);
printf("Consumed %d: ", buf[currentConsumeIndex]);
sem_post(&mutex);
sem_post(&emptyBuffer);
currentConsumeIndex = (currentConsumeIndex+1) % BUFFERSIZE;
}
}
Above code has single producer and consumer on buf, using 3 semaphores mutex, fullBuffer & emptyBuffer.
To add further, Does 3 semaphore, mutex, fullBuffer & emptyBuffer suffice to introduce multiple producers and consumers to access buf, in the above code?

As seibie pointed out, it is hard to implement using semaphores. I have modified code and used two mutex and two cond variables. You can create multiple producer and consumer threads and it should work fine.
#include <stdio.h>
#include <pthread.h>
#define BUFFERSIZE 24
void *producer(void *);
void *consumer(void *);
pthread_mutex_t consMutex;
pthread_mutex_t prodMutex;
pthread_cond_t consCond;
pthread_cond_t prodCond;
// Shared resource: Using it to store flags.
// If value at index is 0, it means the index is free
// and producer can write data. If it is 1, it means
// that index is filled, consumer can consume it.
// You need use separate array for actual data.
char buf[BUFFERSIZE] = {0};
int main(void)
{
pthread_t thread1, thread2;
pthread_mutex_init(&consMutex, NULL);
pthread_mutex_init(&prodMutex, NULL);
pthread_cond_init(&consCond, NULL);
pthread_cond_init(&prodCond, NULL);
int ret1, ret2;
int prodIndex = 0;
int consIndex = 0;
ret1 = pthread_create(&thread1, NULL, producer, (void *)&prodIndex);
ret2 = pthread_create(&thread2, NULL, consumer, (void *)&consIndex);
printf("Main function after pthread create\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&prodMutex);
pthread_mutex_destroy(&consMutex);
pthread_cond_destroy(&prodCond);
pthread_cond_destroy(&consCond);
return 0;
}
void *producer(void *index)
{
int *currentProduceIndex = index;
while(1) {
pthread_mutex_lock(&prodMutex);
/* Check if current index is free to fill. */
while(1 == buf[*currentProduceIndex])
{
/* If index is not free, wait for consumer to consume. */
pthread_cond_wait(&prodCond, &prodMutex);
}
/* Now the current index is free. Fill it. */
buf[*currentProduceIndex] = 1;
/* Update the producer index. */
*currentProduceIndex = (*currentProduceIndex+1)%BUFFERSIZE;
pthread_mutex_unlock(&prodMutex);
/* Notify consumer that an item has been produced. */
pthread_mutex_lock(&consMutex);
pthread_cond_signal(&consCond);
pthread_mutex_unlock(&consMutex);
}
return NULL;
}
void *consumer(void *index)
{
int *currentConsumeIndex = index;
while(1) {
pthread_mutex_lock(&consMutex);
/* Check if current index is empty. */
while(0 == buf[*currentConsumeIndex])
{
/* If index is empty, wait for producer to produce. */
pthread_cond_wait(&consCond, &consMutex);
}
/* Index is filled, consume it. */
buf[*currentConsumeIndex] = 0;
/* Update the consumer index. */
*currentConsumeIndex = (*currentConsumeIndex+1)%BUFFERSIZE;
pthread_mutex_unlock(&consMutex);
/* Notify producer that an item has been consumed. */
pthread_mutex_lock(&prodMutex);
pthread_cond_signal(&prodCond);
pthread_mutex_unlock(&prodMutex);
}
return NULL;
}

Related

C pthreads threads not executing functions for producer-consumer problem

Hi I am trying to implement an solution to producer consumer problem with threads and semaphores.
I have the two functions that the threads consumer and producer will call but they aren't executing. I am not sure what I am doing wrong as I am not getting any errors, my program is just not executing the thread functions. I am creating and joining the thread, I am not sure what is causing the issue
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <errno.h>
#include "buffer.h"
struct bufferStruct *item; //calls buffer structure from buffer.h
pthread_mutex_t mutex; //lock for synchronizing execution of threads(producer and consumer)
sem_t empty; //indicates buffer is empty
sem_t full; //indicates buffer is full
int input = 0;
int newitem;
pthread_attr_t attr;
void *producer(void *param)
{
for(int i = 0; i < 5; i++)
{
sem_wait(&empty);
pthread_mutex_lock(&mutex);
newitem = rand();
item->content[item->in] = newitem;
printf("Producer prouced item %d at position %d in buffer\n", newitem, item->in);
item->in = (item->in+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
sleep(1);
}
}
void *consumer(void * param)
{
for(int i =0; i< 5; i++)
{
sem_wait(&full);
pthread_mutex_lock(&mutex);
newitem = item->content[item->out];
printf("Consumer has consumed item %d at position %d in buffer\n", newitem, item->out);
item->out = (item->out+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
sleep(1);
}
}
int main()
{
int initval = 1;
int initval2 = 2;
sem_init(&full, 1, 0);
sem_init(&empty, 1, MAX_SIZE);
if(pthread_mutex_init(&mutex,NULL)!=0){
printf("Mutex init failed\n");
return 1;
}
pthread_attr_init(&attr);
pthread_t thread_produce, thread_consume;
printf("Starting threads...\n");
pthread_create(&thread_produce, &attr, producer, (void*)&(initval));
pthread_create(&thread_consume, &attr, consumer, (void*)&(initval2));
pthread_join(thread_produce, NULL);
pthread_join(thread_consume, NULL);
printf("Threads done executing...\n");
pthread_mutex_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
exit(0);
}
You declare
struct bufferStruct *item;
then you use item without ever assigning it to point to anything. Undefined behavior results.
If I fix that (first synthesizing a version struct bufferStruct and choosing a MAX_SIZE) then the program compiles without error and seems to run successfully.

Producer-Consumer solution runs but doesn't print

This is my current code for the Producer-Consumer problem. I compiled it and ran it but nothing is printed. The command line takes in 3 arguments: Sleep time, producer threads, consumer threads. I've tried setting the values as 5, 1, 1 respectively, the sleep timer works but I'm unsure about the rest.
Code for buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
Code for buffer.c:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"
buffer_item buffer[BUFFER_SIZE];
void *producer(void *param);
void *consumer(void *param);
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int insert_item(buffer_item item)
{
do
{
wait(empty);
wait(mutex);
signal(mutex);
signal(full);
}while(1);
return 0;
}
int remove_item(buffer_item *item)
{
do
{
wait(full);
wait(mutex);
signal(mutex);
signal(empty);
}while(1);
return 0;
}
int main(int argc, char *argv[])
{
int sleepTime;
int producerThreads;
int consumerThreads;
int counter_1;
int counter_2;
if(argc != 4)
{
return -1;
}
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
srand((unsigned)time(NULL));
for(counter_1 = 0; counter_1 < producerThreads; counter_1++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, producer, NULL);
}
for(counter_2 = 0; counter_2 < consumerThreads; counter_2++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, consumer, NULL);
}
sleep(sleepTime);
return 0;
}
void *producer(void *param)
{
buffer_item item;
int randomTime;
int counter_1 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
item = rand();
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Producer ID: %lu, Produced Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_1);
++counter_1;
}
}
}
void *consumer(void *param)
{
buffer_item item;
int randomTime;
int counter_2 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Consumer ID: %lu, Consumed Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_2);
++counter_2;
}
}
}
So far I've tried declaring the tid separately, skipping sleep and join the threads, but it still doesn't print.
Your code can't possibly run, indeed it doesn't even compile.
Here's a list of issues that need to be addressed:
wait should be sem_wait
signal should be sem_post for semaphores
int sem_wait(sem_t *sem); and int sem_post(sem_t *sem); take the pointer to a semaphore
sem_wait(mutex) and sem_post(mutex) give something like "incompatible type for argument 1 of sem_wait", I guess you want to acquire and release the lock on the mutex like pthread_mutex_lock(&mutex) and pthread_mutex_unlock(&mutex)
in the consumer if(insert_item(item)): item is used uninitialized
still in the consumer you use insert_item instead of remove_item
Coming to the main question "I compiled it and ran it but nothing is printed", it doesn't print anything because producer and consumer call, respectively, insert_item and remove_item and are trapped inside infinite loops (e.g. while(1))

Semaphores - Consumer Producer weird result

I recently learned Semaphore and Consumer Producer problem in class and encountered this question:
I used two semaphores to indicate the empty and the full in a buffer plus a mutex.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int fill =0 ;
void *producer(void *param);
void *consumer(void *param);
void* producer(void *param)
{
while(1) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
fill++;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void *consumer(void *param)
{
while(1){
sem_wait(&full);
pthread_mutex_lock(&mutex);
fill--;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
void* dynamic_output(void* ptr){
while(1){
printf("fill = :%d\n",fill);
sleep(1);
}}
int main()
{
pthread_mutex_init(&mutex, NULL);
sem_init(&empty, 0, 5);
sem_init(&full, 0, 0);
pthread_t gid1,oid1;
pthread_t dy;
pthread_create(&dy,NULL,dynamic_output,NULL);
pthread_create(&gid1,NULL,&producer,NULL);
pthread_create(&oid1,NULL,&consumer,NULL);
pthread_join(gid1,NULL);
pthread_join(oid1,NULL);
return 0;
}
here I simply put a variable named 'fill' inside the producer and the consumer. Since I initiated the empty semaphore to 5, I expected 'fill' will be floating between 0 - 5 but when I printed them out I found the weird result:
fill = :0
fill = :19
fill = :446
fill = :112
fill = :156
fill = :-564
fill = :-345
fill = :-744
fill = :-1293
I really don't understand how fill could've become a negative number or number bigger than 5. I thought implementing the semaphores could ensure that the bounded buffer( here I didn't really have a buffer).
Thanks in advance.

consumer producer code undeclared errors linux debug

Trying to compile my code in linux by doing gcc -o consumer.c -lpthread -lm and I am getting compile errors about having undeclared for things I, to the best of my knowledge, have declared. Most of the undeclared seem to be related to buffers, of which this is my first program using buffers. Here are the errors (edited to reflect changes)
typedef char buffer_item buffer[BUFFER_SIZE]; // asm or __attribute__ before "buffer"
both of these(expected ')' before 'item'
int insert_item(buffer_item item)
int insert_item(buffer_item item)
int remove_item(buffer_item *item) //expected ')' before * token
and here is my full code after the changes
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define RAND_DIVISOR 100000000
#define TRUE 1
#define BUFFER_SIZE 1000
pthread_mutex_t mutex; //mutex lock
sem_t full, empty; //semaphores
typedef char buffer_item buffer[BUFFER_SIZE];
int counter; //buffer counter
pthread_t tid1, tid2; //Thread ID
pthread_attr_t attr; // thread attributes
void *producer(void *param); // producer thread
void *consumer(void *param); //consumer thread
void initializeData() {
pthread_mutex_init(&mutex, NULL); //Create mutex lock
sem_init(&full, 0, 0); // Create the full semaphore and initialize to 0
sem_init(&empty, 0, BUFFER_SIZE); // Create the empty semaphore and initialize to BUFFER_SIZE
pthread_attr_init(&attr); //default attributes
counter = 0;
}
// Producer Thread
int insert_item(buffer_item item)
void *producer(void *param) {
while(TRUE) {
// random sleep time
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&empty); //get empty lock
pthread_mutex_lock(&mutex); //get mutex lock
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
}
else {
printf("producer produced %d\n", item);
}
pthread_mutex_unlock(&mutex); //release mutex lock
sem_post(&full); //signal full
}
}
// Consumer Thread
void *consumer(void *param) {
while(TRUE) {
int rNum = rand() / RAND_DIVISOR; // sleep for a random period of time
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&full);// aquire the full lock */
pthread_mutex_lock(&mutex);// aquire the mutex lock
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
}
else {
printf("consumer consumed %d\n", item);
}
pthread_mutex_unlock(&mutex);// release mutex lock
sem_post(&empty); //signal empty
}
}
int insert_item(buffer_item item)
{
// add item as long as buffer isn't full
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1; //buffer full error
}
}
// Remove an item from the buffer
int remove_item(buffer_item *item)// remove item and decrement counter when buffer not empty
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else { //buffer empty error
}
return -1;
}
int main(int argc, char *argv[]) {
int i; //loop counter
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); // sleep time in seconds
int numProd = atoi(argv[2]); // producer threads
int numCons = atoi(argv[3]); // consumer threads
initializeData(); //initialize app
for(i = 0; i < numProd; i++) {
pthread_create(&tid1,&attr,producer,NULL);
}
for(i = 0; i < numCons; i++) {
pthread_create(&tid2,&attr,consumer,NULL);
}
// sleep in milliseconds
//sleep(mainSleepTime);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("Program Exiting\n");
exit(0);
}
Edit: latest code and screenshot of errors http://tinypic.com/r/xptzww/9
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define RAND_DIVISOR 100000000
#define TRUE 1
#define BUFFER_SIZE 1000
pthread_mutex_t mutex; //mutex lock
sem_t full, empty; //semaphores
typedef char buffer_item;
int counter; //buffer counter
pthread_t tid1, tid2; //Thread ID
pthread_attr_t attr; // thread attributes
void *producer(void *param); // producer thread
void *consumer(void *param); //consumer thread
void initializeData() {
pthread_mutex_init(&mutex, NULL); //Create mutex lock
sem_init(&full, 0, 0); // Create the full semaphore and initialize to 0
sem_init(&empty, 0, BUFFER_SIZE); // Create the empty semaphore and initialize to BUFFER_SIZE
pthread_attr_init(&attr); //default attributes
counter = 0;
}
// Producer Thread
int insert_item(buffer_item item)
void *producer(void *param) {
while(TRUE) {
// random sleep time
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&empty); //get empty lock
pthread_mutex_lock(&mutex); //get mutex lock
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
}
else {
printf("producer produced %d\n", item);
}
pthread_mutex_unlock(&mutex); //release mutex lock
sem_post(&full); //signal full
}
}
// Consumer Thread
void *consumer(void *param) {
while(TRUE) {
int rNum = rand() / RAND_DIVISOR; // sleep for a random period of time
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&full);// aquire the full lock */
pthread_mutex_lock(&mutex);// aquire the mutex lock
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
}
else {
printf("consumer consumed %d\n", item);
}
pthread_mutex_unlock(&mutex);// release mutex lock
sem_post(&empty); //signal empty
}
}
int insert_item(buffer_item item){// add item as long as buffer isn't full
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1; //buffer full error
}
}
// Remove an item from the buffer
int remove_item(buffer_item *item)// remove item and decrement counter when buffer not empty
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else { //buffer empty error
}
return -1;
}
int main(int argc, char *argv[]) {
int i; //loop counter
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); // sleep time in seconds
int numProd = atoi(argv[2]); // producer threads
int numCons = atoi(argv[3]); // consumer threads
initializeData(); //initialize app
for(i = 0; i < numProd; i++) {
pthread_create(&tid1,&attr,producer,NULL);
}
for(i = 0; i < numCons; i++) {
pthread_create(&tid2,&attr,consumer,NULL);
}
// sleep in milliseconds
//sleep(mainSleepTime);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("Program Exiting\n");
exit(0);
}
You have declared but not defined BUFFER_SIZE.
Instead
char BUFFER_SIZE;
try
char BUFFER_SIZE = some_value;
where some_value should be anything between 1-255
Line:
char buffer_item buffer[BUFFER_SIZE];
should be:
char buffer_item[BUFFER_SIZE];
A variable declaration should look like:
<type name> <variable name>;
There is no standard type buffer_item. If you want to use custom type name it can be defined:
typedef char buffer_item;
I assume that you wanted to use char for that type, since item should keep numbers from 0 to 99 and the char type is enough for that.
After that line the name buffer_item is alias for char. So variables can be declared as buffer_item buffer[BUFFER_SIZE]; or buffer_item item;.
In that case lines like char buffer_item; are redundant. Also you do not need to write char before buffer_item, since buffer_item is already another name for char, so char buffer_item; is the same as char char; that does not make any sense.
Probably that the unknow symbol BUFFER_SIZE should defined as you define #define RAND_DIVISOR 100000000. Typically capital letters in names in C are used for macro definitions. So, you may want to set that size on the top of your file, for example:
#define BUFFER_SIZE 1000
In that case the line char BUFFER_SIZE; is not needed anymore.
You use function insert_item before its declaration. So, to compile that you may put forward declaration also on top before producer():
int insert_item(buffer_item item);
That should be enough to compile the code.
Updated for new errors
Type declaration uses special keyword typedef to create type alias. Here to declare that buffer_item name is used as a type name and it is the same as char it should be exactly:
typedef char buffer_item;
The buffer array should be defined below as:
buffer_item buffer[BUFFER_SIZE];
Forward function declaration requires semicolon at the end:
int insert_item(buffer_item item);
I'm not sure that it will work as expected, but now it should be compiled.

Producer and consumer code don't appear on screen

I have the following code but the producer and consumer code don't appear. It just prints "Exit the program". It's like the consumer and producer functions are never executed. I don't understand why this is happening. Can anyone explain why?
The code is as follows:
/* buffer.h */
typedef int buffer_item;
#define BUFFER_SIZE 18
/* main.c */
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
/* #include "buffer.h" */
#define RAND_DIVISOR 100000000
#define TRUE 1
/* The mutex lock */
pthread_mutex_t mutex;
/* the semaphores */
sem_t full, empty;
/* the buffer */
buffer_item buffer[BUFFER_SIZE];
/* buffer counter */
int counter;
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
void *producer(void *param); /* the producer thread */
void *consumer(void *param); /* the consumer thread */
void initializeData()
{
/* Create the mutex lock */
pthread_mutex_init(&mutex, NULL);
/* Create the full semaphore and initialize to 0 */
sem_init(&full, 0, 0);
/* Create the empty semaphore and initialize to BUFFER_SIZE */
sem_init(&empty, 0, BUFFER_SIZE);
/* Get the default attributes */
pthread_attr_init(&attr);
/* init buffer */
counter = 0;
}
/* Producer Thread */
void *producer(void *param)
{
buffer_item item;
while(TRUE)
{
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
/* generate a random number */
item = rand();
/* acquire the empty lock */
sem_wait(&empty);
/* acquire the mutex lock */
pthread_mutex_lock(&mutex);
if (insert_item(item))
fprintf(stderr, " Producer report error condition\n");
else
printf("producer produced %d\n", item);
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal full */
sem_post(&full);
}
}
/* Consumer Thread */
void *consumer(void *param)
{
buffer_item item;
while(TRUE) {
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
/* aquire the full lock */
sem_wait(&full);
/* aquire the mutex lock */
pthread_mutex_lock(&mutex);
if (remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
} else {
printf("consumer consumed %d\n", item);
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal empty */
sem_post(&empty);
}
}
/* Add an item to the buffer */
int insert_item(buffer_item item)
{
/* When the buffer is not full add the item
and increment the counter*/
if (counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
} else { /* Error the buffer is full */
return -1;
}
}
/* Remove an item from the buffer */
int remove_item(buffer_item *item)
{
/* When the buffer is not empty remove the item
and decrement the counter */
if (counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
} else { /* Error buffer empty */
return -1;
}
}
int main(int argc, char *argv[])
{
/* Loop counter */
int i;
/* Verify the correct number of arguments were passed in */
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */
int numProd = atoi(argv[2]); /* Number of producer threads */
int numCons = atoi(argv[3]); /* Number of consumer threads */
/* Initialize the app */
initializeData();
/* Create the producer threads */
for(i = 0; i < numProd; i++) {
/* Create the thread */
pthread_create(&tid,&attr,producer,NULL);
}
/* Create the consumer threads */
for(i = 0; i < numCons; i++) {
/* Create the thread */
pthread_create(&tid,&attr,consumer,NULL);
}
/* Sleep for the specified amount of time in milliseconds */
sleep(mainSleepTime);
/* Exit the program */
printf("Exit the program\n");
exit(0);
}
First you need to apply different tid's for your threads.
pthread_t tid1, tid2;
Then use these tid's:
pthread_create(&tid1, &attr, producer, NULL);
pthread_create(&tid2, &attr, consumer, NULL);
Lastly, skip the sleep and join the threads.
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
I've tested it, and works on my system. Below is the working code in full.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"
#define RAND_DIVISOR 100000000
#define TRUE 1
/* The mutex lock */
pthread_mutex_t mutex;
/* the semaphores */
sem_t full, empty;
/* the buffer */
buffer_item buffer[BUFFER_SIZE];
/* buffer counter */
int counter;
pthread_t tid1, tid2; //Thread ID
pthread_attr_t attr; //Set of thread attributes
void *producer(void *param); /* the producer thread */
void *consumer(void *param); /* the consumer thread */
void initializeData() {
/* Create the mutex lock */
pthread_mutex_init(&mutex, NULL);
/* Create the full semaphore and initialize to 0 */
sem_init(&full, 0, 0);
/* Create the empty semaphore and initialize to BUFFER_SIZE */
sem_init(&empty, 0, BUFFER_SIZE);
/* Get the default attributes */
pthread_attr_init(&attr);
/* init buffer */
counter = 0;
}
/* Producer Thread */
void *producer(void *param) {
buffer_item item;
while(TRUE) {
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
/* generate a random number */
item = rand();
/* acquire the empty lock */
sem_wait(&empty);
/* acquire the mutex lock */
pthread_mutex_lock(&mutex);
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
}
else {
printf("producer produced %d\n", item);
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal full */
sem_post(&full);
}
}
/* Consumer Thread */
void *consumer(void *param) {
buffer_item item;
while(TRUE) {
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
/* aquire the full lock */
sem_wait(&full);
/* aquire the mutex lock */
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
}
else {
printf("consumer consumed %d\n", item);
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal empty */
sem_post(&empty);
}
}
/* Add an item to the buffer */
int insert_item(buffer_item item) {
/* When the buffer is not full add the item
and increment the counter*/
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else { /* Error the buffer is full */
return -1;
}
}
/* Remove an item from the buffer */
int remove_item(buffer_item *item) {
/* When the buffer is not empty remove the item
and decrement the counter */
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else { /* Error buffer empty */
return -1;
}
}
int main(int argc, char *argv[]) {
/* Loop counter */
int i;
/* Verify the correct number of arguments were passed in */
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */
int numProd = atoi(argv[2]); /* Number of producer threads */
int numCons = atoi(argv[3]); /* Number of consumer threads */
/* Initialize the app */
initializeData();
/* Create the producer threads */
for(i = 0; i < numProd; i++) {
/* Create the thread */
pthread_create(&tid1,&attr,producer,NULL);
}
/* Create the consumer threads */
for(i = 0; i < numCons; i++) {
/* Create the thread */
pthread_create(&tid2,&attr,consumer,NULL);
}
/* Sleep for the specified amount of time in milliseconds */
//sleep(mainSleepTime);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
/* Exit the program */
printf("Exit the program\n");
exit(0);
}

Resources