I wrote the following code for the famous sleeping barber problem, but now I found out i had to use memory mapped files instead of global variables. How Can I do that?I have no idea about memory mapped files.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_CUSTOMERS 5
void *customer(void *num);
void *barber(void *);
// CWait is used to make the customer to wait until the barber is done cutting his/her hair.
sem_t CWait;
// waitingRoom Limits the # of customers allowed to enter the waiting room at one time.
sem_t waitingRoom;
// barberChair ensures mutually exclusive access to the barber chair.
sem_t barberChair;
// barberPillow is used to allow the barber to sleep until a customer arrives.
sem_t barberPillow;
// Flag to stop the barber thread when all customers have been serviced.
int allDone = 0;
int main(int argc, char *argv[])
{
pthread_t btid;
pthread_t tid[MAX_CUSTOMERS];
int i, numChairs;
int Number[MAX_CUSTOMERS];
numChairs = MAX_CUSTOMERS; //number of chairs will be equal to max num of costumers
printf("A solution to the sleeping barber problem using semaphores.\n");
for (i = 0; i < MAX_CUSTOMERS; i++) {
Number[i] = i;
}
sem_init(&waitingRoom, 0, numChairs);
sem_init(&barberChair, 0, 1);
sem_init(&barberPillow, 0, 0);
sem_init(&CWait, 0, 0);
// Create the barber.
pthread_create(&btid, NULL, barber, NULL);
// Create the customers.
for (i = 0; i < MAX_CUSTOMERS; i++) {
pthread_create(&tid[i], NULL, customer, (void *)&Number[i]);
}
// Join each of the threads to wait for them to finish.
for (i = 0; i < MAX_CUSTOMERS; i++) {
pthread_join(tid[i],NULL);
}
// When all of the customers are finished, kill the barber thread.
allDone = 1;
sem_post(&barberPillow); // Wake the barber so he will exit.
pthread_join(btid,NULL);
return 0;
}
void *customer(void *number) {
int num = *(int *)number; // Leave for the shop and take some random amount of time to arrive.
sleep(1);
printf("Customer %d arrived at barber shop.\n", num); // Wait for space to open up in the waiting room...
sem_wait(&waitingRoom);
printf("Customer %d entering waiting room.\n", num); // Wait for the barber chair to become free.
sem_wait(&barberChair); // The chair is free so give up your spot in the waiting room.
sem_post(&waitingRoom); // Wake up the barber...
printf("Customer %d waking the barber.\n", num);
sem_post(&barberPillow); // Wait for the barber to finish cutting your hair.
sem_wait(&CWait); // Give up the chair.
sem_post(&barberChair);
printf("Customer %d leaving barber shop.\n", num);
}
void *barber(void *junk)
{
// While there are still customers to be serviced... Our barber is omniscient and can tell if there are customers still on the way to his shop.
while (!allDone) { // Sleep until someone arrives and wakes you..
printf("The barber is sleeping\n");
sem_wait(&barberPillow); // Skip this stuff at the end...
if (!allDone)
{ // Take a random amount of time to cut the customer's hair.
printf("The barber is cutting hair\n");
sleep(1);
printf("The barber has finished cutting hair.\n"); // Release the customer when done cutting...
sem_post(&CWait);
}
else {
printf("The barber is going home for the day.\n");
}
}
}
Using memory mapped files to share entirely within a single processes is a bit strange, but is certainly doable.
Let's say you need to share a read-write variable of type some_type_t named var_name.
First use the shm_open call:
var_fd = shm_open("var_name", O_CREAT, S_IRUSR | S_IWUSR)
This creates a new file descriptor for our variable.
Next we allocate the space for the variable:
some_type_t *var_ptr;
var_ptr = mmap(NULL, sizeof(some_type_t), PROT_READ | PROT_WRITE, MAP_PRIVATE, var_fd, 0);
You can now access the variable through *var_ptr; e.g. *var_ptr = 42
You can even skip the shm_open call and just do:
var_ptr = mmap(NULL, sizeof(some_type_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0)
I left out error checking and deallocating the variable once you are done.
Related
Here is my code. The sum part is not working. I need some controls for that but I couldn't do it.
I tried make number variable number=-1, but that also didn't work and I had an infinite loop.
By the way this is my first question that i ask here, so i can make mistakes. Sorry for that.
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdbool.h>
int number = 0, sum = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *threadFunction1()
{
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
}
void *threadFunction2()
{
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t thread1, thread2;
int case1, case2;
case1 = pthread_create(&thread1, NULL, threadFunction1, NULL);
case2 = pthread_create(&thread2, NULL, threadFunction2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("It's over..\n");
pthread_mutex_destroy(&mutex);
return 0;
}
Here is the output
An immediately obvious issue is that threadFunction1 locks the mutex
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
but never unlocks it. It is impossible to share a resource when one thread takes complete control over it.
The next issue is that the locking and unlocking of the mutex occurs outside of the while loop.
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
This means whichever thread gets CPU time first will lock the mutex, and enter a potentially long running loop, only unlocking the mutex when that loop ends:
If threadFunction1 is the first to lock the mutex, this loop lasts until the user enters 0, wherein the loop is broken and the thread is terminated. After this, threadFunction2 never gets a turn, due to the lack of an unlock.
If threadFunction2 is the first to lock the mutex, this loop is broken after during its first iteration, as number is initialized to 0. After this the thread is terminated, and threadFunction1 would get a turn, since the mutex is unlocked.
The final issue is that a single mutex alone is not the correct tool to use here.
Even moving the locks and unlocks inside the loop, so that each thread has a chance to lock the mutex, do some work, and then unlock, there is no guarantee that both threads will get equal access to the lock.
while (true)
{
pthread_mutex_lock(&mutex);
sum += number;
printf("Sum is:%d\n", sum);
pthread_mutex_unlock(&mutex);
if (number == 0) break;
}
In fact, the opposite will probably occur. By default, it is very likely for one thread to be granted some CPU time, lock the mutex, do some work, unlock the mutex, and with its remaining time immediately lock the mutex again.
So we need a way to make two threads evenly share a resource.
One way is, instead of using a mutex, to use two semaphores to create a lockstep. This means one thread waits to for a semaphore which the other thread posts, and vice versa.
Note that in main we start the to_read semaphore with a value of 1, meaning the scanning thread effectively "goes first".
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
static int number = 0;
static int sum = 0;
static sem_t to_read;
static sem_t to_write;
static void *scanning(void *arg) {
while (true) {
sem_wait(&to_read);
printf("Enter a number: ");
if (1 != scanf("%d", &number))
number = 0;
sem_post(&to_write);
if (number == 0)
break;
}
return NULL;
}
static void *adding(void *arg) {
while (true) {
sem_wait(&to_write);
sum += number;
printf("Sum is: %d\n", sum);
sem_post(&to_read);
if (number == 0)
break;
}
return NULL;
}
int main(void) {
pthread_t thread1, thread2;
sem_init(&to_read, 0, 1);
sem_init(&to_write, 0, 0);
pthread_create(&thread1, NULL, scanning, NULL);
pthread_create(&thread2, NULL, adding, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
puts("It's over...");
sem_destroy(&to_read);
sem_destroy(&to_write);
}
Note that this will surely perform worse than a single threaded loop in main, doing the same amount of work, due to the overhead of context switching. That said, it is just a toy example.
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.
I want a routine to be done by multiple threads, once they are created they need their work to be all finished before copying their calculated things. So a thread is on cond_wait once it has its work done.
A piece of code that works now:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_RAYCAST_THREADS 2
typedef struct s_thread_env
{
int id;
pthread_t thread;
int work_done;
void *shared_data;
} t_thread_env;
typedef struct s_shared_data
{
t_thread_env *tab_thread_env;
int max_thread;
int all_work_done;
pthread_mutex_t mutex;
pthread_cond_t cond;
int stop;
} t_shared_data;
void set_threads_again(int id, t_shared_data *shared_data)
{
int i;
shared_data->all_work_done = 0;
i = -1;
while (++i < shared_data->max_thread)
shared_data->tab_thread_env[i].work_done = 0;
//i = -1;
//while (++i < shared_data->max_thread)
//{
//if (i != id)
//{
//printf("cond_signal to thread %i\n", i);
//pthread_cond_signal(&shared_data->cond);
//}
//}
pthread_cond_broadcast(&shared_data->cond);
}
void wait_or_signal(t_thread_env *thread_env, t_shared_data *shared_data)
{
int i;
i = 0;
while (i < shared_data->max_thread && shared_data->tab_thread_env[i].work_done)
i++;
if (i == shared_data->max_thread)
{
printf(" allworkdone sent by thread %i\n", thread_env->id);
//printf(" copy_screenpixels() by thread %i\n", thread_env->id);
set_threads_again(thread_env->id, shared_data);
}
else
{
printf(" thread number %i is waiting for other threads\n", thread_env->id);
pthread_cond_wait(&shared_data->cond, &shared_data->mutex);
printf("ENFIN ! thread number %i woke up from condwait\n", thread_env->id);
}
}
void *routine(void *arg)
{
t_thread_env *thread_env;
t_shared_data *shared_data;
int stop;
thread_env = (t_thread_env *)arg;
shared_data = (t_shared_data *)thread_env->shared_data;
pthread_mutex_lock(&shared_data->mutex);
while (!shared_data->stop)
{
printf("new frame> thread_id = %i, thread_env->work_done = %i\n", thread_env->id, thread_env->work_done);
pthread_mutex_unlock(&shared_data->mutex);
printf(" raycast() in routine thread %i\n", thread_env->id);
pthread_mutex_lock(&shared_data->mutex);
thread_env->work_done++;
wait_or_signal(thread_env, shared_data);
}
pthread_mutex_unlock(&shared_data->mutex);
return (0);
}
void init_thread_env(t_shared_data *shared_data, int i)
{
t_thread_env *thread_env;
thread_env = &shared_data->tab_thread_env[i];
thread_env->id = i;
thread_env->shared_data = shared_data;
if (pthread_create(&thread_env->thread, NULL, routine, thread_env) != 0)
printf("Error pthread_create for %i\n", i);
}
void free_all(t_shared_data *shared_data)
{
int i;
pthread_mutex_lock(&shared_data->mutex);
shared_data->stop = 1;
pthread_mutex_unlock(&shared_data->mutex);
i = -1;
while (++i < shared_data->max_thread)
pthread_join(shared_data->tab_thread_env[i].thread, NULL);
printf("\nEND\n\n");
//free etc
}
int main()
{
int i;
t_shared_data *shared_data;
shared_data = (t_shared_data*)malloc(sizeof(t_shared_data)); // if (!shared data){free etc}
shared_data->max_thread = MAX_RAYCAST_THREADS;
pthread_mutex_init(&shared_data->mutex, 0);
pthread_cond_init(&shared_data->cond, 0);
shared_data->tab_thread_env = (t_thread_env*)malloc(sizeof(t_thread_env) * shared_data->max_thread);
i = -1;
while (++i < shared_data->max_thread)
init_thread_env(shared_data, i);
while (1)
sleep(1); //program is turning
free_all(shared_data);
return (0);
}
The correct output:
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
new frame> thread_id = 1, thread_env->work_done = 0
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
allworkdone sent by thread 1
cond_signal to thread 0
new frame> thread_id = 1, thread_env->work_done = 0
ENFIN ! thread number 0 woke up from condwait
new frame> thread_id = 0, thread_env->work_done = 0
raycast() in routine thread 0
thread number 0 is waiting for other threads
raycast() in routine thread 1
Thank you for reading me, have a good day!
EDIT: I made a more readable and compilable version with only 1 mutex (old version: https://pastebin.com/4zMyBJi2).
EDIT2: deleted some parts of the original post, and tried to avoid every data races, my code still has some (as it still does not work). But I think I am close to get something working
EDIT3: Ok it is working now, I edited the code. The main issue was my disastrous use of the shared_data variables.
I tried to make my raycasting threads work using 1 call of
pthread_create for each thread (in an initialisation function). Is
it possible to do it?
Each successful call to pthread_create creates exactly one thread, so this is the only way to do it. But do not get confused between threads' start functions and threads themselves. Multiple threads can be created to run the same thread function, but this requires multiple calls to pthread_create, one for each thread.
I guess it is better (for performances) to do
it in this way (rather than an enormous amount of pthread_create and
pthread_join calls), is this correct?
Having chosen to use a certain number of threads to do certain pieces of work, the number of pthread_create calls is already determined. If you have performance concerns then they should be about how many threads to use, the details of the work they are to perform, and the nature and granularity of their synchronization.
In order to make it happen, the last thread (number n) to finish his
job has to tell the other ones that every thread has finished, so
there is a pthread_cond_wait for the (n - 1) first threads, and the
last thread (number n) calls pthread_cond_signal for each (n - 1)
first ones. Each thread has his own mutex.
That seems a little overkill, even if you can make it technically correct. It doesn't make much sense to have a mutex per thread, because mutexes are useful only when different threads use the same one. It may make sense to have different mutexes for protecting different shared resources, however. You would probably want CVs for some of those, but not all of them.
This appears to be (at least one area) where your code is failing. Your threads are not properly synchronized because they all rely on different mutexes to protect the same resources. It's not clear to me whether it makes sense for your program to have any more than just one mutex, but I would start by reducing your usage to that.
So I have been all day working on this project, I was checking the errors that I have and as I was fixing them I came to the last part which is the warnings.
the warnings that I am getting are the same: Passing argument 1 of '' from compatible pointer type [enabled by default]
note: expected 'union sem_t*' but argument is of type 'void * ()(void)'
please just help me out. I have been stuck on this for several hours now. thanks in advance!
I took off the & from sem_init in both customers and barbers, but it did not work.
#include <unistd.h> //Provides API for POSIX(or UNIX) OS for system calls
#include <stdio.h> //Standard I/O Routines
#include <stdlib.h> //For exit() and rand()
#include <pthread.h> //Threading APIs
#include <semaphore.h> //Semaphore APIs
#define MAX 30 //Maximum no. of customers for simulation
#define MAX_BARBERS 1000
sem_t customer; //Semaphore
sem_t barber; //Semaphore
sem_t mutex; //Semaphore for providing mutially exclusive access
void *barbers(void *param); //Thread Function
void *customers(void *param); //Thread Function
int num_chairs;
int barbers_total;
int customers_total;
int serveMeNext; //Index to choose a candidate for cutting hair
void wait(); //Randomized delay function
int main(int argc, char *argv[]){
pthread_t barberid[MAX_BARBERS];
pthread_t customerid[MAX]; //Thread declaration
int i = 0;
if(argc != 4){
printf("Enter 3 arguments (Number of chairs, barbers, customers)\n");
exit(0);
}
num_chairs = atoi(argv[1]);
barbers_total = atoi(argv[2]);
customers_total = atoi(argv[3]);
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
/*Semaphore initialization*/
sem_init(&mutex,0,1);
sem_init(customers,0,0);
sem_init(barbers,0,0);
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
/*Barber thread initialization*/
printf("!!Barber Shop Opens!!\n");
for(i = 0; i <= barbers_total; i++){ //Creation of barbers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
pthread_create(&barberid[i], NULL, barbers, (void*)&i);
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
sleep(1);
}
/*Customer thread initialization*/
for(i = 0; i <= customers_total; i++){ //Creation of Customer Threads
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
pthread_create(&customerid[i],NULL,customers,(void*)&i);
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
wait(); //Create customers in random interval
}
for(i = 0; i <= MAX; i++) //Waiting till all customers are dealt with
pthread_join(customerid[i],NULL);
printf("!!Barber Shop Closes!!\n");
exit(EXIT_SUCCESS); //Exit abandoning infinite loop of barber thread
}
void *customers(void *param){ /*Customer Process*/
int mySeat, B;
static int count = 0; //Counter of No. of customers
int numberOfFreeSeats = num_chairs; //Counter for Vacant seats in waiting room
int seatPocket[num_chairs]; //To exchange pid between customer and barber
int sitHereNext = 0; //Index for next legitimate seat
serveMeNext = 0;
sem_wait(&mutex); //Lock mutex to protect seat changes
count++; //Arrival of customer
printf("Customer-%d entered shop. ",count);
if(numberOfFreeSeats > 0){
--numberOfFreeSeats; //Sit on chairs on waiting room
printf("Customer-%d Sits In Waiting Room.\n",count);
sitHereNext = (++sitHereNext) % num_chairs; //Choose a vacant chair to sit
mySeat = sitHereNext;
seatPocket[mySeat] = count;
sem_post(&mutex); //Release the seat change mutex
sem_post(barbers); //Wake up one barber
sem_wait(customers); //Join queue of sleeping customers
sem_wait(&mutex); //Lock mutex to protect seat changes
B = seatPocket[mySeat]; //Barber replaces customer PID with his own PID
numberOfFreeSeats++; //Stand Up and Go to Barber Room
sem_post(&mutex); //Release the seat change mutex
/*Customer is having hair cut by barber 'B'*/
}else{
sem_post(&mutex); //Release the mutex and customer leaves without haircut
printf("Customer-%d Finds No Seat & Leaves.\n",count);
}
pthread_exit(0);
}
void *barbers(void *param){ /*Barber Process*/
int index = *(int *)(param);
int myNext, C;
int worktime;
int seatPocket[num_chairs]; //To exchange pid between customer and barber
printf("Barber-%d joins shop. ",index);
while(1){ /*Infinite loop*/
printf("Barber-%d Gone To Sleep.\n",index);
sem_wait(barbers); //Join queue of sleeping barbers
sem_wait(&mutex); //Lock mutex to protect seat changes
serveMeNext = (++serveMeNext) % MAX; //Select next customermyNext = serveMeNext;
C = seatPocket[myNext]; //Get selected customer's PID
seatPocket[myNext] = pthread_self(); //Leave own PID for customer
sem_post(&mutex);
sem_post(customers); //Call selected customer
/*Barber is cutting hair of customer 'C'*/
printf("Barber-%d Wakes Up & Is Cutting Hair Of Customer-%d.\n",index,C);
worktime = (rand() % 3) + 1;
printf("Barber-%d Finished.\n",index);
sleep(worktime);
}
}
void wait(){ /*Generates random number between 50000 to 250000*/
int x = rand() % (250000 - 50000 + 1) + 50000;
srand(time(NULL));
usleep(x); //usleep halts execution in specified miliseconds
}
I marked with """ the places where I think I am wrong because of the research that I have been doing.
From the warning, it is evident that you were passing a pointer to a function instead of the sem_t type that it expects.
You seem to have had a typo with customer and barber.
The sem_init must be
sem_init(&customer,0,0);
sem_init(&barber,0,0);
And your sem_post must be
sem_post(&customer);
sem_post(&barber);
Also, don't forget to compile this with -lpthread or -pthread
I am having a problem in the synchronisation of threads. I m trying to implement sleeping barber problem in a different approach.
When i run the code the threads run in a completely vague manner.
When i add join to the threads the processes run one by one which is not required.
I know the solutions to the sleeping barber problem but can anybody tell me what is the problem with this code.?
Thank You
#include<stdio.h>
#include<pthread.h>
#include<time.h>
#include <unistd.h>
#include<semaphore.h>
#define n 1
#define n1 50
int status[n];
int b=0;
sem_t mutex;
sem_t barber;
void *barb()
{
printf("Barber Sleeping\n");
b=1;
sem_wait(&barber);
printf("Barber woke up\n");
sleep(1);
b=0;
}
void *handler(void *ptr)
{
int x;
x = *((int *) ptr);
int flag=0;
int i=0;
int cnt=0;
for(i=0;i<n;i++)
{
if(status[i]==1)
{
flag=1;
cnt++;
}
}
printf("Count=%d",cnt);
if(cnt==n)
{
printf("%d Customer Returned\n",x);
return 0;
}
if(flag==1)
{
status[x]=1;
printf("%d Customer waiting\n",x);
sem_wait(&mutex);
}
if(b==1)
{
printf("Customer %d woke up barber",x);
sem_post(&barber);
}
printf("Cutting Hair of customer %d\n",x);
status[x]=1;
sleep(5);
flag=0;
for(i=0;i<n;i++)
{
if(status[i]==1)
{
flag=1;
}
}
status[x]=0;
printf("Finished cutting Hair of customer %d\n",x);
if(flag==1)
sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, n);
sem_init(&barber, 0, 1);
pthread_t thread[n1];
pthread_t barber;
int i=0;
for(i=0;i<n;i++)
{
status[i]=0;
}
pthread_create(&barber,NULL,barb,NULL);
pthread_join(barber,NULL);
for(i=0;i<n1;i++)
{
sleep(1);
printf("Customer entered %d\n",i);
pthread_create(&thread[i], NULL, handler, (void *)&i);
//pthread_join(thread[i],NULL);
}
for(i=0;i<n1;i++)
{
//pthread_join(thread[i],NULL);
}
//sem_post(&barber);
}
I have the code to help you
#define _REENTRANT
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
// The maximum number of customer threads.
#define MAX_CUSTOMERS 25
// Function prototypes...
void *customer(void *num);
void *barber(void *);
void randwait(int secs);
// Define the semaphores.
// waitingRoom Limits the # of customers allowed
// to enter the waiting room at one time.
sem_t waitingRoom;
// barberChair ensures mutually exclusive access to
// the barber chair.
sem_t barberChair;
// barberPillow is used to allow the barber to sleep
// until a customer arrives.
sem_t barberPillow;
// seatBelt is used to make the customer to wait until
// the barber is done cutting his/her hair.
sem_t seatBelt;
// Flag to stop the barber thread when all customers
// have been serviced.
int allDone = 0;
int main(int argc, char *argv[]) {
pthread_t btid;
pthread_t tid[MAX_CUSTOMERS];
long RandSeed;
int i, numCustomers, numChairs;
int Number[MAX_CUSTOMERS];
// Check to make sure there are the right number of
// command line arguments.
if (argc != 4) {
printf("Use: SleepBarber <Num Customers> <Num Chairs> <rand seed>\n");
exit(-1);
}
// Get the command line arguments and convert them
// into integers.
numCustomers = atoi(argv[1]);
numChairs = atoi(argv[2]);
RandSeed = atol(argv[3]);
// Make sure the number of threads is less than the number of
// customers we can support.
if (numCustomers > MAX_CUSTOMERS) {
printf("The maximum number of Customers is %d.\n", MAX_CUSTOMERS);
exit(-1);
}
printf("\nSleepBarber.c\n\n");
printf("A solution to the sleeping barber problem using semaphores.\n");
// Initialize the random number generator with a new seed.
srand48(RandSeed);
// Initialize the numbers array.
for (i=0; i<MAX_CUSTOMERS; i++) {
Number[i] = i;
}
// Initialize the semaphores with initial values...
sem_init(&waitingRoom, 0, numChairs);
sem_init(&barberChair, 0, 1);
sem_init(&barberPillow, 0, 0);
sem_init(&seatBelt, 0, 0);
// Create the barber.
pthread_create(&btid, NULL, barber, NULL);
// Create the customers.
for (i=0; i<numCustomers; i++) {
pthread_create(&tid[i], NULL, customer, (void *)&Number[i]);
}
// Join each of the threads to wait for them to finish.
for (i=0; i<numCustomers; i++) {
pthread_join(tid[i],NULL);
}
// When all of the customers are finished, kill the
// barber thread.
allDone = 1;
sem_post(&barberPillow); // Wake the barber so he will exit.
pthread_join(btid,NULL);
}
void *customer(void *number) {
int num = *(int *)number;
// Leave for the shop and take some random amount of
// time to arrive.
printf("Customer %d leaving for barber shop.\n", num);
randwait(5);
printf("Customer %d arrived at barber shop.\n", num);
// Wait for space to open up in the waiting room...
sem_wait(&waitingRoom);
printf("Customer %d entering waiting room.\n", num);
// Wait for the barber chair to become free.
sem_wait(&barberChair);
// The chair is free so give up your spot in the
// waiting room.
sem_post(&waitingRoom);
// Wake up the barber...
printf("Customer %d waking the barber.\n", num);
sem_post(&barberPillow);
// Wait for the barber to finish cutting your hair.
sem_wait(&seatBelt);
// Give up the chair.
sem_post(&barberChair);
printf("Customer %d leaving barber shop.\n", num);
}
void *barber(void *junk) {
// While there are still customers to be serviced...
// Our barber is omnicient and can tell if there are
// customers still on the way to his shop.
while (!allDone) {
// Sleep until someone arrives and wakes you..
printf("The barber is sleeping\n");
sem_wait(&barberPillow);
// Skip this stuff at the end...
if (!allDone) {
// Take a random amount of time to cut the
// customer's hair.
printf("The barber is cutting hair\n");
randwait(3);
printf("The barber has finished cutting hair.\n");
// Release the customer when done cutting...
sem_post(&seatBelt);
}
else {
printf("The barber is going home for the day.\n");
}
}
}
void randwait(int secs) {
int len;
// Generate a random number...
len = (int) ((drand48() * secs) + 1);
sleep(len);
}