Sleeping barber using semaphore - c

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);
}

Related

Producer/Consumer "produce" and "consume" function are not working

For the Producer/Consumer use semaphore in c language
Ask from user whether producer should run or consumer. Producer/consumer shouldn't call each other in your code. The call should be made explicitly from user only.
If producer is called to execute , the buffer should fill one slot. For consumer it should consume one slot.
Your code should make usage of bounded buffer. The capacity of buffer will be decided by user after execution of code.
For every producer/consumer call, the system should generate output how many filled slots are available and how many free slots are available in your buffer array.
Producer should be notified that it can't make more products if the array is full and consumer should be notified if there is no available slot to be consumed.
My produce and consume function are not working it just stucks after entering 'P' or 'C'
`
#include <stdio.h>
#include <semaphore.h>
#define MAX_BUFFER_SIZE 100
int buffer[MAX_BUFFER_SIZE];
int capacity;
int count = 0;
sem_t full;
sem_t empty;
sem_t mutex;
void produce() {
sem_wait(&empty);
sem_wait(&mutex);
buffer[count] = 1;
count++;
printf("Produced 1 item, %d slots available\n", capacity - count);
sem_post(&mutex);
sem_post(&full);
}
void consume() {
sem_wait(&full);
sem_wait(&mutex);
count--;
printf("Consumed 1 item, %d slots available\n", capacity - count);
sem_post(&mutex);
sem_post(&empty);
}
int main() {
sem_init(&full, 0, 0);
sem_init(&empty, 0, capacity);
sem_init(&mutex, 0, 1);
printf("Enter capacity of buffer: ");
scanf("%d", &capacity);
char choice;
while (1) {
printf("Enter P to produce or C to consume: ");
scanf(" %c", &choice);
if (choice == 'P') {
produce();
} else if (choice == 'C') {
consume();
} else {
break;
}
}
sem_destroy(&full);
sem_destroy(&empty);
sem_destroy(&mutex);
return 0;
}
`
I tried to enter 'p' or 'C' it just does nothing
Terminal Output it just stuck

I am getting warnings for semaphores

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

How to avoid worker threads being stuck in sem_wait?

I am new to semaphores and wanted to know how to avoid a situation where my worker thread (in a multiple worker single producer problem) is stuck in sem_wait(&full). I also have a mutex lock after this but I doubt that, that is where it is stuck. I know all my tasks are being completed but the threads are not exiting. The producer thread in my program stops sending data once all tasks are done.
For reference... the producer thread...
while (i<number_of_tasks)
{
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
sem_wait(&empty);
pthread_mutex_lock(&mutex);
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
i++;
//printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
And ...the worker thread function
int i, item, index;
TASK task;
index = *((int*)arg);
int notasks1;
for (i=number_of_tasks; i > 0; i--) {
//previous code
sem_wait(&full);
pthread_mutex_lock(&mutex);
task=tasks[out];
out = (out+1)%buff_size;
//completing task code...
counter++;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
printf("Worker thread %d has terminated and completed %d tasks\n",index,notasks1);
return NULL;
the full code... for reference
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include </usr/include/semaphore.h>
// for sleep
#include <unistd.h>
#include "Mandel.h"
#include "draw.h"
#define BUFF_SIZE 10 /* total number of slots */
#define NP 1 /* total number of producers */
#define NC 5 /* total number of consumers */
#define NITERS IMAGE_HEIGHT/10 /* number of items produced/consumed */
//int buf[BUFF_SIZE]; /* shared var */
//struct task for storing the tasks the current worker thread has to do
typedef struct task
{
int start_row;
int num_of_rows;
} TASK;
TASK* tasks;
int buff_size; //= 7;
//TASK buff[buff_size];
int in=0; /* buf[in%BUFF_SIZE] is the first empty slot */
int out=0; /* buf[out%BUFF_SIZE] is the first full slot */
sem_t full; /* keep track of the number of full spots */
sem_t empty; /* keep track of the number of empty spots */
int number_of_tasks;// = IMAGE_HEIGHT/20;
float *pixels;
int num_of_rows;// = 20;
int counter = 0;
// use correct type here
pthread_mutex_t mutex; /* enforce mutual exclusion to shared data */
/*void *Producer(void *arg)
{
int i =0;
while (i<number_of_tasks)
{
if (counter==number_of_tasks)
break;
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
sem_wait(&empty);
pthread_mutex_lock(&mutex);
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
i++;
if (counter==number_of_tasks)
break;
}
return NULL;
}*/
//function for consumer threads to accesss
void *Consumer(void *arg)
{
int i, item, index;
TASK task;
index = *((int*)arg);//getting index of thread from argument parsing it into int
int notasks1;
//for loop to complete number of tasks per thread
for (i=number_of_tasks; i > 0; i--) {
//defining start_compute and end compute to calculate time per task
struct timespec start_compute, end_compute;
float difftime;
printf("Worker(%d): Start the computation ...\n", index);
clock_gettime(CLOCK_MONOTONIC, &start_compute);
//calling sem wait to wait for producer thread to fill in tasks for worker threads. will wait if buffer is empty
sem_wait(&full);
//calling mutex lock
pthread_mutex_lock(&mutex);
//getting tasks from struct tasks array
task=tasks[out];
//incrementing to next task in buffer so that next thread accesses next task
out = (out+1)%buff_size;
//calculating pixels for image
int x, y;
//printf("start_row... %d, num_of_rows... %d\n", task.start_row, task.num_of_rows);
for (y=task.start_row; y<task.start_row+task.num_of_rows; y++)
{
for (x=0; x<IMAGE_WIDTH; x++)
{
pixels[y*IMAGE_WIDTH+x] = Mandelbrot(x, y);
}
}
//increasing counter to check if all tasks are done
counter++;
pthread_mutex_unlock(&mutex);
sem_post(&empty);//informing a producer that a task has been taken out and if tasks are left buffer is empty to add tasks
//calculating end compute and posting
clock_gettime(CLOCK_MONOTONIC, &end_compute); //end time values for the child processes
difftime = (end_compute.tv_nsec - start_compute.tv_nsec)/1000000.0 + (end_compute.tv_sec - start_compute.tv_sec)*1000.0;
printf("Worker(%d):\t...completed. Elapse time = %f ms\n",index, difftime);\
notasks1++;
printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
printf("Worker thread %d has terminated and completed %d tasks\n",index,notasks1);
return NULL;
}
int main(int argc, char* args[])
{
buff_size = atoi(args[3]);
num_of_rows = atoi(args[2]);
number_of_tasks = IMAGE_HEIGHT/num_of_rows;
int number_of_workers;
number_of_workers = atoi(args[1]);
struct timespec start_time, end_time;
printf("number_of_tasks...%d\n", number_of_tasks);
pthread_t idP, idC;
int index;
sem_init(&full, 0, 0);//initializing full to zero so that consumer thread knows buffer is empty and waits for producer thread
sem_init(&empty, 0, buff_size);//initializing empty to buffer size so that producer knows to add that many tasks
pthread_mutex_init(&mutex, NULL);
int i = 0;
pixels = (float *) malloc(sizeof(float) * IMAGE_WIDTH * IMAGE_HEIGHT);//assigning pixels memory
//tasks = (TASK*) malloc (sizeof(TASK) *buff_size);
//pthread_create(&idP, NULL, Producer, NULL);
for(index=0; index<number_of_workers/*5*/; index++)
{
printf("Worker(%d): Start up. Wait for task!\n", index);
pthread_create(&idC, NULL, Consumer, (void*)&index);//creating worker threads to go to consumer function sending their index
}
tasks = (TASK*) malloc (sizeof(TASK) *buff_size);
//master/producer thread work
while (i<number_of_tasks)
{
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
//calling sem wait if buffer is not empty
sem_wait(&empty);
pthread_mutex_lock(&mutex);
//adding tasks to struct task tasks array for worker/consumer threads to use
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
//incrementing full so that worker threads know that buffer is not empty
i++;
//printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
//pthread_exit(NULL);
//waiting for all threads to exit
//pthread_join(idC, NULL);
//printing image
printf("Draw the image\n");
DrawImage(pixels, IMAGE_WIDTH, IMAGE_HEIGHT, "Mandelbrot demo", 3000);
return 0;
}
How to stop the worker thread from being stuck in the loop?
I know the program continues on and displays the correct result but when I call pthread_join it keeps on waiting... obviously. How to solve the issue?

using memory mapped files for in global variables

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.

Synchronization not working properly when Multi-threading in C

I am trying to create a simple bar program where a certain amount of customers can be inside the bar at the same time. And every time a customer asks for a beer, then the bartender should server the customer a beer.
For some reason in my program, the bar tender serves the customer after he/she leaves the bar
How can I fix this? Any suggestions?
Here is my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> //for declaration of exit()
#include <semaphore.h> //to use semaphores
pthread_mutex_t serve = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
sem_t OktoEnter;
int cid = 0;
void EnterBar();
void OrderStart();
void ServeStart();
void ServeDone();
void OrderDone();
void DrinkBeer();
void LeaveBar();
void* Bartender(void *arg)
{
ServeStart();
ServeDone();
}
void* Customer(void* id)
{
cid =(int)id;
EnterBar();
LeaveBar();
}
void EnterBar(){
printf("Customer %d enters the bar.\n", cid);
int cups;
pthread_t order;
for(cups=0;cups<(cid%3+1);cups++){
pthread_mutex_lock(&serve);
OrderStart();
OrderDone();
DrinkBeer();
pthread_mutex_unlock(&serve);
}
//decrease semaphore
}
void OrderStart(){
pthread_t order;
printf("Customer %d asks for beer.\n", cid);
int rc = pthread_create(&order, NULL, Bartender, NULL);
}
void OrderDone(){
printf("Customer %d gets the beer.\n", cid);
}
void DrinkBeer(){
printf("Customer %d drinks the beer.\n", cid);
}
void LeaveBar(){
printf("Customer %d leaves the bar.\n", cid);
//increase semaphore
}
void ServeStart(){
printf("Bartender starts to serve customer %d.\n", cid);
}
void ServeDone(){
printf("Bartender is done serving customer %d.\n", cid);
}
int main (int argc, char *argv[])
{
int t;
long rc;
int num_customers = atoi(argv[1]); //number of customers
int capacity = atoi(argv[2]); //bar capacity
if(num_customers > 0 && capacity > 0){
pthread_t threads[num_customers];
if(random() > RAND_MAX / 2)
usleep(1);
//rc = sem_init(&sem1,0,capacity);
rc = pthread_barrier_init(&barrier1, NULL, num_customers);
for(t=0; t< num_customers; t++){
printf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, Customer, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %ld\n", rc);
exit(-1);
}
}
}
else{
printf("ERROR: Both parameters should be a valid positive numbers.");
exit(-1);
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
I worked all around changing the functions but it does not work properly.
To be honest it is not clear if you originally had a clear idea of where you were going with this to begin with or just got so lost in the weeds you started throwing things against the wall to see what would stick. Sorry for the mixed metaphors.
You had a bunch of small errors (e.g. sometimes cid was a param, sometimes it was a global shared by all threads) and a bunch of unnecessary stuff I assume was detritus from experimenting.
I stripped this down a very basic threaded program and I'll leave it at that since I really don't understand where exactly you want to take it. Get the simple stuff working first, layer on the complexity later. Good luck.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void EnterBar();
void OrderStart();
void ServeStart();
void ServeDone();
void OrderDone();
void DrinkBeer();
void LeaveBar();
void Bartender(int cid)
{
ServeStart(cid);
ServeDone(cid);
}
void* Customer(void* id)
{
int cid = (int) id;
EnterBar(cid);
LeaveBar(cid);
}
void EnterBar(int cid)
{
printf("Customer %d enters the bar.\n", cid);
int cups;
pthread_t order;
OrderStart(cid);
OrderDone(cid);
DrinkBeer(cid);
}
void OrderStart(int cid)
{
printf("Customer %d asks for beer.\n", cid);
Bartender(cid);
}
void OrderDone(int cid)
{
printf("Customer %d gets the beer.\n", cid);
}
void DrinkBeer(int cid)
{
printf("Customer %d drinks the beer.\n", cid);
}
void LeaveBar(int cid)
{
printf("Customer %d leaves the bar.\n", cid);
}
void ServeStart(int cid)
{
printf("Bartender starts to serve customer %d.\n", cid);
}
void ServeDone(int cid)
{
printf("Bartender is done serving customer %d.\n", cid);
}
int main (int argc, char *argv[])
{
int t;
long rc;
if (argc < 3)
{
printf("use the parameters\n");
exit(1);
}
int num_customers = atoi(argv[1]); //number of customers
int capacity = atoi(argv[2]); //bar capacity
if (num_customers <= 0 || capacity <= 0)
{
printf("ERROR: Both parameters should be a valid positive numbers.");
exit(1);
}
pthread_t threads[num_customers];
for (t = 0; t < num_customers; t++)
{
printf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, Customer, (void* )t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %ld\n", rc);
exit(1);
}
}
for (t = 0; t < num_customers; t++)
pthread_join(threads[t], NULL);
pthread_exit(NULL);
}
First, this is a great little project in understanding threads and how life is multi-threaded.
There are problems with the above scenarios. First off, neither of you are keeping track of how many customers are in the bar from your EnterBar() and LeaveBar() functions. In these functions, you will need to keep track of the current bar count. Once the bar is full, you must lock the door so no other customers can enter. Then when a customer leaves the bar, they must unlock the door so at least one more customer can enter. Also, given the complete problem scenario, you should only create one bartender (i.e. one bartender thread) and syncronize with him using pthread_cond_wait/pthread_cond_signal to pour the beer once a customer asks for it. You can't just keep killing off and recreating the bartender for each drink to be poured, and remember only one customer can ask for a beer at a time. This should all be done with pthread_mutex_lock/unlock's.

Resources