Blob


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