/*Producer_consumer problem in c using semaphores and pthreads*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define RAND_DIVISOR 100000000
#define TRUE 1
typedef int buffer_item;
#define BUFFER_SIZE 5
/* 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);
}
when i compile this using gcc i get the following errors:
cse#cse-Not-Specified:~/11011P0519$ vi producer_consumer2.c
cse#cse-Not-Specified:~/11011P0519$ gcc producer_consumer2.c
/tmp/ccu6fydZ.o: In function `initializeData':
producer_consumer2.c:(.text+0x32): undefined reference to `sem_init'
producer_consumer2.c:(.text+0x4e): undefined reference to `sem_init'
/tmp/ccu6fydZ.o: In function `producer':
producer_consumer2.c:(.text+0xac): undefined reference to `sem_wait'
producer_consumer2.c:(.text+0x11d): undefined reference to `sem_post'
/tmp/ccu6fydZ.o: In function `consumer':
producer_consumer2.c:(.text+0x160): undefined reference to `sem_wait'
producer_consumer2.c:(.text+0x1d1): undefined reference to `sem_post'
/tmp/ccu6fydZ.o: In function `main':
producer_consumer2.c:(.text+0x2ef): undefined reference to `pthread_create'
producer_consumer2.c:(.text+0x32d): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
and when i try using gcc -lpthreads i get
cannot find lpthreads.
How to fix this ?
You need to Link with -lrt or -pthread while using function from semphore.h
compile as below
gcc producer_consumer2.c -pthread
see man sem_init
Related
I am using multi thread and I have made a program where producer creates values and insert into buffer and consumer consumes it.
However consumer never terminates. I would like to terminate the consumer process when there is nothing left to consume.
Is there any way to change the code?
This is the main code
#include<pthread.h>
#include <stdio.h>
/* Producer/consumer program illustrating conditional variables */
/* Size of shared buffer */
#define BUF_SIZE 3
int buffer[BUF_SIZE]; /* shared buffer */
int add=0; /* place to add next element */
int rem=0; /* place to remove next element */
int num=0; /* number elements in buffer */
pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER; /* mutex lock for buffer */
pthread_cond_t c_cons=PTHREAD_COND_INITIALIZER; /* consumer waits on this cond var */
pthread_cond_t c_prod=PTHREAD_COND_INITIALIZER; /* producer waits on this cond var */
void *producer(void *param);
void *consumer(void *param);
main (int argc, char *argv[])
{
pthread_t tid1, tid2; /* thread identifiers */
int i;
/* create the threads; may be any number, in general */
if (pthread_create(&tid1,NULL,producer,NULL) != 0) {
fprintf (stderr, "Unable to create producer thread\n");
exit (1);
}
if (pthread_create(&tid2,NULL,consumer,NULL) != 0) {
fprintf (stderr, "Unable to create consumer thread\n");
exit (1);
}
/* wait for created thread to exit */
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf ("Parent quiting\n");
}
This is the producer part
/* Produce value(s) */
void *producer(void *param)
{
int i;
for (i=1; i<=20; i++) {
/* Insert into buffer */
pthread_mutex_lock (&m);
if (num > BUF_SIZE) exit(1); /* overflow */
while (num == BUF_SIZE) /* block if buffer is full */
pthread_cond_wait (&c_prod, &m);
/* if executing here, buffer not full so add element */
buffer[add] = i;
add = (add+1) % BUF_SIZE;
num++;
pthread_mutex_unlock (&m);
pthread_cond_signal (&c_cons);
printf ("producer: inserted %d\n", i); fflush (stdout);
}
printf ("producer quiting\n"); fflush (stdout);
}
This is the consumer part
/* Consume value(s); Note the consumer never terminates */
void *consumer(void *param)
{
int i;
while (1) {
pthread_mutex_lock (&m);
if (num < 0) exit(1); /* underflow */
while (num == 0) /* block if buffer empty */
pthread_cond_wait (&c_cons, &m);
/* if executing here, buffer not empty so remove element */
i = buffer[rem];
rem = (rem+1) % BUF_SIZE;
num--;
pthread_mutex_unlock (&m);
pthread_cond_signal (&c_prod);
printf ("Consume value %d\n", i); fflush(stdout);
}
}
The usual way to do this is for the producer to put something in the buffer that tells the consumer it's quitting. Since your numbers go from 1 to 20, you could choose that a 0 or a -1 means the end. When the producer ends it puts -1 in the buffer and when the consumer sees a -1 in the buffer it also ends.
I'm having an issue with my sleep cycles in the ProducerConsumer.h file. If I comment out the sleep(rnum) the program will access the line printf("producer produced %d\n", item); If it's not commented out it will never access that line and I cant figure out why.
Here is my code it's in 3 separate files I would be grateful of any help thank you.
buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
ProducerConsumer.h:
#include <stdlib.h> /* required for rand() */
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <iostream>
#include "buffer.h"
#define RAND_DIVISOR 100000000;
#define TRUE 1
int counter;
buffer_item buffer[BUFFER_SIZE];
pthread_mutex_t mutex;
sem_t full, empty;
/* 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);
printf("producer produced %d\n", item);
/* 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);`enter code here`
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal empty */
sem_post(&empty);
}
}
int insert_item(buffer_item item) {
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
} else {
return -1;
}
}
int remove_item(buffer_item *item) {
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
} else {
return -1;
}
}
main.cpp:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include "ProducerConsumer.h"
#include "buffer.h"
pthread_t tid;
pthread_attr_t attr;
void initializeData()
{
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main() {
int i;
int numProd = 5; /* Number of producer threads */
int numCons = 5; /* Number of consumer threads */
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);
}
void *producer(void *param);
void *consumer(void *param);
/* Exit the program */
printf("Exit the program\n");
exit(0);
}
The RAND_MAX value is likely at least 32767, causing the the following line:
int rNum = rand() / RAND_DIVISOR;// defined as 100000000
to most always set rNum == 0.
Change statement to get a non-zero value:
int rNum = 1 + rand() % 10;// yields 1-10
Also, call srand() one time, and before using rand(). eg:
void *producer(void *param) {
buffer_item item;
srand((unsigned) time(&t));
...
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.
Hi im trying to do the producer/consumer problem on a ubuntu virtual image using vmware. I got the code from here : http://macboypro.wordpress.com/2009/05/25/producer-consumer-problem-using-cpthreadsbounded-buffer/ but i just keep getting "segmentation fault (core dumped)". Any help would be great or even a more clean solution to the producer/consumer problem (bounded buffer problem).
Heres the code im using but due to errors i had to take out the '#include "buffer.h"' :
/* buffer.h */
typedef int buffer_item;
#define BUFFER_SIZE 5
/* 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);
}
Your code seems correct, except that you don't have prototypes at the top for:
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
I was able to run your program without getting a seg fault after adding those prototypes. Using rand() in a multithreaded app is somewhat dangerous though. When I ran the code with multiple producers, they were all sleeping the same random time and generating the same random item numbers.
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);
}