Blame


1 f1e8706d 2004-12-27 devnull #include "u.h"
2 f1e8706d 2004-12-27 devnull #include <errno.h>
3 f1e8706d 2004-12-27 devnull #include <sys/types.h>
4 f1e8706d 2004-12-27 devnull #include <sys/wait.h>
5 f1e8706d 2004-12-27 devnull #include <sched.h>
6 f1e8706d 2004-12-27 devnull #include <signal.h>
7 f1e8706d 2004-12-27 devnull #include "libc.h"
8 f1e8706d 2004-12-27 devnull #include "thread.h"
9 f1e8706d 2004-12-27 devnull #include "threadimpl.h"
10 f1e8706d 2004-12-27 devnull
11 2c87dda8 2004-12-28 devnull int ngetpid;
12 2c87dda8 2004-12-28 devnull
13 2c87dda8 2004-12-28 devnull
14 f1e8706d 2004-12-27 devnull /*
15 f1e8706d 2004-12-27 devnull * spin locks
16 f1e8706d 2004-12-27 devnull */
17 f1e8706d 2004-12-27 devnull extern int _tas(int*);
18 f1e8706d 2004-12-27 devnull
19 f1e8706d 2004-12-27 devnull void
20 f1e8706d 2004-12-27 devnull _threadunlock(Lock *l, ulong pc)
21 f1e8706d 2004-12-27 devnull {
22 f1e8706d 2004-12-27 devnull USED(pc);
23 f1e8706d 2004-12-27 devnull
24 f1e8706d 2004-12-27 devnull l->held = 0;
25 f1e8706d 2004-12-27 devnull }
26 f1e8706d 2004-12-27 devnull
27 f1e8706d 2004-12-27 devnull int
28 f1e8706d 2004-12-27 devnull _threadlock(Lock *l, int block, ulong pc)
29 f1e8706d 2004-12-27 devnull {
30 f1e8706d 2004-12-27 devnull int i;
31 f1e8706d 2004-12-27 devnull
32 f1e8706d 2004-12-27 devnull USED(pc);
33 f1e8706d 2004-12-27 devnull
34 f1e8706d 2004-12-27 devnull /* once fast */
35 f1e8706d 2004-12-27 devnull if(!_tas(&l->held))
36 f1e8706d 2004-12-27 devnull return 1;
37 f1e8706d 2004-12-27 devnull if(!block)
38 f1e8706d 2004-12-27 devnull return 0;
39 f1e8706d 2004-12-27 devnull
40 f1e8706d 2004-12-27 devnull /* a thousand times pretty fast */
41 f1e8706d 2004-12-27 devnull for(i=0; i<1000; i++){
42 f1e8706d 2004-12-27 devnull if(!_tas(&l->held))
43 f1e8706d 2004-12-27 devnull return 1;
44 f1e8706d 2004-12-27 devnull sched_yield();
45 f1e8706d 2004-12-27 devnull }
46 f1e8706d 2004-12-27 devnull /* now nice and slow */
47 f1e8706d 2004-12-27 devnull for(i=0; i<1000; i++){
48 f1e8706d 2004-12-27 devnull if(!_tas(&l->held))
49 f1e8706d 2004-12-27 devnull return 1;
50 f1e8706d 2004-12-27 devnull usleep(100*1000);
51 f1e8706d 2004-12-27 devnull }
52 f1e8706d 2004-12-27 devnull /* take your time */
53 f1e8706d 2004-12-27 devnull while(_tas(&l->held))
54 f1e8706d 2004-12-27 devnull usleep(1000*1000);
55 f1e8706d 2004-12-27 devnull return 1;
56 f1e8706d 2004-12-27 devnull }
57 f1e8706d 2004-12-27 devnull
58 f1e8706d 2004-12-27 devnull /*
59 f1e8706d 2004-12-27 devnull * sleep and wakeup
60 f1e8706d 2004-12-27 devnull */
61 f1e8706d 2004-12-27 devnull static void
62 f1e8706d 2004-12-27 devnull ign(int x)
63 f1e8706d 2004-12-27 devnull {
64 f1e8706d 2004-12-27 devnull USED(x);
65 f1e8706d 2004-12-27 devnull }
66 f1e8706d 2004-12-27 devnull
67 f1e8706d 2004-12-27 devnull static void /*__attribute__((constructor))*/
68 f1e8706d 2004-12-27 devnull ignusr1(int restart)
69 f1e8706d 2004-12-27 devnull {
70 f1e8706d 2004-12-27 devnull struct sigaction sa;
71 f1e8706d 2004-12-27 devnull
72 f1e8706d 2004-12-27 devnull memset(&sa, 0, sizeof sa);
73 f1e8706d 2004-12-27 devnull sa.sa_handler = ign;
74 f1e8706d 2004-12-27 devnull sigemptyset(&sa.sa_mask);
75 f1e8706d 2004-12-27 devnull sigaddset(&sa.sa_mask, SIGUSR1);
76 f1e8706d 2004-12-27 devnull if(restart)
77 f1e8706d 2004-12-27 devnull sa.sa_flags = SA_RESTART;
78 f1e8706d 2004-12-27 devnull sigaction(SIGUSR1, &sa, nil);
79 f1e8706d 2004-12-27 devnull }
80 f1e8706d 2004-12-27 devnull
81 f1e8706d 2004-12-27 devnull void
82 f1e8706d 2004-12-27 devnull _procsleep(_Procrendez *r)
83 f1e8706d 2004-12-27 devnull {
84 f1e8706d 2004-12-27 devnull sigset_t mask;
85 f1e8706d 2004-12-27 devnull
86 f1e8706d 2004-12-27 devnull /*
87 f1e8706d 2004-12-27 devnull * Go to sleep.
88 f1e8706d 2004-12-27 devnull *
89 f1e8706d 2004-12-27 devnull * Block USR1, set the handler to interrupt system calls,
90 f1e8706d 2004-12-27 devnull * unlock the vouslock so our waker can wake us,
91 f1e8706d 2004-12-27 devnull * and then suspend.
92 f1e8706d 2004-12-27 devnull */
93 955a2ca7 2004-12-27 devnull again:
94 f1e8706d 2004-12-27 devnull r->asleep = 1;
95 f1e8706d 2004-12-27 devnull r->pid = getpid();
96 f1e8706d 2004-12-27 devnull
97 f1e8706d 2004-12-27 devnull sigprocmask(SIG_SETMASK, nil, &mask);
98 f1e8706d 2004-12-27 devnull sigaddset(&mask, SIGUSR1);
99 f1e8706d 2004-12-27 devnull sigprocmask(SIG_SETMASK, &mask, nil);
100 f1e8706d 2004-12-27 devnull ignusr1(0);
101 f1e8706d 2004-12-27 devnull unlock(r->l);
102 f1e8706d 2004-12-27 devnull sigdelset(&mask, SIGUSR1);
103 f1e8706d 2004-12-27 devnull sigsuspend(&mask);
104 f1e8706d 2004-12-27 devnull
105 f1e8706d 2004-12-27 devnull /*
106 f1e8706d 2004-12-27 devnull * We're awake. Make USR1 not interrupt system calls.
107 f1e8706d 2004-12-27 devnull */
108 f1e8706d 2004-12-27 devnull lock(r->l);
109 955a2ca7 2004-12-27 devnull ignusr1(1);
110 955a2ca7 2004-12-27 devnull if(r->asleep && r->pid == getpid()){
111 955a2ca7 2004-12-27 devnull /* Didn't really wake up - signal from something else */
112 955a2ca7 2004-12-27 devnull goto again;
113 955a2ca7 2004-12-27 devnull }
114 f1e8706d 2004-12-27 devnull }
115 f1e8706d 2004-12-27 devnull
116 f1e8706d 2004-12-27 devnull void
117 f1e8706d 2004-12-27 devnull _procwakeup(_Procrendez *r)
118 f1e8706d 2004-12-27 devnull {
119 f1e8706d 2004-12-27 devnull if(r->asleep){
120 f1e8706d 2004-12-27 devnull r->asleep = 0;
121 f1e8706d 2004-12-27 devnull assert(r->pid >= 1);
122 f1e8706d 2004-12-27 devnull kill(r->pid, SIGUSR1);
123 f1e8706d 2004-12-27 devnull }
124 f1e8706d 2004-12-27 devnull }
125 f1e8706d 2004-12-27 devnull
126 f1e8706d 2004-12-27 devnull /*
127 f1e8706d 2004-12-27 devnull * process creation and exit
128 f1e8706d 2004-12-27 devnull */
129 f1e8706d 2004-12-27 devnull typedef struct Stackfree Stackfree;
130 f1e8706d 2004-12-27 devnull struct Stackfree
131 f1e8706d 2004-12-27 devnull {
132 f1e8706d 2004-12-27 devnull Stackfree *next;
133 f1e8706d 2004-12-27 devnull int pid;
134 f1e8706d 2004-12-27 devnull };
135 f1e8706d 2004-12-27 devnull static Lock stacklock;
136 f1e8706d 2004-12-27 devnull static Stackfree *stackfree;
137 f1e8706d 2004-12-27 devnull
138 f1e8706d 2004-12-27 devnull static void
139 f1e8706d 2004-12-27 devnull delayfreestack(uchar *stk)
140 f1e8706d 2004-12-27 devnull {
141 f1e8706d 2004-12-27 devnull Stackfree *sf;
142 f1e8706d 2004-12-27 devnull
143 f1e8706d 2004-12-27 devnull sf = (Stackfree*)stk;
144 f1e8706d 2004-12-27 devnull sf->pid = getpid();
145 f1e8706d 2004-12-27 devnull lock(&stacklock);
146 f1e8706d 2004-12-27 devnull sf->next = stackfree;
147 f1e8706d 2004-12-27 devnull stackfree = sf;
148 f1e8706d 2004-12-27 devnull unlock(&stacklock);
149 f1e8706d 2004-12-27 devnull }
150 f1e8706d 2004-12-27 devnull
151 f1e8706d 2004-12-27 devnull static void
152 f1e8706d 2004-12-27 devnull dofreestacks(void)
153 f1e8706d 2004-12-27 devnull {
154 f1e8706d 2004-12-27 devnull Stackfree *sf, *last, *next;
155 f1e8706d 2004-12-27 devnull
156 f1e8706d 2004-12-27 devnull if(stackfree==nil || !canlock(&stacklock))
157 f1e8706d 2004-12-27 devnull return;
158 f1e8706d 2004-12-27 devnull
159 f1e8706d 2004-12-27 devnull for(last=nil,sf=stackfree; sf; last=sf,sf=next){
160 f1e8706d 2004-12-27 devnull next = sf->next;
161 f1e8706d 2004-12-27 devnull if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
162 f1e8706d 2004-12-27 devnull free(sf);
163 2c87dda8 2004-12-28 devnull if(last)
164 2c87dda8 2004-12-28 devnull last->next = next;
165 2c87dda8 2004-12-28 devnull else
166 2c87dda8 2004-12-28 devnull stackfree = next;
167 f1e8706d 2004-12-27 devnull sf = last;
168 f1e8706d 2004-12-27 devnull }
169 f1e8706d 2004-12-27 devnull }
170 2c87dda8 2004-12-28 devnull unlock(&stacklock);
171 2c87dda8 2004-12-28 devnull }
172 f1e8706d 2004-12-27 devnull
173 f1e8706d 2004-12-27 devnull static int
174 f1e8706d 2004-12-27 devnull startprocfn(void *v)
175 f1e8706d 2004-12-27 devnull {
176 f1e8706d 2004-12-27 devnull void **a;
177 f1e8706d 2004-12-27 devnull uchar *stk;
178 f1e8706d 2004-12-27 devnull void (*fn)(void*);
179 f1e8706d 2004-12-27 devnull Proc *p;
180 f1e8706d 2004-12-27 devnull
181 f1e8706d 2004-12-27 devnull a = (void**)v;
182 f1e8706d 2004-12-27 devnull fn = a[0];
183 f1e8706d 2004-12-27 devnull p = a[1];
184 f1e8706d 2004-12-27 devnull stk = a[2];
185 f1e8706d 2004-12-27 devnull free(a);
186 f1e8706d 2004-12-27 devnull p->osprocid = getpid();
187 f1e8706d 2004-12-27 devnull
188 f1e8706d 2004-12-27 devnull (*fn)(p);
189 f1e8706d 2004-12-27 devnull
190 f1e8706d 2004-12-27 devnull delayfreestack(stk);
191 f1e8706d 2004-12-27 devnull _exit(0);
192 f1e8706d 2004-12-27 devnull return 0;
193 f1e8706d 2004-12-27 devnull }
194 f1e8706d 2004-12-27 devnull
195 f1e8706d 2004-12-27 devnull /*
196 f1e8706d 2004-12-27 devnull * indirect through here so that parent need not wait for child zombie
197 f1e8706d 2004-12-27 devnull *
198 f1e8706d 2004-12-27 devnull * slight race - if child exits and then another process starts before we
199 f1e8706d 2004-12-27 devnull * manage to exit, we'll be running on a freed stack.
200 f1e8706d 2004-12-27 devnull */
201 f1e8706d 2004-12-27 devnull static int
202 f1e8706d 2004-12-27 devnull trampnowait(void *v)
203 f1e8706d 2004-12-27 devnull {
204 f1e8706d 2004-12-27 devnull void **a;
205 f1e8706d 2004-12-27 devnull
206 f1e8706d 2004-12-27 devnull a = (void*)v;
207 f1e8706d 2004-12-27 devnull *(int*)a[3] = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
208 f1e8706d 2004-12-27 devnull _exit(0);
209 f1e8706d 2004-12-27 devnull return 0;
210 f1e8706d 2004-12-27 devnull }
211 f1e8706d 2004-12-27 devnull
212 f1e8706d 2004-12-27 devnull void
213 f1e8706d 2004-12-27 devnull _procstart(Proc *p, void (*fn)(Proc*))
214 f1e8706d 2004-12-27 devnull {
215 f1e8706d 2004-12-27 devnull void **a;
216 f1e8706d 2004-12-27 devnull uchar *stk;
217 f1e8706d 2004-12-27 devnull int pid, kidpid, status;
218 f1e8706d 2004-12-27 devnull
219 f1e8706d 2004-12-27 devnull dofreestacks();
220 f1e8706d 2004-12-27 devnull a = malloc(4*sizeof a[0]);
221 f1e8706d 2004-12-27 devnull if(a == nil)
222 f1e8706d 2004-12-27 devnull sysfatal("_procstart malloc: %r");
223 f1e8706d 2004-12-27 devnull stk = malloc(65536);
224 f1e8706d 2004-12-27 devnull if(stk == nil)
225 f1e8706d 2004-12-27 devnull sysfatal("_procstart malloc stack: %r");
226 f1e8706d 2004-12-27 devnull
227 f1e8706d 2004-12-27 devnull a[0] = fn;
228 f1e8706d 2004-12-27 devnull a[1] = p;
229 f1e8706d 2004-12-27 devnull a[2] = stk;
230 f1e8706d 2004-12-27 devnull a[3] = &kidpid;
231 f1e8706d 2004-12-27 devnull kidpid = -1;
232 f1e8706d 2004-12-27 devnull
233 f1e8706d 2004-12-27 devnull pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
234 f1e8706d 2004-12-27 devnull if(pid > 0)
235 f1e8706d 2004-12-27 devnull if(wait4(pid, &status, __WALL, 0) < 0)
236 f1e8706d 2004-12-27 devnull fprint(2, "ffork wait4: %r\n");
237 f1e8706d 2004-12-27 devnull if(pid < 0 || kidpid < 0){
238 f1e8706d 2004-12-27 devnull fprint(2, "_procstart clone: %r\n");
239 f1e8706d 2004-12-27 devnull abort();
240 f1e8706d 2004-12-27 devnull }
241 f1e8706d 2004-12-27 devnull }
242 f1e8706d 2004-12-27 devnull
243 f1e8706d 2004-12-27 devnull static char *threadexitsmsg;
244 f1e8706d 2004-12-27 devnull void
245 f1e8706d 2004-12-27 devnull sigusr2handler(int s)
246 f1e8706d 2004-12-27 devnull {
247 2c87dda8 2004-12-28 devnull /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
248 f1e8706d 2004-12-27 devnull if(threadexitsmsg)
249 f1e8706d 2004-12-27 devnull _exits(threadexitsmsg);
250 f1e8706d 2004-12-27 devnull }
251 f1e8706d 2004-12-27 devnull
252 f1e8706d 2004-12-27 devnull void
253 f1e8706d 2004-12-27 devnull threadexitsall(char *msg)
254 f1e8706d 2004-12-27 devnull {
255 f1e8706d 2004-12-27 devnull static int pid[1024];
256 f1e8706d 2004-12-27 devnull int i, npid, mypid;
257 f1e8706d 2004-12-27 devnull Proc *p;
258 f1e8706d 2004-12-27 devnull
259 f1e8706d 2004-12-27 devnull if(msg == nil)
260 f1e8706d 2004-12-27 devnull msg = "";
261 f1e8706d 2004-12-27 devnull mypid = getpid();
262 f1e8706d 2004-12-27 devnull lock(&_threadprocslock);
263 f1e8706d 2004-12-27 devnull threadexitsmsg = msg;
264 f1e8706d 2004-12-27 devnull npid = 0;
265 f1e8706d 2004-12-27 devnull for(p=_threadprocs; p; p=p->next)
266 f1e8706d 2004-12-27 devnull if(p->osprocid != mypid && p->osprocid >= 1)
267 f1e8706d 2004-12-27 devnull pid[npid++] = p->osprocid;
268 f1e8706d 2004-12-27 devnull for(i=0; i<npid; i++)
269 f1e8706d 2004-12-27 devnull kill(pid[i], SIGUSR2);
270 f1e8706d 2004-12-27 devnull unlock(&_threadprocslock);
271 f1e8706d 2004-12-27 devnull exits(msg);
272 f1e8706d 2004-12-27 devnull }
273 f1e8706d 2004-12-27 devnull
274 f1e8706d 2004-12-27 devnull /*
275 f1e8706d 2004-12-27 devnull * per-process data, indexed by pid
276 f1e8706d 2004-12-27 devnull *
277 f1e8706d 2004-12-27 devnull * could use modify_ldt and a segment register
278 f1e8706d 2004-12-27 devnull * to avoid the many calls to getpid(), but i don't
279 f1e8706d 2004-12-27 devnull * care -- this is compatibility code. linux 2.6 with
280 f1e8706d 2004-12-27 devnull * nptl is a good enough pthreads to avoid this whole file.
281 f1e8706d 2004-12-27 devnull */
282 f1e8706d 2004-12-27 devnull typedef struct Perproc Perproc;
283 f1e8706d 2004-12-27 devnull struct Perproc
284 f1e8706d 2004-12-27 devnull {
285 f1e8706d 2004-12-27 devnull int pid;
286 f1e8706d 2004-12-27 devnull Proc *proc;
287 f1e8706d 2004-12-27 devnull };
288 f1e8706d 2004-12-27 devnull
289 f1e8706d 2004-12-27 devnull static Lock perlock;
290 f1e8706d 2004-12-27 devnull static Perproc perproc[1024];
291 f1e8706d 2004-12-27 devnull #define P ((Proc*)-1)
292 f1e8706d 2004-12-27 devnull
293 f1e8706d 2004-12-27 devnull static Perproc*
294 f1e8706d 2004-12-27 devnull myperproc(void)
295 f1e8706d 2004-12-27 devnull {
296 f1e8706d 2004-12-27 devnull int i, pid, h;
297 f1e8706d 2004-12-27 devnull Perproc *p;
298 f1e8706d 2004-12-27 devnull
299 f1e8706d 2004-12-27 devnull pid = getpid();
300 f1e8706d 2004-12-27 devnull h = pid%nelem(perproc);
301 f1e8706d 2004-12-27 devnull for(i=0; i<nelem(perproc); i++){
302 f1e8706d 2004-12-27 devnull p = &perproc[(i+h)%nelem(perproc)];
303 f1e8706d 2004-12-27 devnull if(p->pid == pid)
304 f1e8706d 2004-12-27 devnull return p;
305 f1e8706d 2004-12-27 devnull if(p->pid == 0){
306 f1e8706d 2004-12-27 devnull print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
307 f1e8706d 2004-12-27 devnull break;
308 f1e8706d 2004-12-27 devnull }
309 f1e8706d 2004-12-27 devnull }
310 f1e8706d 2004-12-27 devnull fprint(2, "myperproc %d: cannot find self\n", pid);
311 f1e8706d 2004-12-27 devnull abort();
312 f1e8706d 2004-12-27 devnull return nil;
313 f1e8706d 2004-12-27 devnull }
314 f1e8706d 2004-12-27 devnull
315 f1e8706d 2004-12-27 devnull static Perproc*
316 f1e8706d 2004-12-27 devnull newperproc(void)
317 f1e8706d 2004-12-27 devnull {
318 f1e8706d 2004-12-27 devnull int i, pid, h;
319 f1e8706d 2004-12-27 devnull Perproc *p;
320 f1e8706d 2004-12-27 devnull
321 f1e8706d 2004-12-27 devnull lock(&perlock);
322 f1e8706d 2004-12-27 devnull pid = getpid();
323 f1e8706d 2004-12-27 devnull h = pid%nelem(perproc);
324 f1e8706d 2004-12-27 devnull for(i=0; i<nelem(perproc); i++){
325 f1e8706d 2004-12-27 devnull p = &perproc[(i+h)%nelem(perproc)];
326 f1e8706d 2004-12-27 devnull if(p->pid == pid || p->pid == -1 || p->pid == 0){
327 f1e8706d 2004-12-27 devnull p->pid = pid;
328 f1e8706d 2004-12-27 devnull unlock(&perlock);
329 f1e8706d 2004-12-27 devnull return p;
330 f1e8706d 2004-12-27 devnull }
331 f1e8706d 2004-12-27 devnull }
332 f1e8706d 2004-12-27 devnull fprint(2, "newperproc %d: out of procs\n", pid);
333 f1e8706d 2004-12-27 devnull abort();
334 f1e8706d 2004-12-27 devnull return nil;
335 f1e8706d 2004-12-27 devnull }
336 f1e8706d 2004-12-27 devnull
337 f1e8706d 2004-12-27 devnull Proc*
338 f1e8706d 2004-12-27 devnull _threadproc(void)
339 f1e8706d 2004-12-27 devnull {
340 f1e8706d 2004-12-27 devnull return myperproc()->proc;
341 f1e8706d 2004-12-27 devnull }
342 f1e8706d 2004-12-27 devnull
343 f1e8706d 2004-12-27 devnull void
344 f1e8706d 2004-12-27 devnull _threadsetproc(Proc *p)
345 f1e8706d 2004-12-27 devnull {
346 f1e8706d 2004-12-27 devnull Perproc *pp;
347 f1e8706d 2004-12-27 devnull
348 2c87dda8 2004-12-28 devnull if(p)
349 2c87dda8 2004-12-28 devnull p->osprocid = getpid();
350 f1e8706d 2004-12-27 devnull pp = newperproc();
351 f1e8706d 2004-12-27 devnull pp->proc = p;
352 f1e8706d 2004-12-27 devnull if(p == nil)
353 f1e8706d 2004-12-27 devnull pp->pid = -1;
354 f1e8706d 2004-12-27 devnull }
355 f1e8706d 2004-12-27 devnull
356 f1e8706d 2004-12-27 devnull void
357 f1e8706d 2004-12-27 devnull _pthreadinit(void)
358 f1e8706d 2004-12-27 devnull {
359 f1e8706d 2004-12-27 devnull signal(SIGUSR2, sigusr2handler);
360 f1e8706d 2004-12-27 devnull }
361 f1e8706d 2004-12-27 devnull