Producer-Consumer Problem


Cook cooks pizza and puts that pizza onto shelf. Waiter picks pizza from the shelf and serves it to customers. The shelf can hold three pizza at most at the same time. When the shelf is full, cook wait until picked up; when there is no pizza on the shelf, waiter waits until made.

We use three semaphores to synchronize cook and waiter. cook.c is a producer program. After cooking one pizza and placing it on shelf, it posts semaphore fill and makes shelf increase by 1. waiter.c is a consumer program. After picking a pizza from the shelf, it posts semaphore avail and makes shelf decrease by 1. The value of shelf is the current number of pizza and processes should access it exclusively. Semaphore mutex is response for the mutual exclusion.

Note that shared memory is used in these two programs, you can see more details about shared memory in Section 4.

Use these two programs like this:

$ gcc cook.c -pthread -lrt -o cook
$ gcc waiter.c -pthread -lrt -o waiter
$ ./cook & ./waiter &
/*cook.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>
int main()
{
    const char * name = "shared_memory";
    const char * sema1= "fill";
    const char * sema2= "avail";
    const char * sema3= "mutex";
    int shm_fd;   //shared memory file discriptor
    int * shelf;
    int loop=6;  
    sem_t * fill, * avail, * mutex;
    /* make * shelf shared between processes*/
    //create the shared memory segment
    shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    //configure the size of the shared memory segment
    ftruncate(shm_fd,sizeof(int));
    //map the shared memory segment in process address space
    shelf = mmap(0,sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    /* creat/open semaphores*/
    //cook post semaphore fill after cooking a pizza
    fill = sem_open(sema1, O_CREAT,0666,0);
    //waiter post semaphore avail after picking up a pizza, at the beginning avail=3
    avail = sem_open(sema2, O_CREAT, 0666, 3);
    //mutex for mutual exclusion of shelf
    mutex = sem_open(sema3,O_CREAT,0666,1);
    printf("\nCook: I have started cooking pizza.\n");
    while(loop--){
        sem_wait(avail);
        sleep(rand()%2+1);
        sem_wait(mutex);
        (* shelf)++;
        sem_post(mutex);
        printf("Cook: cook a pizza, there are %d pizza now\n", * shelf);
        sem_post(fill);
    }
    printf("Cook: Time is up. I cooked 6 pizza. %d are left.\n", * shelf);
      /* close and unlink semaphores*/
    sem_close(fill);
    sem_close(avail);
    sem_close(mutex);
    sem_unlink(sema1);
    sem_unlink(sema2);
    sem_unlink(sema3);
      /* close and unlink shared memory*/
      munmap(shelf, sizeof(int));
    close(shm_fd);
    shm_unlink(name);
    return 0;
}
/*waiter.c*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>
int main()
{
    const char * name = "shared_memory";
    const char * sema1= "fill";
    const char * sema2= "avail";
    const char * sema3="mutex";
    int shm_fd; //file descriptor of
    int * shelf;
    int loop=6;
    sem_t * fill, * avail, * mutex;
    /* open the shared memory segment */
    shm_fd = shm_open(name, O_RDWR, 0666);
    /* now map the shared memory segment in the address space of the process*/
    shelf = mmap(0,sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    /* open semaphores*/
    fill = sem_open(sema1, O_CREAT,0666,0);
    avail = sem_open(sema2, O_CREAT, 0666, 3);
    mutex = sem_open(sema3,O_CREAT,0666,1);
    while(loop--){
        sem_wait(fill);
        sleep(rand()%2+1);
        sem_wait(mutex);
        (* shelf)--;
        sem_post(mutex);
        printf("Waiter: I pick up a pizza\n");
        sem_post(avail);
    }
      /* remove semaphores*/
    sem_close(fill);
    sem_close(avail);
    sem_close(mutex);
    sem_unlink(sema1);
    sem_unlink(sema2);
    sem_unlink(sema3);
    /* remove shared memory segment*/
    munmap(shelf, sizeof(int));
    close(shm_fd);
    shm_unlink(name);
    return 0;
}