threadimpl.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. };
  47. struct Rgrp
  48. {
  49. Lock lock;
  50. Thread *hash[RENDHASH];
  51. };
  52. struct Tqueue /* Thread queue */
  53. {
  54. int asleep;
  55. Thread *head;
  56. Thread **tail;
  57. };
  58. struct Thread
  59. {
  60. Lock lock; /* protects thread data structure */
  61. jmp_buf sched; /* for context switches */
  62. int id; /* thread id */
  63. int grp; /* thread group */
  64. int moribund; /* thread needs to die */
  65. State state; /* run state */
  66. State nextstate; /* next run state */
  67. uchar *stk; /* top of stack (lowest address of stack) */
  68. uint stksize; /* stack size */
  69. Thread *next; /* next on ready queue */
  70. Proc *proc; /* proc of this thread */
  71. Thread *nextt; /* next on list of threads in this proc*/
  72. int ret; /* return value for Exec, Fork */
  73. char *cmdname; /* ptr to name of thread */
  74. int inrendez;
  75. Thread *rendhash; /* Trgrp linked list */
  76. ulong rendtag; /* rendezvous tag */
  77. ulong rendval; /* rendezvous value */
  78. int rendbreak; /* rendezvous has been taken */
  79. Chanstate chan; /* which channel operation is current */
  80. Alt *alt; /* pointer to current alt structure (debugging) */
  81. void* udata; /* User per-thread data pointer */
  82. };
  83. struct Execargs
  84. {
  85. char *prog;
  86. char **args;
  87. int fd[2];
  88. };
  89. struct Proc
  90. {
  91. Lock lock;
  92. jmp_buf sched; /* for context switches */
  93. int pid; /* process id */
  94. int splhi; /* delay notes */
  95. Thread *thread; /* running thread */
  96. int needexec;
  97. Execargs exec; /* exec argument */
  98. Proc *newproc; /* fork argument */
  99. char exitstr[ERRMAX]; /* exit status */
  100. int rforkflag;
  101. int nthreads;
  102. Tqueue threads; /* All threads of this proc */
  103. Tqueue ready; /* Runnable threads */
  104. Lock readylock;
  105. char printbuf[Printsize];
  106. int blocked; /* In a rendezvous */
  107. int pending; /* delayed note pending */
  108. int nonotes; /* delay notes */
  109. uint nextID; /* ID of most recently created thread */
  110. Proc *next; /* linked list of Procs */
  111. void *arg; /* passed between shared and unshared stk */
  112. char str[ERRMAX]; /* used by threadexits to avoid malloc */
  113. void* udata; /* User per-proc data pointer */
  114. };
  115. struct Pqueue { /* Proc queue */
  116. Lock lock;
  117. Proc *head;
  118. Proc **tail;
  119. };
  120. struct Ioproc
  121. {
  122. int pid;
  123. Channel *c;
  124. int inuse;
  125. long (*op)(va_list*);
  126. va_list arg;
  127. long ret;
  128. char err[ERRMAX];
  129. Ioproc *next;
  130. };
  131. void _freeproc(Proc*);
  132. void _freethread(Thread*);
  133. Proc* _newproc(void(*)(void*), void*, uint, char*, int, int);
  134. int _procsplhi(void);
  135. void _procsplx(int);
  136. void _sched(void);
  137. int _schedexec(Execargs*);
  138. void _schedexecwait(void);
  139. void _schedexit(Proc*);
  140. int _schedfork(Proc*);
  141. void _schedinit(void*);
  142. void _systhreadinit(void);
  143. void _threadassert(char*);
  144. void _threadbreakrendez(void);
  145. void _threaddebug(ulong, char*, ...);
  146. void _threadexitsall(char*);
  147. void _threadflagrendez(Thread*);
  148. Proc* _threadgetproc(void);
  149. void _threadsetproc(Proc*);
  150. void _threadinitstack(Thread*, void(*)(void*), void*);
  151. void* _threadmalloc(long, int);
  152. void _threadnote(void*, char*);
  153. void _threadready(Thread*);
  154. ulong _threadrendezvous(ulong, ulong);
  155. void _threadsignal(void);
  156. void _threadsysfatal(char*, va_list);
  157. long _xdec(long*);
  158. void _xinc(long*);
  159. extern int _threaddebuglevel;
  160. extern char* _threadexitsallstatus;
  161. extern Pqueue _threadpq;
  162. extern Channel* _threadwaitchan;
  163. extern Rgrp _threadrgrp;
  164. #define DBGAPPL (1 << 0)
  165. #define DBGSCHED (1 << 16)
  166. #define DBGCHAN (1 << 17)
  167. #define DBGREND (1 << 18)
  168. /* #define DBGKILL (1 << 19) */
  169. #define DBGNOTE (1 << 20)
  170. #define DBGEXEC (1 << 21)
  171. #define ioproc_arg(io, type) (va_arg((io)->arg, type))