/* * 5 dining philosophers: a sample rtx demo for gcc * simulation of the classic dining philosophers problem. * * ++jrb * bang: {any internet host}!dsrgsun.ces.CWRU.edu!bammi * domain: bammi@dsrgsun.ces.CWRU.edu * GEnie: J.Bammi * CIS: 71515,155 */ #include "grtxbind.h" #ifndef NULL #define NULL ((void *)0) #endif #define fflush(x) /* nothing */ #define printf(x) Bconws(x) #define fprintf(s,x) Bconws(x) #define clear() printf("\033E") #define moveto(r,c) printf("\033Y"), Bconout(2,r+040),Bconout(2,c+040) #define Rand() (Random() >> 8) void Bconws(); typedef struct { char *name; /* process name */ char *pid; /* pid of process */ short event; /* event (ready) condition */ int me; /* my index */ int left; /* index of phil to left */ int right; /* index of phil to right */ int col; /* column for printing */ long message[4]; /* message buffer */ short eventbuf; /* event buffer */ } PHIL; /* 5 philosophers on a round table */ PHIL phils[] = { {"phil-0", (char *)NULL, 0x001, 0, 4, 1, 0, 0L, 0L, 0L, 0L, 0 }, {"phil-1", (char *)NULL, 0x002, 1, 0, 2, 16, 0L, 0L, 0L, 0L, 0 }, {"phil-2", (char *)NULL, 0x004, 2, 1, 3, 32, 0L, 0L, 0L, 0L, 0 }, {"phil-3", (char *)NULL, 0x008, 3, 2, 4, 48, 0L, 0L, 0L, 0L, 0 }, {"phil-4", (char *)NULL, 0x010, 4, 3, 0, 64, 0L, 0L, 0L, 0L, 0 } }; /* forks: number of forks available to philosopher i * note: mutex access at all times (ie only one process may read/write * any element of forks at one time, implemented via semaphore). * usage: * at any time forks[i] can only be 0, 1, or 2 * when a philosopher [i] wants to eat, forks[i] must be 2, * if it is * decrement forks to the right and left by one and start eating * otherwise * wait for event phil[i].event (ready condition for phil i) to occur. * * when a philosopher is done eating, * increments forks to left and right * if forks[left] == 2 cause event phil[left].event * if forks[right] == 2 cause event phil[right].event */ int forks [] = { 2, 2, 2, 2, 2 }; /* fork semaphore (queue) */ char *forkSemaphore; /* P/V on fork semaphore */ #define Pfork(q) q_req (forkSemaphore, q, 0, 0L) #define Vfork(q) q_send(forkSemaphore, q) /* screen semaphore, for exclusive access to write to screen */ char *screenSemaphore; /* P/V on screen semaphore */ #define Pscreen(q) q_req (screenSemaphore, q, 0, 0L) #define Vscreen(q) q_send(screenSemaphore, q) /* * pickup * pickup both forks or wait until both avail */ void pickup(phil) PHIL *phil; /* philosopher requesting forks */ { Pfork(phil->message); /* mutually exclusive access to forks */ if(forks[phil->me] != 2) { Vfork(phil->message); /* release */ phil->eventbuf = phil->event; e_wait(&phil->eventbuf, 0, 0L); /* wait for ready condition */ Pfork(phil->message); } /* get the two forks */ forks[phil->left]--; forks[phil->right]--; Vfork(phil->message); } /* * putdown * done eating, put down forks,and signal any ready conditions */ void putdown(phil) PHIL *phil; { Pfork(phil->message); /* drop forks and signal any events */ if(++forks[phil->left] == 2) e_signal(phils[phil->left].pid, phils[phil->left].event); if(++forks[phil->right] == 2) e_signal(phils[phil->right].pid, phils[phil->right].event); Vfork(phil->message); } /* * philosopher process */ void philosopher(phil) PHIL *phil; { Pscreen(phil->message); moveto(3, phil->col); printf(phil->name); fflush(stdout); Vscreen(phil->message); while(1) { Pscreen(phil->message); moveto(4, phil->col); printf(" Hungry "); fflush(stdout); Vscreen(phil->message); pickup(phil); /* eat */ Pscreen(phil->message); moveto(4, phil->col); printf(" Eating "); fflush(stdout); Vscreen(phil->message); p_pause( (long)(((Rand() & 15) + 1) * 1000L) ); putdown(phil); Pscreen(phil->message); moveto(4, phil->col); printf(" Thinking "); fflush(stdout); Vscreen(phil->message); p_pause( (long)(((Rand() & 15) + 1) * 1000L) ); } /*NOTREACHED*/ } /* * kill all live philosophers * free fork semaphore queue */ void killall() { int i; for(i = 0; i < 5; i++) { if(phils[i].pid != NULL) { p_delete(phils[i].pid); moveto(4, phils[i].col); printf(" KILLED! "); fflush(stdout); } } q_delete(forkSemaphore); q_delete(screenSemaphore); } /* * print a int (short range only) */ void printi(val) register int val; { register int j; register int div_idx; register int first; static int divisors[] = { 10000, 1000, 100, 10, 1 }; /* Special Cases */ if (val == 0) { Bconout(2, '0'); return; } else if (val == -32768) { Bconws("-32768"); return; } /* Get digit for each power of 10 and print them, skip leading 0's */ first = div_idx = 0; if (val < 0) { Bconout(2, '-'); val = -val; } while( div_idx < 5 ) { if(((j = val / divisors[div_idx]) != 0) || first != 0) { Bconout(2, j + '0'); first = 1; } val %= divisors[div_idx++]; } } /* * the top level process, called after rtx initialization */ void Top() { int i; long message[4]; PHIL *stk; /* create semaphores */ forkSemaphore = q_create("FORKSEM", 0); screenSemaphore = q_create("SCRSEM", 0); /* lower my prio (phils will be given higher prio) */ p_priority((char *)NULL, -5); /* create the philosophers */ for(i = 0; i < 5; i++) { stk = &phils[i]; phils[i].pid = p_create(phils[i].name, p_priority((char *)NULL, 0)+1, p_slice((char *)NULL, 0), philosopher, (short)(sizeof(PHIL *)), &stk, 512L); if(phils[i].pid == (char *)NULL) { fprintf(stderr,"P_create failed\r\n"); killall(); return; } } moveto(10, 33); printf("Hit q to quit"); fflush(stdout); /* start it all up */ Vscreen(message); Vfork(message); while((Crawio(0x00ff) & 0x07f) != 'q') { /* report process status */ for(i = 0; i < 5; i++) { PROCESS_STATE status; p_info(phils[i].pid, &status); Pscreen(message); moveto(7, phils[i].col); if(status.EWAIT) printf(" event wait "); else if(status.QWAIT) printf(" queue wait "); else if(status.PAUSED) printf(" Paused "); else if(status.RUNNING) printf(" Running "); else if(status.READY) printf(" Ready "); else printf(" Unknown "); printi(forks[i]); fflush(stdout); Vscreen(message); p_pause(500L); } } killall(); } void Bconws(str) char *str; { auto char *s = str; while(*s) Bconout(2, *s++); } extern BASEPAGE *_base; int main() { CONFIG config; char *RootPid; config.basepage = _base; config.max_proc = 32; config.max_msgs = 64; config.max_queues = 64; config.create_call = NULL; config.delete_call = NULL; config.switch_call = NULL; if((RootPid = rtx_install(&config)) == (char *)NULL) { fprintf(stderr, "microRtx could not be installed\r\n"); exit(1); } clear(); Top(); rtx_remove(); }