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.
Related
I'm currently working on custom thread scheduler project that uses pthreads in C. I have been struggling conceptually with it but am finally getting the behavior I expect to see, save for the segmentation fault.
My job is to register five child threads and schedule each one based on the order of their IDs stored in an array. What I do is call pthread_mutex_lock and tell whichever child thread that is not to be scheduled first to wait. I do some stuff to my counter to keep track of when the next child should be scheduled and after one child thread increments counter to five it should wake up other threads and do the same thing for as many times as main loop is defined.
all variables:
#define NTHREADS 5 /* Number of child threads */
#define NUM_LOOPS 10 /* Number of local loops */
#define SCHEDULE_INTERVAL 1 /* thread scheduling interval */
#define errexit(code,str) fprintf(stderr,"%s: %s\n",(str),strerror(code));exit(1);
int schedule_vector[NTHREADS]; /* The thread schedule vector */
int flag = 0;
pthread_cond_t cv; // condtitional variable
pthread_mutex_t mtx; // mutex semaphore 1
int globalcounter = 0;
int currentThread;
#define TASK_LIMIT 6
here is parent thread:
int main(int argc,char *argv[])
{
int i;
int worker;
int ids[NTHREADS];
int errcode;
int *status;
int policy;
pthread_t threads[NTHREADS];
/* Create child threads --------------------------------------------- */
for (worker = 0; worker < NTHREADS; worker++)
{
ids[worker] = worker;
printf("creating child thread using id %d\n", worker);
/* Create a child thread ----------------------------------------- */
pthread_create (
&threads[worker],
NULL,
my_thread,
&ids[worker]);
}
/* Initialize the thread schedule vector -------------------------- */
schedule_vector[0] = 0; /* First thread to be executed (0) */
schedule_vector[1] = 1; /* Second thread to be exceuted (1) */
schedule_vector[2] = 2; /* Third thread to be executed (2) */
schedule_vector[3] = 3; /* Fourth thread to be executed (3) */
schedule_vector[4] = 4; /* Fifth thread to be executed (4) */
signal(SIGALRM, clock_interrupt_handler);
alarm(SCHEDULE_INTERVAL);
printf("handler set up\n");
/* Reap the threads as they exit ----------------------------------- */
for (worker = 0; worker < NTHREADS; worker++)
{
/* Wait for thread to terminate --- */
if (errcode=pthread_join(threads[worker],(void *) &status))
{ errexit(errcode,"pthread_join"); }
/* Check thread's exit status and release its resources -------- */
if (*status != worker)
{
fprintf(stderr,"thread %d terminated abnormally\n",worker);
exit(1);
}
}
/* The main (parent) thread terminates itself ---------------------- */
return(0);
}
Here is the child thread function:
void *my_thread(void * arg)
{
long int i;
long int counter;
int myid=*(int *) arg;
counter = 0;
printf("\nI am thread #%d\n\n", myid);
/* Main loop ------------------------------------------ */
for (i = 0; i < NUM_LOOPS; i++)
{
currentThread = myid;
pthread_mutex_lock(&mtx);
while(myid != schedule_vector[flag]){
pthread_cond_wait(&cv, &mtx);
}
counter++;
globalcounter = counter;
printf("Thread: %d is running ...\n", myid);
usleep(100000);
}
return arg;
}
and here is my interrupt handler:
void clock_interrupt_handler(void)
{
printf("scheduler started ++++++++++++++++++++++++++++++++++ \n");
if (currentThread == schedule_vector[flag]) {
printf("scheduled thread received: thread %d, and it's counter is at %d\n", currentThread, globalcounter);
while(globalcounter < TASK_LIMIT){
if(globalcounter == 5){
flag++;
pthread_cond_broadcast(&cv);
}
pthread_mutex_unlock(&mtx);
alarm(SCHEDULE_INTERVAL);
}
} else {
printf("unscheduled thread received, putting thread %d with count %d to sleep...\n", currentThread, globalcounter);
alarm(SCHEDULE_INTERVAL);
}
}
This is the output:
scheduler started ++++++++++++++++++++++++++++++++++
scheduled thread received: thread 0, and it's counter is at 1
Thread: 0 is running ...
Thread: 0 is running ...
Thread: 0 is running ...
Thread: 0 is running ...
Segmentation fault (core dumped)
It basically repeats this behavior, but for each thread. I'd like to understand what is exactly causing the seg fault
Seems pthread_mutex_lock/pthread_mutex_unlock do not pair.
The correct code looks like
pthread_mutex_lock()
pthread_cond_broadcast()
pthread_mutex_unlock()
pthread_mutex_lock()
pthread_cond_wait()
pthread_mutex_unlock()
I am trying to create a consumer-producer program where the consumer thread producer numbers to fill an array, and a consumer thread prints the numbers that populate the array. Currently, I can fill the array and pass data back and forth between the consumer/producer threads, but I want the producer to create numbers faster than the consumer processes them.
At the moment, a number is produced every 1 second, and a number is consumed every 3. Two numbers should be produced before one is consumed, but my producer thread is waiting until the number it produced is consumed.
I've tried moving around the mutex locks and unlocks, and also the signals, but I haven't gotten it to work. The following code produces the following output:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
struct Data {
int num;
int wait_time;
};
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
//int count = 0;
struct Data buffer[32];
void* producer(void *ptr) {
int i, w; /* counter and random wait time */
struct Data data;
int count = 0;
while(1) {
//w = rand() % 5 + 3;
w = 1;
sleep(w); /* Wait between 3 and 7 seconds */
data.num = rand() % 1000; /* Create random number to pass */
//data.wait_time = rand() % 8 + 2;
data.wait_time = 3;
pthread_mutex_lock(&the_mutex); /* lock the buffer */
while (buffer[count].num != 0) { /* while full */
//pthread_cond_signal(&condc);
pthread_cond_wait(&condp, &the_mutex);
}
//pthread_mutex_lock(&the_mutex); /* lock the buffer */
buffer[count] = data;
pthread_cond_signal(&condc); /* signal consumer */
pthread_mutex_unlock(&the_mutex);
printf("Produced %i and slept for %i seconds\n", buffer[count].num, w);
if (count != 31){
count += 1;
//printf("Producer count: %i\n", count);
}
else
count = 0;
//pthread_cond_signal(&condc); /* signal consumer */
//pthread_mutex_unlock(&the_mutex); /* unlock */
}
pthread_exit(0);
}
void* consumer(void *ptr) {
int i;
int count = 0;
//for(i = 1; i <= MAX; i++) {
while(1) {
pthread_mutex_lock(&the_mutex); /* lock th buffer */
while(buffer[count].num == 0){
//pthread_cond_signal(&condp); /* while empty */
pthread_cond_wait(&condc, &the_mutex);
}
//pthread_mutex_lock(&the_mutex);
sleep(buffer[count].wait_time);
printf("Consumed %i and slept for %i seconds\n", buffer[count].num, buffer[count].wait_time);
//pthread_mutex_lock(&the_mutex);
buffer[count].num = 0;
buffer[count].wait_time = 0;
pthread_cond_signal(&condp); /* signal producer */
pthread_mutex_unlock(&the_mutex);
if(count != 31){
count += 1;
//printf("Consumer count: %i\n", count);
}
else
count = 0;
//pthread_cond_signal(&condp); /* signal producer */
//pthread_mutex_unlock(&the_mutex); /* unlock */
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
srand(time(NULL));
for (int i = 0; i < 32; i++) { /* Initialize buffer */
buffer[i].num = 0;
buffer[i].wait_time = 0;
}
// Initialize the mutex and condition variables
/* What's the NULL for ??? */
pthread_mutex_init(&the_mutex, NULL);
pthread_cond_init(&condc, NULL); /* Initialize consumer condition variable */
pthread_cond_init(&condp, NULL); /* Initialize producer condition variable */
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
// Wait for the threads to finish
// Otherwise main might run to the end
// and kill the entire process when it exits.
pthread_join(con, NULL);
pthread_join(pro, NULL);
//pthread_join(&con, NULL);
//pthread_join(&pro, NULL);
// Cleanup -- would happen automatically at end of program
pthread_mutex_destroy(&the_mutex); /* Free up the_mutex */
pthread_cond_destroy(&condc); /* Free up consumer condition variable */
pthread_cond_destroy(&condp); /* Free up producer condition variable */
}
Output (The program prints the 1st line after 1 seconds, then prints both the 2nd and 3rd at the same time after 3 seconds):
Produced 985 and slept for 1 seconds
Consumed 985 and slept for 3 seconds
Produced 540 and slept for 1 seconds
I would rather have the output look something like this:
Produced 985 and slept for 1 seconds
Produced 540 and slept for 1 seconds
Consumed 985 and slept for 3 seconds
The consumer is locking the mutex then sleeping for 3 seconds. So the producer is having to wait for the consumer to finish it's job/sleep before it can produce something else. Avoid sleeping either thread when a lock is in place.
EDIT:
Just edited your code a bit and this seems to work without the signals etc here. Give it a go:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
struct Data {
int num;
int wait_time;
};
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
struct Data buffer[32];
void* producer(void *ptr) {
int i, w; /* counter and random wait time */
struct Data data;
int count = 0;
while(1) {
printf("prod count %d\n",count);
w = 1;
sleep(w);
data.num = rand() % 1000;
data.wait_time = 3;
while (buffer[count].num != 0) {
printf("buffer full, count = %d\n", count);
sleep(1);
}
// Only using the mutex when we want to change the variable.
pthread_mutex_lock(&the_mutex);
buffer[count] = data;
pthread_mutex_unlock(&the_mutex);
printf("Produced %i and slept for %i seconds\n", buffer[count].num, w);
if (count != 31){
count += 1;
}
else
count = 0;
}
pthread_exit(0);
}
void* consumer(void *ptr) {
int i;
int count = 0;
while(1) { /* lock th buffer */
printf("cons count %d\n",count);
while(buffer[count].num == 0){
printf("buffer empty, count = %d\n", count);
sleep(1);
}
sleep(buffer[count].wait_time);
printf("Consumed %i and slept for %i seconds\n", buffer[count].num, buffer[count].wait_time);
pthread_mutex_lock(&the_mutex);
buffer[count].num = 0;
buffer[count].wait_time = 0;
pthread_mutex_unlock(&the_mutex);
if(count != 31){
count += 1;
//printf("Consumer count: %i\n", count);
}
else {
count = 0;
}
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
srand(time(NULL));
for (int i = 0; i < 32; i++) { /* Initialize buffer */
buffer[i].num = 0;
buffer[i].wait_time = 0;
}
// Initialize the mutex and condition variables
/* What's the NULL for ??? */
pthread_mutex_init(&the_mutex, NULL);
pthread_cond_init(&condc, NULL); /* Initialize consumer condition variable */
pthread_cond_init(&condp, NULL); /* Initialize producer condition variable */
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
// Wait for the threads to finish
// Otherwise main might run to the end
// and kill the entire process when it exits.
pthread_join(con, NULL);
pthread_join(pro, NULL);
//pthread_join(&con, NULL);
//pthread_join(&pro, NULL);
// Cleanup -- would happen automatically at end of program
pthread_mutex_destroy(&the_mutex); /* Free up the_mutex */
pthread_cond_destroy(&condc); /* Free up consumer condition variable */
pthread_cond_destroy(&condp); /* Free up producer condition variable */
}
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.
/*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
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);
}