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