home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / quartz / quartz10.lha / src / presto / threads.h < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  6.1 KB  |  229 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.         Stack   *t_stack;               // thread's stack
  54.         int     t_stack_size;           // size of stack
  55.     int    t_state;        // current state
  56.     int     t_flags;        // internal only flags
  57. #ifdef sun
  58.     int     t_pc;
  59. #endif sun
  60. #ifdef vax
  61.     int    t_pc;            // needed for Ultrix preemption
  62. #endif vax
  63. #ifdef PROFILE
  64.     int qThread;
  65. #endif
  66.     int    t_tag;            // given tag on birth (UNIQUE)
  67.     int    t_tid;            // user's tag name
  68.     int    t_pri;            // thread priority
  69.     int    t_expired;        // true iff timeslice expired
  70.     int    t_slockcount;        // number of spinlocks held/spinning
  71.     Objany    t_data;            // for getdata/setdata
  72.     Objany        t_boundobj;    // what we are bound to
  73.     Callstate    t_callstate;    // initial call state
  74.     SynchroObject    *t_blockedon;    // Synchro object we are blked on 
  75. // redo    
  76.     union    {
  77.         Thread*        thread;    // thread waiting
  78.         Objany        value;    // ready value
  79.     } ut_join;
  80. #define t_jthread        ut_join.thread
  81. #define t_jvalue        ut_join.value
  82.     virtual    void    t_start1(Objany obj);    // second half of fork/start
  83. public:
  84.     Thread(char* name=0, int tid = 0, long ssiz = DEFSTACKSIZ);
  85.     Thread(int tid);
  86.     virtual Thread* newthread(char* name=0, int tid = 0,    // vtl ctr
  87.          long ssiz = DEFSTACKSIZ);
  88.     virtual ~Thread();                // nuke a thread
  89.     virtual int     start(Objany obj, PFany pf, ...);    // enqueue
  90. #define NOJOIN      0
  91. #define WILLJOIN TF_WILLJOIN
  92.             // Usage: thisthread->fork({NO,WILL}JOIN, ...)
  93.     virtual Thread* fork(int needjoin, Objany obj, PFany pf, ...);
  94.     virtual int     runrun();        // LIFE STARTS HERE 
  95.     virtual int     run();
  96.     void    swtch();            // back to the sched thread
  97.     virtual void     sleep(SynchroObject* so = 0);    // relinquish
  98.     virtual void     wakeup(SynchroObject* so = 0);    // resume
  99.     virtual void    willjoin();        // want to join
  100.     virtual Objany    join();            // please join
  101.     virtual void    terminate(Objany retobj=0);    // thread is finished
  102. //    virtual void     setaffinity(Process* p);    // mark affinity
  103.     void    setdata(Objany data)
  104.         { t_data = data; }
  105.     Objany  getdata()
  106.         { return t_data; }
  107.     void    setstate(int newstate)
  108.         { t_state = newstate; }
  109.     void    orstate(int st)
  110.         // { ATOMIC_ORL(&t_state, st); }
  111.         { t_state |= st; }
  112.     void    andstate(int st)
  113.         // { ATOMIC_ANDL(&t_state, st); }
  114.         { t_state &= st; }
  115.     void    isready()
  116.         { orstate(TS_READY); }
  117.     void    setflags(int newflags)
  118.         { t_flags = newflags; }
  119.     void    holdingspinlock()
  120.         { t_slockcount++; }
  121.     void    releasingspinlock()        
  122.         { t_slockcount--; }
  123.     int    inspinlock()
  124.         { return(t_slockcount); }
  125.     inline Stack    *stack();
  126.     int    *csp()
  127.         { return t_csp; }        
  128.     int    flags()
  129.         { return t_flags; }
  130. #ifdef sun
  131.     void    setpc(int pc)
  132.         {t_pc = pc;}
  133.     int    getpc()
  134.         {return t_pc;}
  135. #endif sun
  136. #ifdef vax
  137.     void    setpc(int pc)
  138.         {t_pc = pc;}
  139.     int    getpc()
  140.         {return t_pc;}
  141. #endif vax
  142.     int     state()
  143.         { return t_state; }
  144.     int    tag()    
  145.         { return t_tag; }
  146.     int    tid()
  147.         { return t_tid; }        
  148.     void    setpri(int newpri)    // beware of multiple writers
  149.         { t_pri= newpri; }
  150.     int     getpri()
  151.         { return t_pri; }
  152.     void     setproc(Process* p)
  153.         { t_proc = p; }
  154.     Process *getproc()
  155.         { return t_proc; }
  156.     Process **proc()
  157.         { return &t_proc; }
  158.     inline void    isrunning();    // mark thread running
  159.     void        isrunning2();    // but wait until it is done running
  160.     inline void    isnotrunning(); // as set by someone else
  161. #ifdef PROFILE
  162.     inline int    getqThread()
  163.         { return qThread; }
  164. #endif
  165.     int stackcnt()
  166.         { return stack()->numstacksbuilt(); }
  167.     int tagcnt();
  168.     // 
  169.     // Preemption related cruft
  170.     //
  171.     void preemptable()
  172.         { t_flags &= ~TF_NONPREEMPTABLE; }
  173.     void nonpreemptable()
  174.         { t_flags |= TF_NONPREEMPTABLE; }
  175.     int ispreemptable()
  176.         { return ( (t_flags & TF_NONPREEMPTABLE) == 0 ); }
  177.     double cputime();        // in seconds
  178.     int canpreempt();
  179.     virtual void  print(ostream& = cout);
  180. friend class ThreadQ;
  181. friend class ThreadQUnlocked;
  182. };
  183.  
  184. //
  185. // Mark a thread as running.  This should be called before
  186. // runrun.  If the thread is already running, the caller will
  187. // wait. This guarantess that we don't have two scheduling threads
  188. // trouncing on this poor thread's stack. One guy coming down
  189. // into runrun, while the other guy is trying to return from it.
  190. // We don't have to lock anything, since there is only one ordering of
  191. // ops on the state that can cause problems, 
  192. // and the problems are solved by delaying the
  193. // second thread here.
  194. //
  195.  
  196.  
  197. inline void
  198. Thread::isrunning()
  199. {
  200.  
  201.     if (t_state&TS_RUNNING)
  202.         (void)isrunning2();        // looping wait
  203.     orstate(TS_RUNNING);
  204. }
  205.  
  206.  
  207. //
  208. // This should be called after runrun
  209. //
  210. inline void
  211. Thread::isnotrunning()
  212. {
  213.     // if not finished, and not running, balk
  214.     if ( ((t_state&TS_FINISHED) == 0) && ((t_state&TS_RUNNING)== 0)    )
  215.         error("Thread is already not running\n");
  216.     else
  217.         andstate(~TS_RUNNING);
  218. }
  219.  
  220. inline
  221. Stack*
  222. Thread::stack()    
  223. {
  224.     if (t_flags&TF_INCOMPLETE) 
  225.         error("Thread has no stack");
  226.       return t_stack; 
  227. }
  228.  
  229.