2 * Some notes on locking:
4 * All the locking woes come from implementing
5 * threadinterrupt (and threadkill).
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.
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
19 * _threadrgrp.lock cannot be acquired while holding p->lock.
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 typedef struct Iocall Iocall;
30 /* must match list in sched.c */
57 Thread *hash[RENDHASH];
60 struct Tqueue /* Thread queue */
69 Lock lock; /* protects thread data structure */
70 jmp_buf sched; /* for context switches */
71 int id; /* thread id */
72 int grp; /* thread group */
73 int moribund; /* thread needs to die */
74 State state; /* run state */
75 State nextstate; /* next run state */
76 uchar *stk; /* top of stack (lowest address of stack) */
77 uint stksize; /* stack size */
78 Thread *next; /* next on ready queue */
80 Proc *proc; /* proc of this thread */
81 Thread *nextt; /* next on list of threads in this proc*/
82 int ret; /* return value for Exec, Fork */
84 char *cmdname; /* ptr to name of thread */
87 Thread *rendhash; /* Trgrp linked list */
88 void* rendtag; /* rendezvous tag */
89 void* rendval; /* rendezvous value */
90 int rendbreak; /* rendezvous has been taken */
92 Chanstate chan; /* which channel operation is current */
93 Alt *alt; /* pointer to current alt structure (debugging) */
95 void* udata[NPRIV]; /* User per-thread data pointer */
108 jmp_buf sched; /* for context switches */
109 int pid; /* process id */
110 int splhi; /* delay notes */
111 Thread *thread; /* running thread */
114 Execargs exec; /* exec argument */
115 Proc *newproc; /* fork argument */
116 char exitstr[ERRMAX]; /* exit status */
120 Tqueue threads; /* All threads of this proc */
121 Tqueue ready; /* Runnable threads */
124 char printbuf[Printsize];
125 int blocked; /* In a rendezvous */
126 int pending; /* delayed note pending */
127 int nonotes; /* delay notes */
128 uint nextID; /* ID of most recently created thread */
129 Proc *next; /* linked list of Procs */
131 void *arg; /* passed between shared and unshared stk */
132 char str[ERRMAX]; /* used by threadexits to avoid malloc */
134 void* wdata; /* Lib(worker) per-proc data pointer */
135 void* udata; /* User per-proc data pointer */
136 char threadint; /* tag for threadexitsall() */
139 struct Pqueue /* Proc queue */
156 long (*op)(va_list*);
162 Proc* _newproc(void(*)(void*), void*, uint, char*, int, int);
163 int _procsplhi(void);
166 int _schedexec(Execargs*);
167 void _schedexecwait(void);
168 void _schedexit(Proc*);
169 int _schedfork(Proc*);
170 void _schedinit(void*);
171 void _systhreadinit(void);
172 void _threadassert(char*);
173 void _threadbreakrendez(void);
174 void _threaddebug(ulong, char*, ...);
175 void _threadexitsall(char*);
176 void _threadflagrendez(Thread*);
177 Proc* _threadgetproc(void);
178 void _threadsetproc(Proc*);
179 void _threadinitstack(Thread*, void(*)(void*), void*);
180 void* _threadmalloc(long, int);
181 void _threadnote(void*, char*);
182 void _threadready(Thread*);
183 void* _threadrendezvous(void*, void*);
184 void _threadsysfatal(char*, va_list);
185 void** _workerdata(void);
187 extern int _threaddebuglevel;
188 extern char* _threadexitsallstatus;
189 extern Pqueue _threadpq;
190 extern Channel* _threadwaitchan;
191 extern Rgrp _threadrgrp;
193 #define DBGAPPL (1 << 0)
194 #define DBGSCHED (1 << 16)
195 #define DBGCHAN (1 << 17)
196 #define DBGREND (1 << 18)
197 /* #define DBGKILL (1 << 19) */
198 #define DBGNOTE (1 << 20)
199 #define DBGEXEC (1 << 21)
201 #define ioproc_arg(io, type) (va_arg((io)->arg, type))