threadimpl.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Some notes on locking:
  3. *
  4. * All the locking woes come from implementing
  5. * threadinterrupt (and threadkill).
  6. *
  7. * _threadgetproc()->thread is always a live pointer.
  8. * p->threads, p->ready, and _threadrgrp also contain
  9. * live thread pointers. These may only be consulted
  10. * while holding p->lock or _threadrgrp.lock; in procs
  11. * other than p, the pointers are only guaranteed to be live
  12. * while the lock is still being held.
  13. *
  14. * Thread structures can only be freed by the proc
  15. * they belong to. Threads marked with t->inrendez
  16. * need to be extracted from the _threadrgrp before
  17. * being freed.
  18. *
  19. * _threadrgrp.lock cannot be acquired while holding p->lock.
  20. */
  21. typedef struct Pqueue Pqueue;
  22. typedef struct Rgrp Rgrp;
  23. typedef struct Tqueue Tqueue;
  24. typedef struct Thread Thread;
  25. typedef struct Execargs Execargs;
  26. typedef struct Proc Proc;
  27. /* must match list in sched.c */
  28. typedef enum
  29. {
  30. Dead,
  31. Running,
  32. Ready,
  33. Rendezvous,
  34. } State;
  35. typedef enum
  36. {
  37. Channone,
  38. Chanalt,
  39. Chansend,
  40. Chanrecv,
  41. } Chanstate;
  42. enum
  43. {
  44. RENDHASH = 13,
  45. Printsize = 2048,
  46. NPRIV = 8,
  47. };
  48. struct Rgrp
  49. {
  50. Lock lock;
  51. Thread *hash[RENDHASH];
  52. };
  53. struct Tqueue /* Thread queue */
  54. {
  55. int asleep;
  56. Thread *head;
  57. Thread **tail;
  58. };
  59. struct Thread
  60. {
  61. Lock lock; /* protects thread data structure */
  62. jmp_buf sched; /* for context switches */
  63. int id; /* thread id */
  64. int grp; /* thread group */
  65. int moribund; /* thread needs to die */
  66. State state; /* run state */
  67. State nextstate; /* next run state */
  68. uchar *stk; /* top of stack (lowest address of stack) */
  69. uint stksize; /* stack size */
  70. Thread *next; /* next on ready queue */
  71. Proc *proc; /* proc of this thread */
  72. Thread *nextt; /* next on list of threads in this proc*/
  73. int ret; /* return value for Exec, Fork */
  74. char *cmdname; /* ptr to name of thread */
  75. int inrendez;
  76. Thread *rendhash; /* Trgrp linked list */
  77. void* rendtag; /* rendezvous tag */
  78. void* rendval; /* rendezvous value */
  79. int rendbreak; /* rendezvous has been taken */
  80. Chanstate chan; /* which channel operation is current */
  81. Alt *alt; /* pointer to current alt structure (debugging) */
  82. void* udata[NPRIV]; /* User per-thread data pointer */
  83. };
  84. struct Execargs
  85. {
  86. char *prog;
  87. char **args;
  88. int fd[2];
  89. };
  90. struct Proc
  91. {
  92. Lock lock;
  93. jmp_buf sched; /* for context switches */
  94. int pid; /* process id */
  95. int splhi; /* delay notes */
  96. Thread *thread; /* running thread */
  97. int needexec;
  98. Execargs exec; /* exec argument */
  99. Proc *newproc; /* fork argument */
  100. char exitstr[ERRMAX]; /* exit status */
  101. int rforkflag;
  102. int nthreads;
  103. Tqueue threads; /* All threads of this proc */
  104. Tqueue ready; /* Runnable threads */
  105. Lock readylock;
  106. char printbuf[Printsize];
  107. int blocked; /* In a rendezvous */
  108. int pending; /* delayed note pending */
  109. int nonotes; /* delay notes */
  110. uint nextID; /* ID of most recently created thread */
  111. Proc *next; /* linked list of Procs */
  112. void *arg; /* passed between shared and unshared stk */
  113. char str[ERRMAX]; /* used by threadexits to avoid malloc */
  114. void* udata; /* User per-proc data pointer */
  115. char threadint; /* tag for threadexitsall() */
  116. };
  117. struct Pqueue { /* Proc queue */
  118. Lock lock;
  119. Proc *head;
  120. Proc **tail;
  121. };
  122. struct Ioproc
  123. {
  124. int tid;
  125. Channel *c, *creply;
  126. int inuse;
  127. long (*op)(va_list*);
  128. va_list arg;
  129. long ret;
  130. char err[ERRMAX];
  131. Ioproc *next;
  132. };
  133. void _freeproc(Proc*);
  134. void _freethread(Thread*);
  135. Proc* _newproc(void(*)(void*), void*, uint, char*, int, int);
  136. int _procsplhi(void);
  137. void _procsplx(int);
  138. void _sched(void);
  139. int _schedexec(Execargs*);
  140. void _schedexecwait(void);
  141. void _schedexit(Proc*);
  142. int _schedfork(Proc*);
  143. void _schedinit(void*);
  144. void _systhreadinit(void);
  145. void _threadassert(char*);
  146. void _threadbreakrendez(void);
  147. void _threaddebug(ulong, char*, ...);
  148. void _threadexitsall(char*);
  149. void _threadflagrendez(Thread*);
  150. Proc* _threadgetproc(void);
  151. void _threadsetproc(Proc*);
  152. void _threadinitstack(Thread*, void(*)(void*), void*);
  153. void* _threadmalloc(long, int);
  154. void _threadnote(void*, char*);
  155. void _threadready(Thread*);
  156. void* _threadrendezvous(void*, void*);
  157. void _threadsignal(void);
  158. void _threadsysfatal(char*, va_list);
  159. long _xdec(long*);
  160. void _xinc(long*);
  161. extern int _threaddebuglevel;
  162. extern char* _threadexitsallstatus;
  163. extern Pqueue _threadpq;
  164. extern Channel* _threadwaitchan;
  165. extern Rgrp _threadrgrp;
  166. #define DBGAPPL (1 << 0)
  167. #define DBGSCHED (1 << 16)
  168. #define DBGCHAN (1 << 17)
  169. #define DBGREND (1 << 18)
  170. /* #define DBGKILL (1 << 19) */
  171. #define DBGNOTE (1 << 20)
  172. #define DBGEXEC (1 << 21)
  173. #define ioproc_arg(io, type) (va_arg((io)->arg, type))