home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / presto / prest_04.lha / src / threads.h < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-08  |  6.1 KB  |  227 lines

  1. class SynchroObject;
  2. class Process;
  3. class Thread;
  4. class ThreadQ;
  5. class Scheduler;
  6. class Callstate;
  7.  
  8. extern Thread *systhread;
  9.  
  10. extern private_t Thread    *thisthread;    // always refers to running thread
  11. extern Process* thisproc;
  12.         
  13. #define TF_SCHEDULER    0x01        /* special thread.  Loops only */
  14. #define TF_KEEPSTACK    0x02        /* dont init stack on runrun */
  15. #define TF_INCOMPLETE    0x04        /* must acquire a stack before run */
  16. #define TF_NONPREEMPTABLE 0x08        /* can not preempt */
  17. #define TF_WILLJOIN    0x20        /* someone will join on it */
  18.  
  19.  
  20. #define TS_IDLE        0x01        /* useful, but not started    */
  21. #define TS_RUNNING    0x02        /* busy                */
  22. #define TS_READY    0x04        /* living in the readyq        */
  23.  
  24. #define TS_BLOCKED    0x20        /* blocked.  Don't care on what */
  25.  
  26. #define TS_LOCKED    0x80        /* unused            */
  27. #define TS_STOPPED    0x100        /* thread is unconditionally stopped */
  28.  
  29. #define TS_VIRGIN    0x400        /* thread not yet begun     */
  30. #define TS_ERROR    0x800        /* something amiss        */
  31. #define TS_DELETE    0x1000        /* no more trips to bed        */
  32. //
  33. // FINISHED should be part of the flags and not the state.
  34. //
  35. #define TS_FINISHED    0x2000        /* all done */
  36. #define TS_ANY        (~0)        /* matches all */
  37. #define TP_BASEPRIO    0        /* base priority */
  38.  
  39.  
  40.  
  41. //
  42. // WARNING: A CHANGE TO THIS CLASS OR ANY OF ITS BASE CLASSES MAY REQUIRE
  43. // RECOMPUTING THE STRUCT OFFSETS USED IN swtch!!
  44. //
  45.  
  46. class Stack;
  47. class Thread : public Object    {
  48. protected:
  49.     // *** The offsets of t_csp, t_fp and t_proc are known to swtch().
  50.     int    *t_csp;            // current stack pointer
  51.     int    *t_fp;            // frame pointer
  52.     Process    *t_proc;        // who is running me now
  53.     union    {
  54.         Stack     *stack;
  55.         int    neededstacksize;
  56.     } ut_stack;
  57. #define t_stack            ut_stack.stack    
  58. #define t_neededstacksize     ut_stack.neededstacksize
  59.     int    t_state;        // current state
  60.     int     t_flags;        // internal only flags
  61. #ifdef sun
  62.     int     t_pc;
  63. #endif sun
  64. #ifdef vax
  65.     int    t_pc;            // needed for Ultrix preemption
  66. #endif vax
  67.     int    t_tag;            // given tag on birth (UNIQUE)
  68.     int    t_tid;            // user's tag name
  69.     int    t_pri;            // thread priority
  70.     int    t_expired;        // true iff timeslice expired
  71.     int    t_slockcount;        // number of spinlocks held/spinning
  72.     Objany    t_data;            // for getdata/setdata
  73.     Objany        t_boundobj;    // what we are bound to
  74.     Callstate    t_callstate;    // initial call state
  75.     SynchroObject    *t_blockedon;    // Synchro object we are blked on 
  76. // redo    
  77.     union    {
  78.         Thread*        thread;    // thread waiting
  79.         Objany        value;    // ready value
  80.     } ut_join;
  81. #define t_jthread        ut_join.thread
  82. #define t_jvalue        ut_join.value
  83.     virtual    void    t_start1(Objany obj);    // second half of fork/start
  84. public:
  85.     Thread(char* name=0, int tid = 0,
  86.          long ssiz = DEFSTACKSIZ, int musthavestack = 0);
  87.     Thread(int tid);
  88.     virtual Thread* newthread(char* name=0, int tid = 0,    // vtl ctr
  89.          long ssiz = DEFSTACKSIZ, int musthavestack = 0);
  90.     virtual ~Thread();                // nuke a thread
  91.     virtual int     start(Objany obj, PFany pf, ...);    // enqueue
  92. #define NOJOIN      0
  93. #define WILLJOIN TF_WILLJOIN
  94.             // Usage: thisthread->fork({NO,WILL}JOIN, ...)
  95.     virtual Thread* fork(int needjoin, Objany obj, PFany pf, ...);
  96.     virtual int     runrun();        // LIFE STARTS HERE 
  97.     virtual int     run();
  98.     void    swtch();            // back to the sched thread
  99.     virtual void     sleep(SynchroObject* so = 0);    // relinquish
  100.     virtual void     wakeup(SynchroObject* so = 0);    // resume
  101.     virtual void    willjoin();        // want to join
  102.     virtual Objany    join();            // please join
  103.     virtual void    terminate(Objany retobj=0);    // thread is finished
  104. //    virtual void     setaffinity(Process* p);    // mark affinity
  105.     void    setdata(Objany data)
  106.         { t_data = data; }
  107.     Objany  getdata()
  108.         { return t_data; }
  109.     void    setstate(int newstate)
  110.         { t_state = newstate; }
  111.     void    orstate(int st)
  112.         // { ATOMIC_ORL(&t_state, st); }
  113.         { t_state |= st; }
  114.     void    andstate(int st)
  115.         // { ATOMIC_ANDL(&t_state, st); }
  116.         { t_state &= st; }
  117.     void    isready()
  118.         { orstate(TS_READY); }
  119.     void    setflags(int newflags)
  120.         { t_flags = newflags; }
  121.     void    holdingspinlock()
  122.         { t_slockcount++; }
  123.     void    releasingspinlock()        
  124.         { t_slockcount--; }
  125.     int    inspinlock()
  126.         { return(t_slockcount); }
  127.     inline Stack    *stack();
  128.     int    *csp()
  129.         { return t_csp; }        
  130.     int    flags()
  131.         { return t_flags; }
  132. #ifdef sun
  133.     void    setpc(int pc)
  134.         {t_pc = pc;}
  135.     int    getpc()
  136.         {return t_pc;}
  137. #endif sun
  138. #ifdef vax
  139.     void    setpc(int pc)
  140.         {t_pc = pc;}
  141.     int    getpc()
  142.         {return t_pc;}
  143. #endif vax
  144.     int     state()
  145.         { return t_state; }
  146.     int    tag()    
  147.         { return t_tag; }
  148.     int    tid()
  149.         { return t_tid; }        
  150.     void    setpri(int newpri)    // beware of multiple writers
  151.         { t_pri= newpri; }
  152.     int     getpri()
  153.         { return t_pri; }
  154.     void     setproc(Process* p)
  155.         { t_proc = p; }
  156.     Process *getproc()
  157.         { return t_proc; }
  158.     Process **proc()
  159.         { return &t_proc; }
  160.     inline void    isrunning();    // mark thread running
  161.     void        isrunning2();    // but wait until it is done running
  162.     inline void    isnotrunning(); // as set by someone else
  163.     int stackcnt()
  164.         { return stack()->numstacksbuilt(); }
  165.     int tagcnt();
  166.     // 
  167.     // Preemption related cruft
  168.     //
  169.     void preemptable()
  170.         { t_flags &= ~TF_NONPREEMPTABLE; }
  171.     void nonpreemptable()
  172.         { t_flags |= TF_NONPREEMPTABLE; }
  173.     int ispreemptable()
  174.         { return ( (t_flags & TF_NONPREEMPTABLE) == 0 ); }
  175.     double cputime();        // in seconds
  176.     int canpreempt();
  177.     virtual void  print(ostream& = cout);
  178. friend class ThreadQ;
  179. friend class ThreadQUnlocked;
  180. };
  181.  
  182. //
  183. // Mark a thread as running.  This should be called before
  184. // runrun.  If the thread is already running, the caller will
  185. // wait. This guarantess that we don't have two scheduling threads
  186. // trouncing on this poor thread's stack. One guy coming down
  187. // into runrun, while the other guy is trying to return from it.
  188. // We don't have to lock anything, since there is only one ordering of
  189. // ops on the state that can cause problems, 
  190. // and the problems are solved by delaying the
  191. // second thread here.
  192. //
  193.  
  194.  
  195. inline void
  196. Thread::isrunning()
  197. {
  198.  
  199.     if (t_state&TS_RUNNING)
  200.         (void)isrunning2();        // looping wait
  201.     orstate(TS_RUNNING);
  202. }
  203.  
  204.  
  205. //
  206. // This should be called after runrun
  207. //
  208. inline void
  209. Thread::isnotrunning()
  210. {
  211.     // if not finished, and not running, balk
  212.     if ( ((t_state&TS_FINISHED) == 0) && ((t_state&TS_RUNNING)== 0)    )
  213.         error("Thread is already not running\n");
  214.     else
  215.         andstate(~TS_RUNNING);
  216. }
  217.  
  218. inline
  219. Stack*
  220. Thread::stack()    
  221. {
  222.     if (t_flags&TF_INCOMPLETE) 
  223.         error("Thread has no stack");
  224.       return t_stack; 
  225. }
  226.  
  227.