home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / quartz / quartz10.lha / src / presto / presto.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  6.3 KB  |  269 lines

  1. /*
  2.  * presto.c
  3.  *
  4.  *    Main PRESTO bootstrapping code.  Works something like this:
  5.  *
  6.  *    main()
  7.  *        Create a new MAIN object.
  8.  *        delete the scheduler thread
  9.  *        exit
  10.  *
  11.  *    Main::Main()
  12.  *        Call Main::init giving programmer chance to set up
  13.  *        initial parameters.
  14.  *
  15.  *    -    Bind "thisthread" to the default thread we get from UNIX.
  16.  *    -    Create a new scheduler object.
  17.  *    -    Create a thread to run in the scheduler object.
  18.  *    -    Start new thread in scheduler object.  We are running 
  19.  *        without preemption and with a single processor at this
  20.  *        point, so the start just puts the thread/scheduler pair
  21.  *        on the ready queue.
  22.  *    -    Create nummainthreads bound to Main::main and "start" them
  23.  *        by placing them on the run queue.  Again, we know that 
  24.  *        they won't run until the scheduler actually kicks in.
  25.  *
  26.  *    -    Invoke "thisproc" getting it to start pulling threads
  27.  *        off the readyq.
  28.  */
  29.  
  30. #define _PRESTO_C
  31.  
  32.  
  33. #include <sys/types.h>
  34. #include <osfcn.h>
  35. #include <stream.h>
  36. #include "presto.h"
  37.  
  38. Main            *MAIN;
  39. Scheduler    *sched;            // does not need to be shared,
  40.                     // just what it references does
  41.  
  42. static int main_exit_code = 0;        // how we leave
  43. shared_t int prestoState = STATIC_CTOR;
  44.  
  45. Main::Main(int ac, char **ap, char **ep)
  46. {
  47.     argc = ac;
  48.     argv = ap;
  49.     envp = ep;
  50.     numprocessors = 1;
  51.     mainstacksizes = DEFSTACKSIZ;
  52.     nummainthreads = 1;
  53.     stacksize = DEFSTACKSIZ;
  54.     quantum = DEFQUANTUM;
  55. #ifdef i386
  56.     affinity = 0;
  57. #endif i386
  58. #ifdef PROFILE
  59.     numprofilers = 1;
  60.     QInit();
  61. #endif
  62. }
  63.  
  64.  
  65. void
  66. Main::run ()
  67. {
  68.     int strlen(char*);
  69.     int strcpy(char*, char*);
  70.     Thread *t, *mainthread;
  71.  
  72.  
  73. #ifdef DEBUG_STARTUP
  74.         cout << "in Main::run, mainstacksizes = " << mainstacksizes
  75.              << ", stacksize = " << stacksize << "\n";
  76.         cout << "making scheduler thread _MAIN_\n";
  77. #endif DEBUG_STARTUP
  78.  
  79.     mainthread = new Thread("_MAIN_", 0, 0);    // run on same stack
  80.     mainthread->setflags(TF_SCHEDULER|TF_KEEPSTACK|TF_NONPREEMPTABLE);
  81.  
  82.     //
  83.     // "thisthread" refers to the current thread of execution running
  84.     // right here, right now.  Make our thread point at the static process
  85.     // object until we have our own process object to reference into.
  86.     //
  87.     mainthread->setproc(sysproc);
  88.     thisthread = mainthread;
  89.  
  90.     prestoState = MAIN_INIT;
  91.     // give the programmer a chance
  92.     if (main_exit_code = Main::init())    {    // non-zero return
  93.         return;                    // is bad news
  94.     }
  95.  
  96. #ifdef PROFILE
  97.     if ((numprocessors + numprofilers) > NUMPROCS)
  98.         {
  99.         cout << "Too many processors: " << numprocessors 
  100.                     << numprofilers << "\n";
  101.         return;                    // is bad news
  102.         }
  103.     QBegin(numprocessors, numprofilers, affinity);
  104. #endif
  105.  
  106. #ifdef DEBUG_STARTUP
  107.         cout << "after Main::init, mainstacksizes = " << mainstacksizes <<"\n";
  108. #endif DEBUG_STARTUP
  109.  
  110. #ifdef sun
  111.     numprocessors = 1;
  112. #endif sun
  113. #ifdef vax
  114.     // VAX unix version runs on uniprocessors only for now.
  115.     numprocessors = 1;
  116. #endif vax
  117.  
  118.     if (thisthread != mainthread)
  119.         thisthread = mainthread;
  120.     prestoState = MAIN_MAIN;
  121.  
  122.     //
  123.     // prime the scheduler
  124.     //
  125. #ifdef DEBUG_STARTUP
  126.         cout << "invoking ctor for scheduler\n";
  127. #endif DEBUG_STARTUP
  128.     if (sched == (Scheduler*)0)
  129.         sched = new Scheduler(numprocessors,quantum);  // sets thisproc
  130.  
  131.     //
  132.     // t becomes the first schedulable thread
  133.     // Since we only have one processor, and no preemption here
  134.     // we return with t on the ready q.
  135.     //
  136. #ifdef DEBUG_STARTUP
  137.         cout << "making thread SCHEDULER_STARTER\n";
  138. #endif DEBUG_STARTUP
  139.     t = mainthread->newthread("SCHEDULER_STARTER");
  140.     t->nonpreemptable();
  141.  
  142.     t->start(sched, (PFany)(sched->invoke));    
  143.  
  144.     //
  145.     // Build the main threads and readyq them
  146.     //
  147. #ifdef DEBUG_STARTUP
  148.         cout << "making the main threads\n";
  149. #endif DEBUG_STARTUP
  150.     for (int i = 0; i < nummainthreads; i++)    {
  151.         char buf[8];        // lotsa threads
  152.         sprintf(buf,"%s.%d", MAINNAME, i);
  153.         char *name = new char[strlen(buf)+1];
  154.         strcpy(name, buf);
  155.         Thread *t = mainthread->newthread(name, i+1, mainstacksizes);
  156.         t->start(this, (PFany)(this->main));
  157.     }
  158.  
  159.     // Crank up the scheduler in the context of thisthread.
  160.     //    This will read the SCHEDULER thread off the
  161.     //    the readyq, invoke that thread
  162.     //    on the scheduler itself, which will cause the scheduler
  163.     //    to then create numprocessors copies of itself (each
  164.     //    running on its own stack).  The SCHEDULER thread
  165.     //    is guaranteed not to block and will be the first thread
  166.     //    to terminate, so we can quickly reuse it.
  167.     //    
  168.  
  169.     //
  170.     // Bind this thread to a processor which will start up all the
  171.     // coschedulers.  Thisthread will not be queued since it's a scheduler.
  172.     // We have to start it up directly.
  173.     //
  174. #ifdef DEBUG_STARTUP
  175.         cout << "about to start scheduler\n"; cout.flush ();
  176. #endif DEBUG_STARTUP
  177.  
  178.     mainthread->isrunning();
  179.     thisproc->invoke();        // start thisproc which will start 
  180.                     // the scheduler thread which will
  181.                     // start all the processor threads
  182.                     // which will then pull the main
  183.                     // threads off the readyq
  184.     mainthread->isnotrunning();
  185.  
  186.     //
  187.     // Since shutdown is not synchronized, there is a race condition which
  188.     // can result in sched getting deleted while process objects are still
  189.     // active.  If it hurts, don't do it.
  190.     //
  191.     //    if (sched)
  192.     //        delete sched;
  193.     //
  194.  
  195.     delete thisproc;
  196.     thisproc = sysproc;
  197.  
  198.     //delete thisthread;         /* done in runrun */
  199.     //thisthread = 0;
  200.     //
  201.     // Threads are out... thisthread is undefined at this point
  202.     //
  203.     cout << "HALT\n";        // should be single unix process
  204.     prestoState = MAIN_DONE;
  205.     main_exit_code = Main::done();
  206. }
  207.  
  208.  
  209. Main::~Main()
  210. {
  211. }
  212.  
  213.  
  214. //
  215. // Preallocate tons of threads in the parent process's address space.
  216. // This is a temporary hack to get around the brain-damaged sequent
  217. // shared memory implementation.
  218. //
  219. // NOTE: not called from anywhere in Presto.
  220. //
  221. int
  222. Main::preallocthreads(int cnt, int sz)
  223. {
  224.     int j;
  225.  
  226.     j = cnt;
  227.     Thread **tlist = new Thread*[j];
  228.     while (j--)    {    
  229.         tlist[j] = thisthread->newthread("any",    
  230.                     0,    // any id
  231.                     sz);    // stack size
  232.     }
  233.     j = cnt;
  234.     while (j--)    {
  235.         delete tlist[j];
  236.     }
  237.     delete tlist;
  238.     return cnt;
  239. }
  240.  
  241. typedef void    (*PF)();
  242. extern PF set_new_handler(PF);
  243. extern void failed_malloc();
  244.  
  245. void
  246. main(int argc, char **argv, char **envp)
  247. {
  248.     set_new_handler(failed_malloc);
  249.  
  250.     //
  251.     // Create a new main thread.
  252.     //
  253. //    Main    *MAIN = new Main(argc, argv, envp);
  254.     MAIN = new Main(argc, argv, envp);
  255.  
  256.         MAIN->run ();
  257.  
  258.     if (MAIN)
  259.         delete MAIN;
  260.  
  261.     prestoState = STATIC_DTOR;
  262.  
  263.     extern wait(int*);
  264.     while (::wait(0) != -1)        // collect kids, get execution stats
  265.         continue;
  266.  
  267.     exit(main_exit_code);
  268. }    
  269.