0

I have a systems programming problem. Its a group of small programs that interact with each other to implement a mutual exclusion problem. I was wondeing if somebody could comment them to help me understand them better. Would be very much appreciated.

They are toilets shared by boys and girls. However, at any time only boys or only girls may be in the toilets. (Mary runs a strict establishment and does not want any funny business going on in her toilets.) Mary's rules on using the toilets are simple. A boy can enter iff:

The toilets are empty or
The toilets are occupied by boys and a toilet is available
A girl can enter iff:
The toilets are empty or
The toilets are occupied by girls and a toilet is available
However, there is a caveat. In the interest of fairness, if one sex has been waiting a long time while the other hogs the toilets then a bouncer must intervene. The bouncer allows no one to enter until the toilets have emptied. He then allows the waiting sex to enter.

instead of bouncer she employs this software

Attachments
/*
 * Boys threads
 */
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include "toilet.h"
#include "boys.h"
#include "sleep.h"

void *
boy_queuer(void * in)
{
	tp_t	*tp;
	time_t	next;

	/* Convert what was passed in to a pointer to a toilet */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		my_sleep_random(BOYS_SLEEP_NS);

		next = time(NULL);

		pthread_mutex_lock(&tp->bq.mutex);

		while (tp->bq.occupied == MAX_BOYS_WAITING) {
			pthread_cond_wait(&tp->bq.room, &tp->bq.mutex);
		}

		tp->bq.buffer[tp->bq.nextin] = next;
		tp->bq.nextin++;
		tp->bq.nextin %= MAX_BOYS_WAITING;
		tp->bq.occupied++;
		pthread_cond_signal(&tp->bq.data);

		pthread_mutex_unlock(&tp->bq.mutex);
	}

	return ((void *)NULL);
}

void *
boy_scheduler(void * in)
{
	tp_t	*tp;
	time_t	next;

	/* Convert what was passed in to a pointer to a toilet structure */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		pthread_mutex_lock(&tp->bq.mutex);

		while (tp->bq.occupied == 0) {
			pthread_cond_wait(&tp->bq.data, &tp->bq.mutex);
		}

		next = tp->bq.buffer[tp->bq.nextout];
		tp->bq.nextout++;
		tp->bq.nextout %= MAX_BOYS_WAITING;
		tp->bq.occupied--;
		tp->bq.outs++;

		pthread_cond_signal(&tp->bq.room);

		pthread_mutex_unlock(&tp->bq.mutex);

		pthread_mutex_lock(&tp->ts.mutex);

		while (!(((tp->ts.state == BOYS) || (tp->ts.state == ANYONE))
		    && (tp->ts.occupied < TOILETS))) {

			pthread_cond_wait(&tp->ts.boys, &tp->ts.mutex);

		}

		if (tp->ts.state == ANYONE) {
			tp->ts.state = BOYS;
		}

		tp->ts.buffer[tp->ts.nextin] = next;
		tp->ts.nextin++;
		tp->ts.nextin %= TOILETS;
		tp->ts.occupied++;

		pthread_cond_signal(&tp->ts.data);

		pthread_mutex_unlock(&tp->ts.mutex);		
	}

	return ((void *)NULL);
}
/*
 * Boys header file
 */

#ifndef	_BOYS_H
#define	_BOYS_H	1

/* Prototypes */
void *boy_queuer(void *);
void *boy_scheduler(void *);

#endif
/*
 * In the interest of fairness
 */
#include <pthread.h>
#include <stdio.h>
#include "toilet.h"
#include "fairness.h"

void *
fairness(void * in)
{
	tp_t		*tp;
	time_t		wb, wg;

	/* Convert what was passed in to a pointer to a toilet structure */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		sleep(FAIRNESS_SLEEP_S);

		pthread_mutex_lock(&tp->ts.mutex);

		if (tp->ts.state == GIRLS) {

			pthread_mutex_lock(&tp->bq.mutex);

			if (tp->bq.occupied > 0) {

				wb = time(NULL) -
				    tp->bq.buffer[tp->bq.nextout];

			} else {

				wb = 0;
			}

			pthread_mutex_unlock(&tp->bq.mutex);

			if (wb > MAXIMUM_WAIT_S) {

				empty_toilets(tp);

				tp->ts.drains++;

				tp->ts.state = BOYS;

				pthread_cond_signal(&tp->ts.boys);
			}
		}

		if (tp->ts.state == BOYS) {

			pthread_mutex_lock(&tp->gq.mutex);

			if (tp->gq.occupied > 0) {

				wg = time(NULL) -
				    tp->gq.buffer[tp->gq.nextout];

			} else {

				wg = 0;
			}

			pthread_mutex_unlock(&tp->gq.mutex);

			if (wg > MAXIMUM_WAIT_S) {

				empty_toilets(tp);

				tp->ts.drains++;

				tp->ts.state = GIRLS;

				pthread_cond_signal(&tp->ts.girls);
			}
		}

		pthread_mutex_unlock(&tp->ts.mutex);
	}

	return ((void *)NULL);
}
/*
 * Fairness header file
 */

#ifndef	_FAIRNESS_H
#define	_FAIRNESS_H	1

/* Prototype */
void *fairness(void *);

#endif
/*
 * Girls threads
 */
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include "toilet.h"
#include "girls.h"
#include "sleep.h"

void *
girl_queuer(void * in)
{
	tp_t	*tp;
	time_t	next;

	/* Convert what was passed in to a pointer to a toilet */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		my_sleep_random(GIRLS_SLEEP_NS);

		next = time(NULL);

		pthread_mutex_lock(&tp->gq.mutex);

		while (tp->gq.occupied == MAX_GIRLS_WAITING) {
			pthread_cond_wait(&tp->gq.room, &tp->gq.mutex);
		}

		tp->gq.buffer[tp->gq.nextin] = next;
		tp->gq.nextin++;
		tp->gq.nextin %= MAX_GIRLS_WAITING;
		tp->gq.occupied++;
		pthread_cond_signal(&tp->gq.data);

		pthread_mutex_unlock(&tp->gq.mutex);
	}

	return ((void *)NULL);
}

void *
girl_scheduler(void * in)
{
	tp_t	*tp;
	time_t	next;

	/* Convert what was passed in to a pointer to a toilet structure */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		pthread_mutex_lock(&tp->gq.mutex);

		while (tp->gq.occupied == 0) {
			pthread_cond_wait(&tp->gq.data, &tp->gq.mutex);
		}

		next = tp->gq.buffer[tp->gq.nextout];
		tp->gq.nextout++;
		tp->gq.nextout %= MAX_GIRLS_WAITING;
		tp->gq.occupied--;
		tp->gq.outs++;

		pthread_cond_signal(&tp->gq.room);

		pthread_mutex_unlock(&tp->gq.mutex);

		pthread_mutex_lock(&tp->ts.mutex);

		while (!(((tp->ts.state == GIRLS) || (tp->ts.state == ANYONE))
		    && (tp->ts.occupied < TOILETS))) {

			pthread_cond_wait(&tp->ts.girls, &tp->ts.mutex);

		}

		if (tp->ts.state == ANYONE) {
			tp->ts.state = GIRLS;
		}

		tp->ts.buffer[tp->ts.nextin] = next;
		tp->ts.nextin++;
		tp->ts.nextin %= TOILETS;
		tp->ts.occupied++;

		pthread_cond_signal(&tp->ts.data);

		pthread_mutex_unlock(&tp->ts.mutex);		
	}

	return ((void *)NULL);
}
/*
 * Girls header file
 */

#ifndef	_GIRLS_H
#define	_GIRLS_H	1

/* Prototypes */
void *girl_queuer(void *);
void *girl_scheduler(void *);

#endif
/*
 * Remove people from the toilet
 */
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include "toilet.h"
#include "remover.h"
#include "sleep.h"

void
empty_toilets(tp_t *tp)
{
	while (tp->ts.occupied != 0) {

		my_sleep_random(REMOVER_SLEEP_NS);

		tp->ts.buffer[tp->ts.nextout] = 0;
		tp->ts.nextout++;
		tp->ts.nextout %= TOILETS;
		tp->ts.occupied--;
	}
}

void *
remover(void * in)
{
	tp_t	*tp;

	/* Convert what was passed in to a pointer to a toilet */
	tp = (tp_t *)in;

	/* Loop */
	while (1) {

		my_sleep_random(REMOVER_SLEEP_NS);

		pthread_mutex_lock(&tp->ts.mutex);

		while (tp->ts.occupied == 0) {
			pthread_cond_wait(&tp->ts.data, &tp->ts.mutex);
		}

		tp->ts.buffer[tp->ts.nextout] = 0;
		tp->ts.nextout++;
		tp->ts.nextout %= TOILETS;
		tp->ts.occupied--;

		if (tp->ts.occupied == 0) {

			tp->ts.state = ANYONE;
			pthread_cond_signal(&tp->ts.boys);
			pthread_cond_signal(&tp->ts.girls);

		} else {

			if (tp->ts.state == BOYS) {

				pthread_cond_signal(&tp->ts.boys);

			} else {

				if (tp->ts.state == GIRLS) {

					pthread_cond_signal(&tp->ts.girls);
				}
			}
		}

		pthread_mutex_unlock(&tp->ts.mutex);
	}

	return ((void *)NULL);
}
/*
 * Remover header file
 */

#ifndef	_REMOVER_H
#define	_REMOVER_H	1

#include "toilet.h"

/* Prototypes */
void *remover(void *);
void empty_toilets(tp_t *);

#endif
/*
 * Function for sleeping
 */
#include <time.h>
#include <stdlib.h>
#include "sleep.h"

void
my_sleep_random(int range)
{
	struct timespec	s;

	s.tv_sec = 0;
	s.tv_nsec = (int)(((double)random() / RAND_MAX) * range);

	(void) nanosleep(&s, NULL);
}
/*
 * Sleeping header file
 */

#ifndef	_SLEEPING_H
#define	_SLEEPING_H	1

/* Prototypes */
void my_sleep_random(int);

#endif
/*
 * Solving the toilet problem
 */
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "toilet.h"
#include "boys.h"
#include "girls.h"
#include "remover.h"
#include "fairness.h"

static void *
monitor(void *in)
{
	tp_t	*tp;

	/* Convert what was passed in to a pointer to a toilet */
	tp = (tp_t *)in;

	while (1) {

		sleep(MONITOR_SLEEP_S);

		pthread_mutex_lock(&tp->ts.mutex);

		(void) fprintf(stdout, "Boys: %d\n", tp->bq.outs);
		(void) fprintf(stdout, "Girls: %d\n", tp->gq.outs);

		pthread_mutex_unlock(&tp->ts.mutex);
	}

	return ((void *)NULL);
}

/* Initialise */
static int
init_tp(tp_t *tp)
{

	pthread_mutex_init(&tp->bq.mutex, NULL);
	pthread_cond_init(&tp->bq.room, NULL);
	pthread_cond_init(&tp->bq.data, NULL);
	tp->bq.occupied = tp->bq.nextin = tp->bq.nextout = tp->bq.outs = 0;

	pthread_mutex_init(&tp->gq.mutex, NULL);
	pthread_cond_init(&tp->gq.room, NULL);
	pthread_cond_init(&tp->gq.data, NULL);
	tp->gq.occupied = tp->gq.nextin = tp->gq.nextout = tp->gq.outs = 0;

	pthread_mutex_init(&tp->ts.mutex, NULL);
	pthread_cond_init(&tp->ts.data, NULL);
	pthread_cond_init(&tp->ts.boys, NULL);
	pthread_cond_init(&tp->ts.girls, NULL);
	tp->ts.occupied = tp->ts.nextin = tp->ts.nextout = tp->ts.drains = 0;
	tp->ts.state = ANYONE;

	srandom(getpid());

	return (0);
}

int
main(int argc, char *argv[])
{
	pthread_t	bq, bs, gq, gs, r, m, f;
	tp_t		tp;

	/* Check usage */
	if (argc != 1) {
		(void) fprintf(stderr, "Usage: %s\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	/* Initialise toilets */
	init_tp(&tp);

	/* Create our threads */
	pthread_create(&bq, NULL, boy_queuer, (void *)&tp);
	pthread_create(&bs, NULL, boy_scheduler, (void *)&tp);
	pthread_create(&gq, NULL, girl_queuer, (void *)&tp);
	pthread_create(&gs, NULL, girl_scheduler, (void *)&tp);
	pthread_create(&r, NULL, remover, (void *)&tp);
	pthread_create(&m, NULL, monitor, (void *)&tp);
	pthread_create(&f, NULL, fairness, (void *)&tp);

	/* Leave it to our threads */
	pthread_exit((void *)NULL);

	return (0);
}
/*
 * Toilet header file
 */

#ifndef	_TOILET_H
#define	_TOILET_H	1

#include <pthread.h>

/* Slots in buffers */
#define	TOILETS			6
#define	MAX_GIRLS_WAITING	12
#define	MAX_BOYS_WAITING	12

/* Toilet may be accepting any of these */
#define	BOYS			0
#define	GIRLS			1
#define	ANYONE			2

/* Various sleep times */
#define	BOYS_SLEEP_NS		600
#define	GIRLS_SLEEP_NS		600
#define REMOVER_SLEEP_NS	1800
#define FAIRNESS_SLEEP_S	5
#define MAXIMUM_WAIT_S		5
#define MONITOR_SLEEP_S		1

/* A queue */
typedef struct {
	time_t		buffer[MAX_GIRLS_WAITING];
	int		occupied;
	int		nextin;
	int		nextout;
	int		outs;
	pthread_mutex_t	mutex;
	pthread_cond_t	room;
	pthread_cond_t	data;
} q_t;

/* Toilets */
typedef struct {
	int		buffer[TOILETS];
	int		occupied;
	int		nextin;
	int		nextout;
	int		drains;
	int		state;
	pthread_mutex_t	mutex;
	pthread_cond_t	data;
	pthread_cond_t	girls;
	pthread_cond_t	boys;
} toilets_t;

/*
 * Because our threads take as input a single pointer, we need to create
 * a single structure which contains everything we need and pass to each
 * thread a pointer to this structure.
 */
typedef struct {
	q_t		gq;
	q_t		bq;
	toilets_t	ts;
} tp_t;

#endif
3
Contributors
2
Replies
3
Views
10 Years
Discussion Span
Last Post by fuhaohowy
0

>>I was wondeing if somebody could comment them to help me understand them better.
Comment it yourself and you will understand it even more.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.