trubiat
asked on
Producer/Consumer threads, semaphores and buffer problem
I am trying to initialize semaphores and use pthread_create in order to create new threads for the multiple producers and consumers. I am getting this type of error when I am trying to compile and I have no clue what it means because I it seems like my syntax is correct.
Also if anyone could give me some insight of how to create a Buffer that's accessible by producer and consumer functions and has size a parameter passed by the user. I am confused because the parameter is accessible by the main() function but the buffer has to be globally declared. I think malloc() has to be used but I don't know how.
Here is my code so far followed by the compilation errors I get:
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_BUF_SIZE 255
#include <semaphore.h>
int *Buffer;
int maximum;
sem_t mut;
sem_t empty;
sem_t full;
void *producer(void *param);
void *consumer(void *param);
int main(int argc, char *argv[])
{
pthread_t tid1, tid2;
int i, r, PID, x;
//int shmid, shmkey;
//char *mem, *s;
//char str [MAX_BUF_SIZE] = "Costas";
int bufLength = (int)argv[2], max = (int)argv[1], pno = (int)argv[3], cno = (int)argv[4];
maximum = max;
//int buffer[2][bufLength * 2];
if( !(argc == 4))
{
printf("Wrong number of parameters. Please enter 4 parameters.\n");
exit(1);
}
Buffer = (int*)malloc( (bufLength*sizeof(int)) * 2);
sem_init(&mut, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, bufLength);
for(i = 0; i < pno; i++)
{
PID = fork();
if (PID == 0)
{
x = pthread_create(&tid1, NULL, producer, i);
}
}
if (PID != 0)
{
for(i = 0; i < cno; i++)
{
if (fork() == 0)
{
x = pthread_create(&tid2, NULL, consumer, i);
}
}
}
//}
exit(0);
}
void *producer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//buffer[0][1] = thread_num;
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}
void *consumer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//printf("%d\n", buffer[0][1]);
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}
Errors:
/tmp/ccJh1ehp.o: In function `main':
test.c:(.text+0x84): undefined reference to `sem_init'
test.c:(.text+0x98): undefined reference to `sem_init'
test.c:(.text+0xad): undefined reference to `sem_init'
test.c:(.text+0xe7): undefined reference to `pthread_create'
test.c:(.text+0x132): undefined reference to `pthread_create'
/tmp/ccJh1ehp.o: In function `producer':
test.c:(.text+0x189): undefined reference to `sem_wait'
test.c:(.text+0x199): undefined reference to `sem_post'
/tmp/ccJh1ehp.o: In function `consumer':
test.c:(.text+0x1ed): undefined reference to `sem_wait'
test.c:(.text+0x1fd): undefined reference to `sem_post'
collect2: ld returned 1 exit status
Thank you all ofr your help.
Also if anyone could give me some insight of how to create a Buffer that's accessible by producer and consumer functions and has size a parameter passed by the user. I am confused because the parameter is accessible by the main() function but the buffer has to be globally declared. I think malloc() has to be used but I don't know how.
Here is my code so far followed by the compilation errors I get:
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_BUF_SIZE 255
#include <semaphore.h>
int *Buffer;
int maximum;
sem_t mut;
sem_t empty;
sem_t full;
void *producer(void *param);
void *consumer(void *param);
int main(int argc, char *argv[])
{
pthread_t tid1, tid2;
int i, r, PID, x;
//int shmid, shmkey;
//char *mem, *s;
//char str [MAX_BUF_SIZE] = "Costas";
int bufLength = (int)argv[2], max = (int)argv[1], pno = (int)argv[3], cno = (int)argv[4];
maximum = max;
//int buffer[2][bufLength * 2];
if( !(argc == 4))
{
printf("Wrong number of parameters. Please enter 4 parameters.\n");
exit(1);
}
Buffer = (int*)malloc( (bufLength*sizeof(int)) * 2);
sem_init(&mut, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, bufLength);
for(i = 0; i < pno; i++)
{
PID = fork();
if (PID == 0)
{
x = pthread_create(&tid1, NULL, producer, i);
}
}
if (PID != 0)
{
for(i = 0; i < cno; i++)
{
if (fork() == 0)
{
x = pthread_create(&tid2, NULL, consumer, i);
}
}
}
//}
exit(0);
}
void *producer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//buffer[0][1] = thread_num;
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}
void *consumer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//printf("%d\n", buffer[0][1]);
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}
Errors:
/tmp/ccJh1ehp.o: In function `main':
test.c:(.text+0x84): undefined reference to `sem_init'
test.c:(.text+0x98): undefined reference to `sem_init'
test.c:(.text+0xad): undefined reference to `sem_init'
test.c:(.text+0xe7): undefined reference to `pthread_create'
test.c:(.text+0x132): undefined reference to `pthread_create'
/tmp/ccJh1ehp.o: In function `producer':
test.c:(.text+0x189): undefined reference to `sem_wait'
test.c:(.text+0x199): undefined reference to `sem_post'
/tmp/ccJh1ehp.o: In function `consumer':
test.c:(.text+0x1ed): undefined reference to `sem_wait'
test.c:(.text+0x1fd): undefined reference to `sem_post'
collect2: ld returned 1 exit status
Thank you all ofr your help.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
>how to create a Buffer that's accessible by producer and consumer functions and has size a parameter passed by the user.
>I am confused because the parameter is accessible by the main() function but the buffer has to be globally declared.
>I think malloc() has to be used but I don't know how.
You are right .. you need to use malloc to allocate buffers at run time.
given size n bytes, you would allocate them as shown below.
my_pointer = malloc (n);
malloc returns a void * and the address of newly allocated buffer of n bytes would be assigned to my_pointer. Also note that this buffer would remain in scope until you call free (my_pointer);
Till then this buffer can be accessed by all functions and it will remain in scope.
Let me know if you need some clarifications.
Cheers!
sunnycoder
>I am confused because the parameter is accessible by the main() function but the buffer has to be globally declared.
>I think malloc() has to be used but I don't know how.
You are right .. you need to use malloc to allocate buffers at run time.
given size n bytes, you would allocate them as shown below.
my_pointer = malloc (n);
malloc returns a void * and the address of newly allocated buffer of n bytes would be assigned to my_pointer. Also note that this buffer would remain in scope until you call free (my_pointer);
Till then this buffer can be accessed by all functions and it will remain in scope.
Let me know if you need some clarifications.
Cheers!
sunnycoder
ASKER
Thank you for your help sunnycoder,
So the buffer does not need to be declared globally?
So the buffer does not need to be declared globally?
you can either declare my_pointer globally and use it in all your functions ... or you can declare it in main and pass it as parameter to all functions that need it. I prefer the latter since I find it cleaner ... lesser the globals, better it is.
Cheers!
sunnycoder
Cheers!
sunnycoder
ASKER
my pthread_create line creates segmentation fault. any idea why?
x = pthread_create(&tid1[i], NULL, producer, i+1);
x = pthread_create(&tid1[i], NULL, producer, i+1);
>pthread_t tid1, tid2;
tid1 does not appear to be an array. Show me the exact code.
tid1 does not appear to be an array. Show me the exact code.
ASKER
The producer function never executes. I get segmentation fault within the for loop...Thanks for your help....I will accept your answer once this one has been answered..
Here is the exact code:
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_BUF_SIZE 255
#include <semaphore.h>
int *Buffer;
int maximum;
sem_t mut;
sem_t empty;
sem_t full;
void *producer(void *param);
void *consumer(void *param);
int main(int argc, int *argv[])
{
int i, r, PID, x;
//int shmid, shmkey;
//char *mem, *s;
//char str [MAX_BUF_SIZE] = "Costas";
int bufLength = atoi(argv[2]), max = atoi(argv[1]), pno = atoi(argv[3]), cno = atoi(argv[4]);
pthread_t tid1, tid2;
maximum = max;
//int buffer[2][bufLength * 2];
printf("max is %d, bufLength is %d, nProducers is %d, nConsumers is %d\n", max, bufLength, pno, cno);
if( !(argc == 5))
{
printf("Wrong number of parameters. Please enter 4 parameters.\n");
exit(1);
}
Buffer = (int*)malloc( (bufLength*sizeof(int)) * 2);
sem_init(&mut, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, bufLength);
for(i = 0; i < pno; i++)
{
//PID = fork();
//if (PID == 0)
//{
x = pthread_create(&tid1, NULL, producer, i);
//}
}
//if (x != 0)
//{
// for(i = 0; i < cno; i++)
//{
// if (fork() == 0)
// {
// x = pthread_create(&tid2, NULL, consumer, i);
// }
// }
//}
//}
exit(0);
}
void *producer(void *param)
{
int thread_num = atoi(param), a = 0;
/*while (a == 0)
{
sem_wait(&mut);
//buffer[0][1] = thread_num;
sem_post(&mut);
}*/
printf("I am in PRODUCER with thread number: %d\n", thread_num);
}
void *consumer(void *param)
{
int thread_num = atoi(param), a = 0;
/*while (a == 0)
{
sem_wait(&mut);
//printf("%d\n", buffer[0][1]);
sem_post(&mut);
}*/
printf("I am in CONSUMER with thread number: %d\n", thread_num);
}
Here is the exact code:
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_BUF_SIZE 255
#include <semaphore.h>
int *Buffer;
int maximum;
sem_t mut;
sem_t empty;
sem_t full;
void *producer(void *param);
void *consumer(void *param);
int main(int argc, int *argv[])
{
int i, r, PID, x;
//int shmid, shmkey;
//char *mem, *s;
//char str [MAX_BUF_SIZE] = "Costas";
int bufLength = atoi(argv[2]), max = atoi(argv[1]), pno = atoi(argv[3]), cno = atoi(argv[4]);
pthread_t tid1, tid2;
maximum = max;
//int buffer[2][bufLength * 2];
printf("max is %d, bufLength is %d, nProducers is %d, nConsumers is %d\n", max, bufLength, pno, cno);
if( !(argc == 5))
{
printf("Wrong number of parameters. Please enter 4 parameters.\n");
exit(1);
}
Buffer = (int*)malloc( (bufLength*sizeof(int)) * 2);
sem_init(&mut, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, bufLength);
for(i = 0; i < pno; i++)
{
//PID = fork();
//if (PID == 0)
//{
x = pthread_create(&tid1, NULL, producer, i);
//}
}
//if (x != 0)
//{
// for(i = 0; i < cno; i++)
//{
// if (fork() == 0)
// {
// x = pthread_create(&tid2, NULL, consumer, i);
// }
// }
//}
//}
exit(0);
}
void *producer(void *param)
{
int thread_num = atoi(param), a = 0;
/*while (a == 0)
{
sem_wait(&mut);
//buffer[0][1] = thread_num;
sem_post(&mut);
}*/
printf("I am in PRODUCER with thread number: %d\n", thread_num);
}
void *consumer(void *param)
{
int thread_num = atoi(param), a = 0;
/*while (a == 0)
{
sem_wait(&mut);
//printf("%d\n", buffer[0][1]);
sem_post(&mut);
}*/
printf("I am in CONSUMER with thread number: %d\n", thread_num);
}
Call looks ok except that you are overwriting previous TIDs and you are not joining the threads .. so there is a resource leak.
Try checking the return values of each system call - malloc and pthread_create return the success/failure status. check it for error conditions.
Put printf as first line in producer and flush it before doing anything else.
Try checking the return values of each system call - malloc and pthread_create return the success/failure status. check it for error conditions.
Put printf as first line in producer and flush it before doing anything else.
ASKER
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_BUF_SIZE 255
#include <semaphore.h>
int *Buffer;
int maximum;
sem_t mut;
sem_t empty;
sem_t full;
void *producer(void *param);
void *consumer(void *param);
int main(int argc, char *argv[])
{
pthread_t tid1, tid2;
int i, r, PID, x;
//int shmid, shmkey;
//char *mem, *s;
//char str [MAX_BUF_SIZE] = "Costas";
int bufLength = (int)argv[2], max = (int)argv[1], pno = (int)argv[3], cno = (int)argv[4];
maximum = max;
//int buffer[2][bufLength * 2];
if( !(argc == 4))
{
printf("Wrong number of parameters. Please enter 4 parameters.\n");
exit(1);
}
Buffer = (int*)malloc( (bufLength*sizeof(int)) * 2);
sem_init(&mut, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, bufLength);
for(i = 0; i < pno; i++)
{
//PID = fork();
//if (PID == 0)
//{
x = pthread_create(&tid1, NULL, producer, i);
//}
}
if (PID != 0)
{
for(i = 0; i < cno; i++)
{
// if (fork() == 0)
// {
x = pthread_create(&tid2, NULL, consumer, i);
// }
}
}
//}
exit(0);
}
void *producer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//buffer[0][1] = thread_num;
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}
void *consumer(void *param)
{
int thread_num = atoi(param), a = 0;
while (a == 0)
{
sem_wait(&mut);
//printf("%d\n", buffer[0][1]);
sem_post(&mut);
}
printf("I am in CHILD PROCESS 1\n");
}