Why my producer-consumer program in C not working properly? - c

I'm trying to synchronize 02 child processes that communicate using a buffer of size 5 using the semaphores "empty" and "full" only.
Process 01 executes producer() function and the second one executes consumer(), but the consumer functions does not execute at all even when the producer is blocked (empty=0).
after 5 iterations, I only get 5 insertions but no consuming ( I'm inserting 5's for now). Also I believe there is no need for a mutex since there are only 01 producer and 01 consumer right? here are the 02 functions and the main program:
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include <pthread.h>
#define MaxItems 5
#define BufferSize 5
sem_t empty;
sem_t full;
//pthread_mutex_t lock;
int in = 0;
int out = 0;
int buffer[BufferSize];
int N = 20;
void *producer()
{
while(1)
{
//pthread_mutex_lock(&lock);
sem_wait(&empty);
buffer[in] = 5; // fill the buffer with numbers
printf("\nInsert Item %d at %d\n", buffer[in],in);
int emptyvalue, fullValue;
sem_getvalue(&full, &fullValue); sem_getvalue(&empty, &emptyvalue);
printf("full is:%d, empty is:%d\n", fullValue, emptyvalue);
//pthread_mutex_unlock(&lock);
sem_post(&full); // increase the value of full, so the consumer should execute now?
in = (in+1)%BufferSize;
usleep(500000);
}
}
void *consumer()
{
printf("test: consumer"); //this consumer function does not execute
while (1)
{
sem_wait(&full); // full initially is = 0, so it blocks at first
//pthread_mutex_lock(&lock);
int item = buffer[out];
printf("Remove Item %d from %d\n",item, out);
//pthread_mutex_unlock(&lock);
sem_post(&empty);
printf(" %d", out); //using the values in the buffer
out = (out+1)%BufferSize;
}
}
int main()
{
//pthread_mutex_init(&lock, NULL);
sem_init(&empty,0,BufferSize);
sem_init(&full,0,0);
pid_t id1, id2;
id1 = fork();
if (id1 == 0) {
id2 = fork();
if (id2 == 0) //child 2
{
printf("im the consumer");
consumer();
}else{ //child 1
printf("i'm the producer");
producer();
}
}else{
sem_destroy(&full);
sem_destroy(&empty);
//pthread_mutex_destroy(&lock);
return 0;
}
}
thank you so much

By default, different processes live in different virtual address spaces. They cannot access each other's memory. The same is true for POSIX semaphores. This means that when you use fork to make two processes, you end up with two different sets of variables. You have a separate buffer and semaphores for each process.
To make this work, you should create a memory mapping (mmap for POSIX) where you put all the data you need to share between the processes, including the semaphores. The semaphores should be initialized with pshared to non-zero. The man page for sem_init has more details about this.
Alternatively you could use some other form of inter-process communication, like pipes.

Related

Only three of my five threads are executing, synchronizing using mutexes

I am doing an academic exercise for an OS class where we synchronize five detached threads using ONLY mutex locks and unlocks. We "CANNOT force the threads into any serial execution. Once spawned they must be free from external influences (other than the mutexes). The parent should NOT employ a pthread_join."
I am spawning 5 threads, detaching them and then using each threads to read in data and update a global variable. Currently my code spawns the 5 threads but only three of them output their ID's and none of them get into the while loop. Any help/advice here would be appreciated!
Output:
thread: 6156515168
thread: 6156515192
thread: 6156515176
There is a sleep in main which if uncommented provides the expected output, but this would be forcing a serial execution..
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER; // declaring mutex
int FileNameHelper=1;
int balance=0;
void* detatchedThread(void *param){
long tid = (long)param;
char* base = "data";
char filename[256];
char buf[100];
sprintf(filename, "%s%d.in", base, FileNameHelper); //creates data1.in, data2.in...
FileNameHelper ++;
FILE *inputFile = fopen(filename, "r");
printf ("thread: %ld\n", tid);
// critical sec line
if(fgets(buf, sizeof buf, inputFile) == NULL)
return NULL; // could not read first line
sleep(1); // make sure each thread runs long enough to get the random update behavior required.
pthread_mutex_lock(&mutex_lock); //we are in the critical section, lock mutex
while(fgets(buf, sizeof buf, inputFile) != NULL) {
int val;
if(sscanf(buf, "%d", &val) != 1){
break;
}
printf("%d\n", val);
balance += val;
printf ("Account balance after thread %ld is $%d\n", tid, balance);
}
pthread_mutex_unlock(&mutex_lock);
if(buf[0] != 'W')
return NULL;// last line data was invalid
pthread_exit(NULL);
}
int main(){
pthread_t th[5];
//initialize the mutex
if(pthread_mutex_init(&mutex_lock, NULL) != 0){
printf("\nmutex init has failed\n");
return 1;
}
//call the 5 threads, Detach the threads once they are created.
for (int i = 0; i < 5; i++){
pthread_create(&th[i], NULL, detatchedThread, (void *)&th[i]);
pthread_detach(th[i]);
//sleep(1); uncommenting this line gives me the expected behavior
}
pthread_mutex_destroy(&mutex_lock);
return 0;
}

Why is my semaphore lock not locking this process as expected? (Multithreading)

I'm currently writing a program that takes an array that has randomly generated numbers, and uses multithreading to essentially divide the array in equal parts, then each thread will find the minimum of their respective division of the array. Essentially, I need my parent thread to be blocked (have non-busy waiting for parallel processing efficiency) using semaphores while the child threads are looking for the minimum, however the combination of sem_wait and sem_post is not blocking the parent thread as expected.
I've attempted to change the sem_init parameters to different values, however it seems no matter what I do the parent doesn't actually get blocked.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/timeb.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#define MAX_SIZE 100000000
#define MAX_THREADS 16
#define RANDOM_SEED 8631
#define MAX_RANDOM_NUMBER 5000
// Global variables
long gRefTime; //For timing
int gData[MAX_SIZE]; //The array that will hold the data
int gThreadCount; //Number of threads
int gDoneThreadCount; //Number of threads that are done at a certain point. Whenever a thread is done, it increments this. Used with the semaphore-based solution
int gThreadMin[MAX_THREADS]; //The minimum value found by each thread
bool gThreadDone[MAX_THREADS]; //Is this thread done? Used when the parent is continually checking on child threads
int indices[MAX_THREADS][3];
// Semaphores
sem_t completed; //To notify parent that all threads have completed or one of them found a zero
sem_t mutex; //Binary semaphore to protect the shared variable gDoneThreadCount
int main(int argc, char *argv[]){
pthread_t tid[MAX_THREADS];
pthread_attr_t attr[MAX_THREADS];
int i, indexForZero, arraySize, min;
// Code for parsing and checking command-line arguments
if(argc != 4){
fprintf(stderr, "Invalid number of arguments!\n");
exit(-1);
}
if((arraySize = atoi(argv[1])) <= 0 || arraySize > MAX_SIZE){
fprintf(stderr, "Invalid Array Size\n");
exit(-1);
}
gThreadCount = atoi(argv[2]);
if(gThreadCount > MAX_THREADS || gThreadCount <=0){
fprintf(stderr, "Invalid Thread Count\n");
exit(-1);
}
indexForZero = atoi(argv[3]);
if(indexForZero < -1 || indexForZero >= arraySize){
fprintf(stderr, "Invalid index for zero!\n");
exit(-1);
}
GenerateInput(arraySize, indexForZero);
CalculateIndices(arraySize, gThreadCount, indices);
InitSharedVars();
SetTime();
// Initialize threads, create threads, and then make the parent wait on the "completed" semaphore
// The thread start function is ThFindMinWithSemaphore
sem_init(&mutex, 0, 1);
sem_init(&completed, 0, 0);
for(i=0; i < gThreadCount; i++){
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],ThFindMinWithSemaphore,&indices[i]);
}
sem_wait(&completed);
if(gThreadDone[i] == true && gThreadMin[i] == min){
for(i=0; i < gThreadCount; i++){
pthread_cancel(tid[i]);
}
}
min = SearchThreadMin();
printf("Threaded FindMin with parent waiting on a semaphore completed in %ld ms. Min = %d\n", GetTime(), min);
void* ThFindMinWithSemaphore(void *param) {
int threadNum = ((int*)param)[0];
int i;
int startIndex = indices[threadNum][1];
int endIndex = indices[threadNum][2];
sem_wait(&completed);
for (i = startIndex; i < endIndex; i++) {
if (gData[i] < gThreadMin[threadNum]){
gThreadMin[threadNum] = gData[i];
}
else if (gData[i] == 0){
sem_post(&completed);
pthread_exit(0);
}
}
sem_wait(&mutex);
gDoneThreadCount++;
sem_post(&mutex);
if (gDoneThreadCount == gThreadCount){
sem_post(&completed);
}
pthread_exit(0);
}
Note that this is not all of the file code that is actually in the file.
I want the main function to wait at the line where it says sem_wait(&completed). The goal is to have the child threads signal the parent by using sem_post when each thread is done searching for their minimum value, or one of the threads has found a zero within the array. Then at that point the main function should continue after receiving that sem_post signal.
As I understand, if the semaphore completed has a count of zero which I have initialized it to that using sem_init(&completed, 0, 0), the caller for sem_wait waits until it receives sem_post from one of the child threads. It appears that my program does not do the wait as expected.

Creating a process pool C Linux

I have an assignment and I am not quite sure how to go about it. Basically I have to create a coordinator process which creates 5 working processes which are waiting to be awakened. The coordinator passes a marker(integer) to the first process, then that process increments the marker by 1 and passes it to the next process. The coordinator process awakens the next process which does the same and so on. The so called marker should go through all the processes 10 times and in the end its value should be printed by the coordinator. Signals should be used as well as shared memory for the marker.
So I created 5 processes and I am thinking that on every iteration there should be a signal and a handler should be passed which will basically do all the work with the marker.
This is my first time working with processes. This is what I have so far:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <signal.h>
#define numOfProcesses 5
pid_t procIDs[5];
void handler(int signum){
//marker and all work here
}
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}else if(procIDs == 0){
pause();
}
}
}
int main(){
createProcesses();
int i;
for(i = 0; i < numOfProcesses; i++){
pkill(SIGUSR1, handler);
}
return 0;
}
I honestly don't know how to go about this. I would really appreciate a piece of advice. Thanks in advance!
This is what I have come up with. Sorry for answering, I couldn't find out how to format code in a comment. Anyway:
It should be 10 times each process. I am using shared memory so I guess I don't need a global variable for the marker? This is what I have come up with:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/shm.h>
#include<signal.h>
#include<sys/ipc.h>
#define numOfProcesses 5
#define numOfLoops 10
pid_t* procIDs[5];
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}
else if(procIDs == 0){
pause();
}
}
}
void init(){//init marker = 0
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data;
data = (int*) shmat(shID, 0, 0);
*data = 0;
}
int* getValue(){//get value of marker
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data = shmat(shID, 0, 0);
return data;
}
void increment(int sig){//increment + 1
if(sig == SIGUSR1){
int temp;
int* data;
data = getValue();
temp = *data;
temp++;
*data = temp;
}
}
void yourFunc(int count, pid_t* mypid, int mysig){
if(count == 0){
return;
}else{
printf("Signal sent :: to PID : %d\n", mypid);
kill(*mypid, SIGUSR1);
yourFunc(count -1, ++mypid, SIGUSR1);
}
}
int main(){
signal(SIGUSR1, increment);
init();
int i,j;
createProcesses();
for(j = 0; j < numOfLoops; j++){//loop every pid 10 times
pid_t* currProcess = procIDs[0];
yourFunc(numOfProcesses, currProcess, SIGUSR1);
}
int* data = getValue();
printf("Marker: %d\n", *data);
return 0;
}
I tried your problem, but I am really baffled by the structure of your question, its really unclear what your problem statement is.
10 times each(10 times per process or a total of 10 times(2 times per process)
You say the processes are waiting to be awakened, which hints that they are not child processes rather other processes running on the system, and would require a fifo to communicate.
Nevertheless, the following is what I could conclude from the limited information.
You need to create a function which would be invoked 10 times(loop) by the coordinator on the first process(waiting to be awakened)
The function would recursively invoke the second process and so on till the last sleeping process.
You'll have to use SIGUSR1, and define action for it in a custom signal handler,
eg.
signal(SIGUSR1,custom_handler)
You will need to keep marker as a global variable.
Because C is a procedural language and kernel's scheduling is not in your hands once a process terminates you cannot recall it or ensure same PID for a process on forking.
So if you are thinking of creating processes inside functions which will be paused and on getting a signal shall resume, fine.....!, But it would be a one-off.
That's all I can say by the limited information your question presents.
Following is the above idea in C.
Initialise count = 5 (no. of processes)in the caller.
mypid points to the first process's PID.
void party_time(int count, pid_t* mypid, int mysig)
{
if(count == 0)
return;
else
{
printf("Signal sent :: to PID : %d\n",*mypid);
kill(*mypid,SIGUSR1);
party_time(count - 1 ,++mypid,SIGUSR1);
}
}

producer consumer using posix

I have a Standard Producer Consumer problem for bounded buffer.Whenever i give unequal number of producer or consumer the Program does not terminate.
I have limited the number of insertion or deletion to 50
I would like to know why the above problem occurs and ways to fix it
#include<stdio.h>
#include<pthread.h> //Header for creating Posix Threads;
#include<semaphore.h>
#include<stdlib.h>
#define MAX 20
typedef struct shared_buffer
{
int arr[20];
int i;
}buffer;
buffer b; //Fixed Length buffer shared memory
sem_t full,empty; //Counting semaphores full->no of slots filled empty ->no of slots empty
pthread_mutex_t mutex; //mutual exclusion for critcal section
int flag=1,cnt=0;
void * producer(void * arg) //Producer threads method
{
int index; //thread Id
index=(int)arg;
while(flag)
{
sem_wait(&empty); //will check if slot available and decrement empty count
pthread_mutex_lock(&mutex); //acquiring lock on process
b.arr[b.i]=rand()%100; //critcal section
printf("\n Process %d Produced :%d",index,b.arr[b.i]);
b.i++;
cnt++; //critcal section ends
pthread_mutex_unlock(&mutex); //realeasing lock
sem_post(&full); //increment full count
usleep(rand()%100); //sleep for random time
}
}
void * consumer(void * arg)
{
int index;
index=(int)arg;
while(flag)
{
sem_wait(&full); //will check if buffer is not empty
pthread_mutex_lock(&mutex);
b.i--; //critical section
printf("\n Process %d consumed :%d",index,b.arr[b.i]);
cnt++; //critical section ends
pthread_mutex_unlock(&mutex); //release lock
sem_post(&empty); //increment count of empty slots
usleep(rand()%100);
}
}
int main(int argc,char * argv[])
{
pthread_t Pid,Cid;
int P,C,index,size;
b.i=0;
if(argc<4)
{
printf("Error.Usage : ./filename.out <no of producer> <no of consumer> <Buffer Size(<=15)> \n");
exit(0);
}
P=atoi(argv[1]);
C=atoi(argv[2]);
size=atoi(argv[3]);
sem_init(&full,0,0); //number of slots filled is 0
sem_init(&empty,0,size); //number of empty slots is buffer size
pthread_mutex_init(&mutex,NULL);
for (index=0;index<C;index++) //creating C number of consumer
{
pthread_create(&Cid,NULL,consumer,index);
}
for (index=0;index<P;index++) //creating P number of producer
{
pthread_create(&Pid,NULL,producer,index);
}
while(cnt<=50) //maximum 50 operations allowed
usleep(200);
flag=0;
printf("phew!Successful");
pthread_exit(NULL);
return 1;
}
Here are some clues (not full answer):
First thing that bugging me is that you are overwriting your pthread_t references in your loops. But it is OK since you don't use them afterwards.
Second thing is that you misplaced the pthread_exit: there should be at the end of the threads you created:
void * consumer_producer(void * arg)
{
// ...
while(flag)
{
// ...
}
pthread_exit(NULL);
}
I guess you have a race condition. It is possible that a thread is waiting when flag is set to 0. Other threads possibly catch that state and return, thus the waiting thread is waiting forever.

Dining Philosophers in C using fork()

I wrote a C program for the Dining Philosophers Problem using pthread some time ago and am now trying to change it to use fork() instead. This is an exercive for a lecture I already passed. But a friend asked me for help and I can't seem to get it figured out by myself, which is driving me crazy!
If i do a "ps" the processes are there. But there isn't any output to stdout, so I think I'm doing something wrong with the pipes.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define N 5
#define LEFT (i+4)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
sem_t spoon;
sem_t phil[N];
int state[N];
int phil_num[N]={0,1,2,3,4};
int fd[N][2]; // file descriptors for pipes
pid_t pid, pids[N]; // process ids
int i;
int num;
void philosopher(int i);
void test(int i);
void take_spoon(int i);
void put_spoon(int i);
char buffer[100];
int main(void)
{
for(i=0;i<N;++i)
{
pipe(fd[i]);
pids[i] = fork();
printf("i=%d\n",i);
printf("pids[i]=%d\n",pids[i]);
if(pids[i]==0)
{
// child
dup2(fd[i][1],1);
close(fd[i][0]);
close(fd[i][1]);
philosopher(i);
_exit(0);
}
else if(pids[i]>0)
{
// parent
dup2(fd[i][0],0);
close(fd[i][0]);
close(fd[i][1]);
}
}
// wait for child processes to end
for(i=0;i<N;++i) waitpid(pids[i],NULL,0);
return 0;
}
void philosopher(int i)
{
while(1)
{
sleep(1);
take_spoon(i);
sleep(2);
put_spoon(i);
sleep(1);
}
}
void take_spoon(int i)
{
sem_wait(&spoon);
state[i] = HUNGRY;
printf("philosopher %d is hungry\n",i+1);
test(i);
sem_post(&spoon);
sem_wait(&phil[i]);
}
void put_spoon(int i)
{
sem_wait(&spoon);
state[i] = THINKING;
printf("philosopher %d puts down spoon %d and %d hin\n",i+1,LEFT+1,i+1);
printf("philosopher %d thinks\n",i+1);
test(LEFT);
test(RIGHT);
sem_post(&spoon);
}
void test(int i)
{
if( state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
{
state[i] = EATING;
printf("philosopher %d takes spoon %d and %d\n",i+1,LEFT+1,i+1);
printf("philosopher %d eats\n",i+1);
sem_post(&phil[i]);
}
}
Thank you in advance for any help.
Several issues. First is that after fork(), the child process and parent process do not share memory. This is one of the primary differences between a thread and a process. Each process has its own virtual address space. Whatever you want the philosophers to share, you have to explicitly do that by creating shared memory. It seems you intended your global variables to be shared among all the processes. (Note that there are some things shared, such as open file descriptors, and the child does get a copy of the variables from the parent, initialized to the values that were assigned to them at the time of the fork() call.)
Second, you have some confusingly unnecessary variables. In particular, the pipes do not serve any real purpose. The stdout for each of the processes will go to the console screen already, without the need for trying to pipe them back to the parent. This is because the child process already inherits the open file descriptors of the parent, so the child will already be using the same stdout as the parent. In addition, the phil_num, and num variables were unused, and the i. pid and pids variables seemed to be needlessly made global.
Third, you failed to initialize your semaphores. The default initialization as a global variable probably leaves the semaphore "useable" but with a 0 initial value, meaning sem_wait() on it will just block. In your case, you need those semaphores in shared memory, so a call to sem_init() is mandatory anyway (to indicate it is going to be shared between multiple processes), and the call gives you a chance to properly initialize the semaphore with a value of 1 so that the initial sem_wait() call has a chance to return.
After adjusting the globals down to what really needs to be shared, they can be bundled together into a structure. Then, a global pointer can be created for the shared data.
struct shared_data {
sem_t spoon;
sem_t phil[N];
int state[N];
};
struct shared_data *shared;
void initialize_shared(); /* at program start */
void finalize_shared(); /* at program end */
One way to create shared memory is to use mmap(). After the memory is created, the data should be initialized properly. This includes a call to sem_init() on the semaphores. sem_destroy() is used to clean up a semaphore, and the mapped memory can be released with munmap(). These are done for you when the process exits, but provided for completeness. (You should always check the return values of all the operating system calls you make, but I have elided them for the sake of brevity.)
void initialize_shared()
{
int i;
int prot=(PROT_READ|PROT_WRITE);
int flags=(MAP_SHARED|MAP_ANONYMOUS);
shared=mmap(0,sizeof(*shared),prot,flags,-1,0);
memset(shared,'\0',sizeof(*shared));
sem_init(&shared->spoon,1,1);
for(i=0;i<N;++i) sem_init(&shared->phil[i],1,1);
}
void finalize_shared()
{
int i;
for(i=0;i<N;++i) sem_destroy(&shared->phil[i]);
munmap(shared, sizeof(*shared));
}
Your main() implementation does not really change, except you need to add local variables for the ones that were needlessly global, as well as call initialize_shared() and optionally finalize_shared(). Also, remove all the code related to pipe().
int main(void)
{
int i;
pid_t pid, pids[N]; // process ids
initialize_shared();
for(i=0;i<N;++i)
{
pid = fork();
if(pid==0)
{
// child
philosopher(i);
_exit(0);
}
else if(pid>0)
{
// parent
pids[i] = pid;
printf("pids[%d]=%d\n",i,pids[i]);
}
else
{
perror("fork");
_exit(0);
}
}
// wait for child processes to end
for(i=0;i<N;++i) waitpid(pids[i],NULL,0);
finalize_shared();
return 0;
}
Note that your program never really exits on its own, since philosopher() is implemented as an infinite loop.

Resources