home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / grtxbind / phil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-09  |  7.1 KB  |  315 lines

  1. /*
  2.  * 5 dining philosophers: a sample rtx demo for gcc
  3.  *    simulation of the classic dining philosophers problem.
  4.  *
  5.  *    ++jrb
  6.  *    bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi
  7.  *    domain: bammi@dsrgsun.ces.CWRU.edu
  8.  *    GEnie:    J.Bammi
  9.  *    CIS:    71515,155
  10.  */
  11. #include "grtxbind.h"
  12.  
  13. #ifndef NULL
  14. #define NULL ((void *)0)
  15. #endif
  16.  
  17. #define fflush(x)    /* nothing */
  18. #define printf(x)    Bconws(x)
  19. #define fprintf(s,x)    Bconws(x)
  20. #define clear()        printf("\033E")
  21. #define moveto(r,c)    printf("\033Y"), Bconout(2,r+040),Bconout(2,c+040)
  22. #define Rand()        (Random() >> 8)
  23. void Bconws();
  24.  
  25. typedef struct {
  26.     char    *name;        /* process name    */
  27.     char    *pid;        /* pid of process  */
  28.     short    event;        /* event (ready) condition */
  29.     int        me;        /* my index           */
  30.     int        left;        /* index of phil to left   */
  31.     int        right;        /* index of phil to right  */
  32.     int        col;        /* column for printing     */
  33.     long    message[4];    /* message buffer       */
  34.     short    eventbuf;    /* event buffer           */
  35. } PHIL;
  36.  
  37. /* 5 philosophers on a round table */
  38. PHIL phils[] = {
  39.      {"phil-0", (char *)NULL, 0x001, 0, 4, 1, 0,  0L, 0L, 0L, 0L, 0 },
  40.      {"phil-1", (char *)NULL, 0x002, 1, 0, 2, 16, 0L, 0L, 0L, 0L, 0 },
  41.      {"phil-2", (char *)NULL, 0x004, 2, 1, 3, 32, 0L, 0L, 0L, 0L, 0 },
  42.      {"phil-3", (char *)NULL, 0x008, 3, 2, 4, 48, 0L, 0L, 0L, 0L, 0 },
  43.      {"phil-4", (char *)NULL, 0x010, 4, 3, 0, 64, 0L, 0L, 0L, 0L, 0 }
  44. };
  45.  
  46. /* forks: number of forks available to philosopher i
  47.  * note: mutex access at all times (ie only one process may read/write
  48.  * any element of forks at one time, implemented via semaphore).
  49.  * usage:
  50.  * at any time forks[i] can only be 0, 1, or 2
  51.  * when a philosopher [i] wants to eat, forks[i] must be 2,
  52.  * if it is
  53.  *    decrement forks to the right and left by one and start eating
  54.  * otherwise
  55.  *    wait for event phil[i].event (ready condition for phil i) to occur.
  56.  *
  57.  * when a philosopher is done eating,
  58.  *    increments forks to left and right
  59.  *    if forks[left] == 2    cause event phil[left].event
  60.  *    if forks[right] == 2    cause event phil[right].event
  61.  */
  62. int forks [] = { 2, 2, 2, 2, 2 };
  63.  
  64. /* fork semaphore (queue) */
  65. char *forkSemaphore;
  66.  
  67. /* P/V on fork semaphore */
  68. #define Pfork(q)    q_req (forkSemaphore, q, 0, 0L)
  69. #define Vfork(q)    q_send(forkSemaphore, q)
  70.  
  71. /* screen semaphore, for exclusive access to write to screen */
  72. char *screenSemaphore;
  73.  
  74. /* P/V on screen semaphore */
  75. #define Pscreen(q)    q_req (screenSemaphore, q, 0, 0L)
  76. #define Vscreen(q)    q_send(screenSemaphore, q)
  77.  
  78.  
  79. /*
  80.  * pickup
  81.  *    pickup both forks or wait until both avail
  82.  */
  83. void pickup(phil)
  84. PHIL *phil;    /* philosopher requesting forks */
  85. {
  86.     Pfork(phil->message);    /* mutually exclusive access to forks */
  87.     if(forks[phil->me] != 2)
  88.     {
  89.     Vfork(phil->message);    /* release */
  90.     phil->eventbuf = phil->event;
  91.     e_wait(&phil->eventbuf, 0, 0L); /* wait for ready condition */
  92.     Pfork(phil->message);
  93.     }
  94.     /* get the two forks */
  95.     forks[phil->left]--;    
  96.     forks[phil->right]--;
  97.     Vfork(phil->message);
  98. }
  99.  
  100. /*
  101.  * putdown
  102.  *    done eating, put down forks,and signal any ready conditions
  103.  */
  104. void putdown(phil)
  105. PHIL *phil;
  106. {
  107.     
  108.     Pfork(phil->message);
  109.  
  110.     /* drop forks and signal any events */
  111.     if(++forks[phil->left] == 2)
  112.     e_signal(phils[phil->left].pid, phils[phil->left].event);
  113.     if(++forks[phil->right] == 2)
  114.     e_signal(phils[phil->right].pid, phils[phil->right].event);
  115.  
  116.     Vfork(phil->message);
  117. }
  118.  
  119. /*
  120.  * philosopher process
  121.  */
  122. void philosopher(phil)
  123. PHIL *phil;
  124. {
  125.     
  126.     Pscreen(phil->message);
  127.     moveto(3, phil->col);
  128.     printf(phil->name);  fflush(stdout);
  129.     Vscreen(phil->message);
  130.     
  131.     while(1)
  132.     {
  133.     Pscreen(phil->message);
  134.     moveto(4, phil->col); printf("  Hungry    "); fflush(stdout);
  135.     Vscreen(phil->message);
  136.     pickup(phil);
  137.     /* eat */
  138.     Pscreen(phil->message);
  139.     moveto(4, phil->col); printf("  Eating    "); fflush(stdout);
  140.     Vscreen(phil->message);
  141.     p_pause( (long)(((Rand() & 15) + 1) * 1000L) );
  142.     putdown(phil);
  143.     Pscreen(phil->message);
  144.     moveto(4, phil->col); printf("  Thinking  "); fflush(stdout);
  145.     Vscreen(phil->message);
  146.     p_pause( (long)(((Rand() & 15) + 1) * 1000L) );
  147.     }
  148.     /*NOTREACHED*/
  149. }
  150.  
  151. /*
  152.  * kill all live philosophers
  153.  * free fork semaphore queue
  154.  */
  155. void killall()
  156. {
  157.     int i;
  158.     for(i = 0; i < 5; i++)
  159.     {
  160.     if(phils[i].pid != NULL)
  161.     {
  162.         p_delete(phils[i].pid);
  163.         moveto(4, phils[i].col);
  164.         printf("  KILLED!   "); fflush(stdout);
  165.     }
  166.     }
  167.     q_delete(forkSemaphore);
  168.     q_delete(screenSemaphore);
  169. }
  170.  
  171. /*
  172.  * print a int (short range only)
  173.  */
  174. void printi(val)
  175. register int val;
  176. {
  177.         register int j;
  178.         register int div_idx;
  179.         register int first;
  180.         static int divisors[] = { 10000, 1000, 100, 10, 1 };
  181.     
  182.     /* Special Cases */
  183.         if (val == 0)
  184.     {
  185.         Bconout(2, '0');
  186.         return;
  187.     }
  188.         else if (val == -32768)
  189.     {
  190.                 Bconws("-32768");
  191.         return;
  192.     }
  193.     
  194.     /* Get digit for each power of 10 and print them, skip leading 0's */
  195.         first = div_idx  = 0;
  196.     
  197.         if (val < 0)
  198.     {
  199.                 Bconout(2, '-');
  200.                 val = -val;
  201.     }
  202.         while( div_idx < 5 )
  203.     {
  204.                 if(((j = val / divisors[div_idx]) != 0) || first != 0)
  205.         {
  206.                         Bconout(2, j + '0');
  207.                         first = 1;
  208.         }
  209.                 val %= divisors[div_idx++];
  210.     }
  211.     
  212. }
  213.  
  214. /*
  215.  * the top level process, called after rtx initialization
  216.  */
  217. void Top()
  218. {
  219.     int i;
  220.     long message[4];
  221.     PHIL *stk;
  222.     
  223.     /* create semaphores */
  224.     forkSemaphore = q_create("FORKSEM", 0);
  225.     screenSemaphore = q_create("SCRSEM", 0);
  226.     
  227.     /* lower my prio (phils will be given higher prio) */
  228.     p_priority((char *)NULL, -5);
  229.     /* create the philosophers */
  230.     for(i = 0; i < 5; i++)
  231.     {
  232.     stk = &phils[i];
  233.     phils[i].pid = p_create(phils[i].name, p_priority((char *)NULL, 0)+1,
  234.                 p_slice((char *)NULL, 0), philosopher,
  235.                 (short)(sizeof(PHIL *)), &stk, 512L);
  236.     if(phils[i].pid == (char *)NULL)
  237.     {
  238.         fprintf(stderr,"P_create failed\r\n");
  239.         killall();
  240.         return;
  241.     }
  242.     
  243.     }
  244.     moveto(10, 33); printf("Hit q to quit"); fflush(stdout);
  245.     /* start it all up */
  246.     Vscreen(message);
  247.     Vfork(message);
  248.     
  249.     while((Crawio(0x00ff) & 0x07f) != 'q')
  250.     {
  251.     /* report process status */
  252.     for(i = 0; i < 5; i++)
  253.     {
  254.         PROCESS_STATE status;
  255.         
  256.         p_info(phils[i].pid, &status);
  257.         Pscreen(message);
  258.         moveto(7,  phils[i].col);
  259.         if(status.EWAIT)
  260.         printf(" event wait ");
  261.         else if(status.QWAIT)
  262.         printf(" queue wait ");
  263.         else if(status.PAUSED)
  264.         printf(" Paused     ");
  265.         else if(status.RUNNING)
  266.         printf(" Running    ");
  267.         else if(status.READY)
  268.         printf(" Ready      ");
  269.         else
  270.         printf(" Unknown    ");
  271.         printi(forks[i]);
  272.         fflush(stdout);
  273.         Vscreen(message);
  274.         
  275.         p_pause(500L);
  276.     }
  277.     }
  278.     killall();
  279. }
  280.  
  281. void Bconws(str)
  282. char *str;
  283. {
  284.     auto char *s = str;
  285.     
  286.     while(*s)
  287.     Bconout(2, *s++);
  288. }
  289.  
  290. extern BASEPAGE *_base;
  291.  
  292. int main()
  293. {
  294.     CONFIG config;
  295.     char *RootPid;
  296.     
  297.     config.basepage = _base;
  298.     config.max_proc = 32;
  299.     config.max_msgs = 64;
  300.     config.max_queues = 64;
  301.     config.create_call = NULL;
  302.     config.delete_call = NULL;
  303.     config.switch_call = NULL;
  304.     
  305.     if((RootPid = rtx_install(&config)) == (char *)NULL)
  306.     {
  307.     fprintf(stderr, "microRtx could not be installed\r\n");
  308.     exit(1);
  309.     }
  310.     clear();
  311.     
  312.     Top();
  313.     rtx_remove();
  314. }
  315.