os161/kern/test/synchprobs.c

325 lines
6.0 KiB
C
Raw Normal View History

/*
* NO NOT MODIFY THIS FILE
*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/
#include <types.h>
#include <lib.h>
#include <thread.h>
#include <test.h>
#include <current.h>
#include <synch.h>
#define PROBLEMS_MAX_YIELDER 16
#define PROBLEMS_MAX_SPINNER 8192
2015-12-31 19:26:33 -05:00
/*
* Shared initialization routines
*/
2015-12-31 19:56:40 -05:00
static uint32_t startcount;
static struct lock *startlock;
static struct cv *startcv;
2015-12-31 19:38:38 -05:00
static struct semaphore *endsem;
2015-12-31 19:26:33 -05:00
static
void
2015-12-31 19:56:40 -05:00
inititems(uint32_t count)
2015-12-31 19:26:33 -05:00
{
2015-12-31 19:56:40 -05:00
startcount = count;
if (startlock==NULL) {
startlock = lock_create("startlock");
if (startlock == NULL) {
panic("synchprobs: lock_create failed\n");
}
}
if (startcv==NULL) {
startcv = cv_create("startcv");
if (startcv == NULL) {
panic("synchprobs: cv_create failed\n");
2015-12-31 19:38:38 -05:00
}
}
if (endsem==NULL) {
endsem = sem_create("endsem", 0);
if (endsem == NULL) {
2015-12-31 19:26:33 -05:00
panic("synchprobs: sem_create failed\n");
}
}
}
/*
* Driver code for the whalemating problem.
*/
2015-12-31 19:26:33 -05:00
static
void
male_wrapper(void * unused1, unsigned long unused2) {
(void)unused1;
(void)unused2;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:26:33 -05:00
male();
2015-12-31 19:38:38 -05:00
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
void
male_start(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s starting\n", curthread->t_name);
}
2015-12-31 19:26:33 -05:00
void
male_end(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s ending\n", curthread->t_name);
}
2015-12-31 19:26:33 -05:00
static
void
female_wrapper(void * unused1, unsigned long unused2) {
(void)unused1;
(void)unused2;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:26:33 -05:00
female();
2015-12-31 19:38:38 -05:00
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
void
female_start(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s starting\n", curthread->t_name);
}
2015-12-31 19:26:33 -05:00
void
female_end(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s ending\n", curthread->t_name);
}
2015-12-31 19:26:33 -05:00
static
void
matchmaker_wrapper(void * unused1, unsigned long unused2) {
(void)unused1;
(void)unused2;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:26:33 -05:00
matchmaker();
2015-12-31 19:38:38 -05:00
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
void
matchmaker_start(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s starting\n", curthread->t_name);
}
2015-12-31 19:26:33 -05:00
void
matchmaker_end(void) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s ending\n", curthread->t_name);
}
#define NMATING 10
2015-12-31 19:26:33 -05:00
int
whalemating(int nargs, char **args) {
(void) nargs;
(void) args;
int i, j, err = 0;
char name[32];
2015-12-31 19:26:33 -05:00
2015-12-31 19:56:40 -05:00
inititems(3 * NMATING);
whalemating_init();
for (i = 0; i < 3; i++) {
for (j = 0; j < NMATING; j++) {
switch (i) {
case 0:
snprintf(name, sizeof(name), "Male Whale Thread %d", (i * 3) + j);
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, male_wrapper, NULL, 0);
break;
case 1:
snprintf(name, sizeof(name), "Female Whale Thread %d", (i * 3) + j);
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, female_wrapper, NULL, 0);
break;
case 2:
snprintf(name, sizeof(name), "Matchmaker Whale Thread %d", (i * 3) + j);
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, matchmaker_wrapper, NULL, 0);
break;
}
if (err) {
panic("whalemating: thread_fork failed: (%s)\n", strerror(err));
}
}
}
2015-12-31 19:26:33 -05:00
for (i = 0; i < 3; i++) {
for (j = 0; j < NMATING; j++) {
2015-12-31 19:38:38 -05:00
P(endsem);
}
}
whalemating_cleanup();
return 0;
}
/*
* Driver code for the stoplight problem.
*/
2015-12-31 19:26:33 -05:00
static
void
turnright_wrapper(void *unused, unsigned long direction)
{
(void)unused;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:38:38 -05:00
turnright((uint32_t)direction);
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
static
void
gostraight_wrapper(void *unused, unsigned long direction)
{
(void)unused;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:38:38 -05:00
gostraight((uint32_t)direction);
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
static
void
turnleft_wrapper(void *unused, unsigned long direction)
{
(void)unused;
random_yielder(4);
2015-12-31 19:56:40 -05:00
lock_acquire(startlock);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, startlock);
} else {
cv_wait(startcv, startlock);
}
2015-12-31 20:01:19 -05:00
lock_release(startlock);
2015-12-31 19:38:38 -05:00
turnleft((uint32_t)direction);
V(endsem);
2015-12-31 19:26:33 -05:00
return;
}
void
inQuadrant(int quadrant) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s in quadrant %d\n", curthread->t_name, quadrant);
}
2015-12-31 19:26:33 -05:00
void
leaveIntersection() {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
tkprintf("%s left the intersection\n", curthread->t_name);
}
2015-12-31 19:56:40 -05:00
#define NCARS 64
struct semaphore * stoplightMenuSemaphore;
int stoplight(int nargs, char **args) {
(void) nargs;
(void) args;
int i, direction, turn, err = 0;
char name[32];
2015-12-31 19:56:40 -05:00
inititems(NCARS);
stoplight_init();
for (i = 0; i < NCARS; i++) {
direction = random() % 4;
turn = random() % 3;
snprintf(name, sizeof(name), "Car Thread %d", i);
switch (turn) {
case 0:
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, gostraight_wrapper, NULL, direction);
break;
case 1:
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, turnleft_wrapper, NULL, direction);
break;
case 2:
2015-12-31 19:26:33 -05:00
err = thread_fork(name, NULL, turnright_wrapper, NULL, direction);
break;
}
if (err) {
panic("stoplight: thread_fork failed: (%s)\n", strerror(err));
}
}
2015-12-31 19:26:33 -05:00
for (i = 0; i < NCARS; i++) {
2015-12-31 19:38:38 -05:00
P(endsem);
}
stoplight_cleanup();
return 0;
}