home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / toy_os / part04 / mult_proc.cc < prev    next >
C/C++ Source or Header  |  1994-09-05  |  4KB  |  137 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *        Multiprocessing under VM_UNT - Virtual OS
  6.  *
  7.  * The present file contains interfaces with the system library
  8.  * of VM_UNT.
  9.  * Important!
  10.  *    Turn off optimization while compiling the present flag. This
  11.  * would prevent the compiler from keeping too much data in registers
  12.  * across the function calls. A call to proc_switching(), either explicit
  13.  * or implicit (through the P-semaphor operation), leads potentially to
  14.  * the thread switching. As experience shows, some registers would not 
  15.  * be restored after the thread gets control back.
  16.  *
  17.  * Note, if the preprocessor symbol DEBUG is set, some debug information
  18.  * as to setting/releasing the locks, etc. is printed FYI.
  19.  *
  20.  ************************************************************************
  21.  */
  22.  
  23. #include "mult_proc.h"
  24. #pragma implementation "mult_proc.h"
  25.  
  26. #include "myenv.h"
  27. #include <setjmp.h>
  28. #include <std.h>
  29.  
  30. /*
  31.  *------------------------------------------------------------------------
  32.  *                   Semaphores
  33.  */
  34.  
  35. extern "C" {                 // VM_UNT library calls
  36.   void p(void *);
  37.   void v(void *);
  38.   int  sem_awaited(void *);
  39.   void * seminit(const char * name, const int size);
  40. }
  41.  
  42.                 // Create a semaphore with a specified name
  43.                 // and assign an initial value to it
  44. Semaphore::Semaphore(const char * _name, const int in_value)
  45.   assert( _name != 0 );
  46.   assure( in_value >= 0, "Initial value of the semaphore cannot be negative");
  47.   strncpy(name,_name,sizeof(name)-1);
  48.   value = in_value;
  49.  
  50.   assert( (_sem_ptr = seminit(name,in_value)) != 0 );
  51. #ifdef DEBUG
  52.   message("\nSemaphore '%s' (ID=%x), in_value %d has been set up",name,
  53.       (int)_sem_ptr,value);
  54. #endif
  55. }
  56.  
  57.                 // P-semaphore operation
  58. void Semaphore::operator -- (void)
  59. {
  60. #ifdef DEBUG
  61.   message("\nAbout to perform P-operation on '%s' (ID=%x), value %d",
  62.       name,(int)_sem_ptr,value);
  63. #endif
  64.   value--;
  65.   asm("pushl %esi");
  66.   ::p(_sem_ptr);
  67.   asm("popl %esi");
  68. #ifdef DEBUG
  69.   message("\nWoke up after sleeping on P-operation on '%s' (ID=%x), value %d",
  70.       name,(int)_sem_ptr,value);
  71. #endif
  72. }
  73.  
  74.                 // V-semaphore operation
  75. void Semaphore::operator ++ (void)
  76. {
  77. #ifdef DEBUG
  78.   message("\nAbout to perform V-operation on '%s' (ID=%x), value %d",
  79.       name,(int)_sem_ptr,value);
  80. #endif
  81.   value++;
  82.   ::v(_sem_ptr);
  83. }
  84.  
  85.                 // Check to see if somebody is waiting on
  86.                 // this semaphore
  87. int Semaphore::awaited(void)
  88. {
  89.   return ::sem_awaited(_sem_ptr);
  90. }
  91.  
  92. /*
  93.  *------------------------------------------------------------------------
  94.  *             Threads of CPU control
  95.  */
  96.                 // System calls in VM_UNT
  97. extern "C" {
  98.                 // Create a thread. Return 0 if we're
  99.                 // in the child thread, and 1 otherwise
  100.                 // (kind of like fork())
  101.   int newproc(const char * name, const short priority);
  102.   volatile void endproc(void);    // Terminate the thread
  103. }
  104.  
  105. static char Was_stack_saved = 0;
  106.  
  107.                  // Create a thread with a specified name
  108.                 // and have it run the procedure we want
  109.                 // until it is over
  110. Thread::Thread(const char * name, const short priority, Thread_body((*body)))
  111. {
  112.   if( !Was_stack_saved )
  113.   {
  114.     Was_stack_saved = 1;
  115.     extern int _stackinit;        // The following instructions save
  116.     asm("movl %esp,__stackinit");    // the stack of the calling proc
  117.     asm("addl $28,__stackinit");    // 28 = (4+3) long words in stack
  118.   }
  119.  
  120.   assert( name != 0 );
  121.  
  122.   if( !newproc(name,priority) )
  123.   {                    // We're in the child thread now
  124. #ifdef DEBUG
  125.   message("\nRunning a thread '%s', priority %d\n",name,priority);
  126. #endif
  127.     body();
  128. #ifdef DEBUG
  129.     message("\nThread '%s' is through\n",name);
  130. #endif
  131.     endproc();
  132.   }
  133.                     // We're in the parent thread now
  134. }
  135.  
  136.