Blame


1 8d82ccef 2020-01-20 rsc #include "threadimpl.h"
2 8d82ccef 2020-01-20 rsc
3 8d82ccef 2020-01-20 rsc #undef exits
4 8d82ccef 2020-01-20 rsc #undef _exits
5 8d82ccef 2020-01-20 rsc
6 8d82ccef 2020-01-20 rsc static int
7 8d82ccef 2020-01-20 rsc timefmt(Fmt *fmt)
8 8d82ccef 2020-01-20 rsc {
9 8d82ccef 2020-01-20 rsc static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
10 8d82ccef 2020-01-20 rsc "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
11 8d82ccef 2020-01-20 rsc vlong ns;
12 8d82ccef 2020-01-20 rsc Tm tm;
13 8d82ccef 2020-01-20 rsc ns = nsec();
14 8d82ccef 2020-01-20 rsc tm = *localtime(time(0));
15 8d82ccef 2020-01-20 rsc return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d",
16 8d82ccef 2020-01-20 rsc mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec,
17 8d82ccef 2020-01-20 rsc (int)(ns%1000000000)/1000000);
18 8d82ccef 2020-01-20 rsc }
19 8d82ccef 2020-01-20 rsc
20 8d82ccef 2020-01-20 rsc /*
21 8d82ccef 2020-01-20 rsc * spin locks
22 8d82ccef 2020-01-20 rsc */
23 8d82ccef 2020-01-20 rsc extern int _tas(int*);
24 8d82ccef 2020-01-20 rsc
25 8d82ccef 2020-01-20 rsc void
26 8d82ccef 2020-01-20 rsc _threadunlock(Lock *l, ulong pc)
27 8d82ccef 2020-01-20 rsc {
28 8d82ccef 2020-01-20 rsc USED(pc);
29 8d82ccef 2020-01-20 rsc
30 8d82ccef 2020-01-20 rsc l->held = 0;
31 8d82ccef 2020-01-20 rsc }
32 8d82ccef 2020-01-20 rsc
33 8d82ccef 2020-01-20 rsc int
34 8d82ccef 2020-01-20 rsc _threadlock(Lock *l, int block, ulong pc)
35 8d82ccef 2020-01-20 rsc {
36 8d82ccef 2020-01-20 rsc int i;
37 8d82ccef 2020-01-20 rsc static int first=1;
38 8d82ccef 2020-01-20 rsc if(first) {first=0; fmtinstall('\001', timefmt);}
39 8d82ccef 2020-01-20 rsc
40 8d82ccef 2020-01-20 rsc USED(pc);
41 8d82ccef 2020-01-20 rsc
42 8d82ccef 2020-01-20 rsc /* once fast */
43 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
44 8d82ccef 2020-01-20 rsc return 1;
45 8d82ccef 2020-01-20 rsc if(!block)
46 8d82ccef 2020-01-20 rsc return 0;
47 8d82ccef 2020-01-20 rsc
48 8d82ccef 2020-01-20 rsc /* a thousand times pretty fast */
49 8d82ccef 2020-01-20 rsc for(i=0; i<1000; i++){
50 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
51 8d82ccef 2020-01-20 rsc return 1;
52 8d82ccef 2020-01-20 rsc sched_yield();
53 8d82ccef 2020-01-20 rsc }
54 8d82ccef 2020-01-20 rsc /* now increasingly slow */
55 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
56 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
57 8d82ccef 2020-01-20 rsc return 1;
58 8d82ccef 2020-01-20 rsc usleep(1);
59 8d82ccef 2020-01-20 rsc }
60 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc);
61 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
62 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
63 8d82ccef 2020-01-20 rsc return 1;
64 8d82ccef 2020-01-20 rsc usleep(10);
65 8d82ccef 2020-01-20 rsc }
66 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc);
67 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
68 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
69 8d82ccef 2020-01-20 rsc return 1;
70 8d82ccef 2020-01-20 rsc usleep(100);
71 8d82ccef 2020-01-20 rsc }
72 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc);
73 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
74 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
75 8d82ccef 2020-01-20 rsc return 1;
76 8d82ccef 2020-01-20 rsc usleep(1000);
77 8d82ccef 2020-01-20 rsc }
78 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc);
79 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
80 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
81 8d82ccef 2020-01-20 rsc return 1;
82 8d82ccef 2020-01-20 rsc usleep(10*1000);
83 8d82ccef 2020-01-20 rsc }
84 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc);
85 8d82ccef 2020-01-20 rsc for(i=0; i<1000; i++){
86 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
87 8d82ccef 2020-01-20 rsc return 1;
88 8d82ccef 2020-01-20 rsc usleep(100*1000);
89 8d82ccef 2020-01-20 rsc }
90 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc);
91 8d82ccef 2020-01-20 rsc /* take your time */
92 8d82ccef 2020-01-20 rsc while(_tas(&l->held))
93 8d82ccef 2020-01-20 rsc usleep(1000*1000);
94 8d82ccef 2020-01-20 rsc return 1;
95 8d82ccef 2020-01-20 rsc }
96 8d82ccef 2020-01-20 rsc
97 8d82ccef 2020-01-20 rsc /*
98 8d82ccef 2020-01-20 rsc * sleep and wakeup
99 8d82ccef 2020-01-20 rsc */
100 8d82ccef 2020-01-20 rsc static void
101 8d82ccef 2020-01-20 rsc ign(int x)
102 8d82ccef 2020-01-20 rsc {
103 8d82ccef 2020-01-20 rsc USED(x);
104 8d82ccef 2020-01-20 rsc }
105 8d82ccef 2020-01-20 rsc
106 8d82ccef 2020-01-20 rsc static void /*__attribute__((constructor))*/
107 8d82ccef 2020-01-20 rsc ignusr1(int restart)
108 8d82ccef 2020-01-20 rsc {
109 8d82ccef 2020-01-20 rsc struct sigaction sa;
110 8d82ccef 2020-01-20 rsc
111 8d82ccef 2020-01-20 rsc memset(&sa, 0, sizeof sa);
112 8d82ccef 2020-01-20 rsc sa.sa_handler = ign;
113 8d82ccef 2020-01-20 rsc sigemptyset(&sa.sa_mask);
114 8d82ccef 2020-01-20 rsc sigaddset(&sa.sa_mask, SIGUSR1);
115 8d82ccef 2020-01-20 rsc if(restart)
116 8d82ccef 2020-01-20 rsc sa.sa_flags = SA_RESTART;
117 8d82ccef 2020-01-20 rsc sigaction(SIGUSR1, &sa, nil);
118 8d82ccef 2020-01-20 rsc }
119 8d82ccef 2020-01-20 rsc
120 8d82ccef 2020-01-20 rsc void
121 8d82ccef 2020-01-20 rsc _procsleep(_Procrendez *r)
122 8d82ccef 2020-01-20 rsc {
123 8d82ccef 2020-01-20 rsc sigset_t mask;
124 8d82ccef 2020-01-20 rsc
125 8d82ccef 2020-01-20 rsc /*
126 8d82ccef 2020-01-20 rsc * Go to sleep.
127 8d82ccef 2020-01-20 rsc *
128 8d82ccef 2020-01-20 rsc * Block USR1, set the handler to interrupt system calls,
129 8d82ccef 2020-01-20 rsc * unlock the vouslock so our waker can wake us,
130 8d82ccef 2020-01-20 rsc * and then suspend.
131 8d82ccef 2020-01-20 rsc */
132 8d82ccef 2020-01-20 rsc again:
133 8d82ccef 2020-01-20 rsc r->asleep = 1;
134 8d82ccef 2020-01-20 rsc r->pid = getpid();
135 8d82ccef 2020-01-20 rsc
136 8d82ccef 2020-01-20 rsc sigprocmask(SIG_SETMASK, nil, &mask);
137 8d82ccef 2020-01-20 rsc sigaddset(&mask, SIGUSR1);
138 8d82ccef 2020-01-20 rsc sigprocmask(SIG_SETMASK, &mask, nil);
139 8d82ccef 2020-01-20 rsc ignusr1(0);
140 8d82ccef 2020-01-20 rsc unlock(r->l);
141 8d82ccef 2020-01-20 rsc sigdelset(&mask, SIGUSR1);
142 8d82ccef 2020-01-20 rsc sigsuspend(&mask);
143 8d82ccef 2020-01-20 rsc
144 8d82ccef 2020-01-20 rsc /*
145 8d82ccef 2020-01-20 rsc * We're awake. Make USR1 not interrupt system calls.
146 8d82ccef 2020-01-20 rsc */
147 8d82ccef 2020-01-20 rsc lock(r->l);
148 8d82ccef 2020-01-20 rsc ignusr1(1);
149 8d82ccef 2020-01-20 rsc if(r->asleep && r->pid == getpid()){
150 8d82ccef 2020-01-20 rsc /* Didn't really wake up - signal from something else */
151 8d82ccef 2020-01-20 rsc goto again;
152 8d82ccef 2020-01-20 rsc }
153 8d82ccef 2020-01-20 rsc }
154 8d82ccef 2020-01-20 rsc
155 8d82ccef 2020-01-20 rsc void
156 8d82ccef 2020-01-20 rsc _procwakeupandunlock(_Procrendez *r)
157 8d82ccef 2020-01-20 rsc {
158 8d82ccef 2020-01-20 rsc int pid;
159 8d82ccef 2020-01-20 rsc
160 8d82ccef 2020-01-20 rsc pid = 0;
161 8d82ccef 2020-01-20 rsc if(r->asleep){
162 8d82ccef 2020-01-20 rsc r->asleep = 0;
163 8d82ccef 2020-01-20 rsc assert(r->pid >= 1);
164 8d82ccef 2020-01-20 rsc pid = r->pid;
165 8d82ccef 2020-01-20 rsc }
166 8d82ccef 2020-01-20 rsc assert(r->l);
167 8d82ccef 2020-01-20 rsc unlock(r->l);
168 8d82ccef 2020-01-20 rsc if(pid)
169 8d82ccef 2020-01-20 rsc kill(pid, SIGUSR1);
170 8d82ccef 2020-01-20 rsc }
171 8d82ccef 2020-01-20 rsc
172 8d82ccef 2020-01-20 rsc /*
173 8d82ccef 2020-01-20 rsc * process creation and exit
174 8d82ccef 2020-01-20 rsc */
175 8d82ccef 2020-01-20 rsc typedef struct Stackfree Stackfree;
176 8d82ccef 2020-01-20 rsc struct Stackfree
177 8d82ccef 2020-01-20 rsc {
178 8d82ccef 2020-01-20 rsc Stackfree *next;
179 8d82ccef 2020-01-20 rsc int pid;
180 8d82ccef 2020-01-20 rsc int pid1;
181 8d82ccef 2020-01-20 rsc };
182 8d82ccef 2020-01-20 rsc static Lock stacklock;
183 8d82ccef 2020-01-20 rsc static Stackfree *stackfree;
184 8d82ccef 2020-01-20 rsc
185 8d82ccef 2020-01-20 rsc static void
186 8d82ccef 2020-01-20 rsc delayfreestack(uchar *stk, int pid, int pid1)
187 8d82ccef 2020-01-20 rsc {
188 8d82ccef 2020-01-20 rsc Stackfree *sf;
189 8d82ccef 2020-01-20 rsc
190 8d82ccef 2020-01-20 rsc sf = (Stackfree*)stk;
191 8d82ccef 2020-01-20 rsc sf->pid = pid;
192 8d82ccef 2020-01-20 rsc sf->pid1 = pid1;
193 8d82ccef 2020-01-20 rsc lock(&stacklock);
194 8d82ccef 2020-01-20 rsc sf->next = stackfree;
195 8d82ccef 2020-01-20 rsc stackfree = sf;
196 8d82ccef 2020-01-20 rsc unlock(&stacklock);
197 8d82ccef 2020-01-20 rsc }
198 8d82ccef 2020-01-20 rsc
199 8d82ccef 2020-01-20 rsc static void
200 8d82ccef 2020-01-20 rsc dofreestacks(void)
201 8d82ccef 2020-01-20 rsc {
202 8d82ccef 2020-01-20 rsc Stackfree *sf, *last, *next;
203 8d82ccef 2020-01-20 rsc
204 8d82ccef 2020-01-20 rsc if(stackfree==nil || !canlock(&stacklock))
205 8d82ccef 2020-01-20 rsc return;
206 8d82ccef 2020-01-20 rsc
207 8d82ccef 2020-01-20 rsc for(last=nil,sf=stackfree; sf; last=sf,sf=next){
208 8d82ccef 2020-01-20 rsc next = sf->next;
209 8d82ccef 2020-01-20 rsc if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH)
210 8d82ccef 2020-01-20 rsc if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){
211 8d82ccef 2020-01-20 rsc free(sf);
212 8d82ccef 2020-01-20 rsc if(last)
213 8d82ccef 2020-01-20 rsc last->next = next;
214 8d82ccef 2020-01-20 rsc else
215 8d82ccef 2020-01-20 rsc stackfree = next;
216 8d82ccef 2020-01-20 rsc sf = last;
217 8d82ccef 2020-01-20 rsc }
218 8d82ccef 2020-01-20 rsc }
219 8d82ccef 2020-01-20 rsc unlock(&stacklock);
220 8d82ccef 2020-01-20 rsc }
221 8d82ccef 2020-01-20 rsc
222 8d82ccef 2020-01-20 rsc static int
223 8d82ccef 2020-01-20 rsc startprocfn(void *v)
224 8d82ccef 2020-01-20 rsc {
225 8d82ccef 2020-01-20 rsc void **a;
226 8d82ccef 2020-01-20 rsc uchar *stk;
227 8d82ccef 2020-01-20 rsc void (*fn)(void*);
228 8d82ccef 2020-01-20 rsc Proc *p;
229 8d82ccef 2020-01-20 rsc int pid0, pid1;
230 8d82ccef 2020-01-20 rsc
231 8d82ccef 2020-01-20 rsc a = (void**)v;
232 8d82ccef 2020-01-20 rsc fn = a[0];
233 8d82ccef 2020-01-20 rsc p = a[1];
234 8d82ccef 2020-01-20 rsc stk = a[2];
235 8d82ccef 2020-01-20 rsc pid0 = (int)a[4];
236 8d82ccef 2020-01-20 rsc pid1 = getpid();
237 8d82ccef 2020-01-20 rsc free(a);
238 8d82ccef 2020-01-20 rsc p->osprocid = pid1;
239 8d82ccef 2020-01-20 rsc
240 8d82ccef 2020-01-20 rsc (*fn)(p);
241 8d82ccef 2020-01-20 rsc
242 8d82ccef 2020-01-20 rsc delayfreestack(stk, pid0, pid1);
243 8d82ccef 2020-01-20 rsc _exit(0);
244 8d82ccef 2020-01-20 rsc return 0;
245 8d82ccef 2020-01-20 rsc }
246 8d82ccef 2020-01-20 rsc
247 8d82ccef 2020-01-20 rsc /*
248 8d82ccef 2020-01-20 rsc * indirect through here so that parent need not wait for child zombie
249 8d82ccef 2020-01-20 rsc *
250 8d82ccef 2020-01-20 rsc * slight race - if child exits and then another process starts before we
251 8d82ccef 2020-01-20 rsc * manage to exit, we'll be running on a freed stack.
252 8d82ccef 2020-01-20 rsc */
253 8d82ccef 2020-01-20 rsc static int
254 8d82ccef 2020-01-20 rsc trampnowait(void *v)
255 8d82ccef 2020-01-20 rsc {
256 8d82ccef 2020-01-20 rsc void **a;
257 8d82ccef 2020-01-20 rsc int *kidpid;
258 8d82ccef 2020-01-20 rsc
259 8d82ccef 2020-01-20 rsc a = (void*)v;
260 8d82ccef 2020-01-20 rsc kidpid = a[3];
261 8d82ccef 2020-01-20 rsc a[4] = (void*)getpid();
262 8d82ccef 2020-01-20 rsc *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
263 8d82ccef 2020-01-20 rsc _exit(0);
264 8d82ccef 2020-01-20 rsc return 0;
265 8d82ccef 2020-01-20 rsc }
266 8d82ccef 2020-01-20 rsc
267 8d82ccef 2020-01-20 rsc void
268 8d82ccef 2020-01-20 rsc _procstart(Proc *p, void (*fn)(Proc*))
269 8d82ccef 2020-01-20 rsc {
270 8d82ccef 2020-01-20 rsc void **a;
271 8d82ccef 2020-01-20 rsc uchar *stk;
272 8d82ccef 2020-01-20 rsc int pid, kidpid, status;
273 8d82ccef 2020-01-20 rsc
274 8d82ccef 2020-01-20 rsc dofreestacks();
275 8d82ccef 2020-01-20 rsc a = malloc(5*sizeof a[0]);
276 8d82ccef 2020-01-20 rsc if(a == nil)
277 8d82ccef 2020-01-20 rsc sysfatal("_procstart malloc: %r");
278 8d82ccef 2020-01-20 rsc stk = malloc(65536);
279 8d82ccef 2020-01-20 rsc if(stk == nil)
280 8d82ccef 2020-01-20 rsc sysfatal("_procstart malloc stack: %r");
281 8d82ccef 2020-01-20 rsc
282 8d82ccef 2020-01-20 rsc a[0] = fn;
283 8d82ccef 2020-01-20 rsc a[1] = p;
284 8d82ccef 2020-01-20 rsc a[2] = stk;
285 8d82ccef 2020-01-20 rsc a[3] = &kidpid;
286 8d82ccef 2020-01-20 rsc kidpid = -1;
287 8d82ccef 2020-01-20 rsc
288 8d82ccef 2020-01-20 rsc pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
289 8d82ccef 2020-01-20 rsc if(pid > 0)
290 8d82ccef 2020-01-20 rsc if(wait4(pid, &status, __WALL, 0) < 0)
291 8d82ccef 2020-01-20 rsc fprint(2, "ffork wait4: %r\n");
292 8d82ccef 2020-01-20 rsc if(pid < 0 || kidpid < 0){
293 8d82ccef 2020-01-20 rsc fprint(2, "_procstart clone: %r\n");
294 8d82ccef 2020-01-20 rsc abort();
295 8d82ccef 2020-01-20 rsc }
296 8d82ccef 2020-01-20 rsc }
297 8d82ccef 2020-01-20 rsc
298 8d82ccef 2020-01-20 rsc static char *threadexitsmsg;
299 8d82ccef 2020-01-20 rsc void
300 8d82ccef 2020-01-20 rsc sigusr2handler(int s)
301 8d82ccef 2020-01-20 rsc {
302 8d82ccef 2020-01-20 rsc /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
303 8d82ccef 2020-01-20 rsc if(threadexitsmsg)
304 8d82ccef 2020-01-20 rsc _exits(threadexitsmsg);
305 8d82ccef 2020-01-20 rsc }
306 8d82ccef 2020-01-20 rsc
307 8d82ccef 2020-01-20 rsc void
308 8d82ccef 2020-01-20 rsc threadexitsall(char *msg)
309 8d82ccef 2020-01-20 rsc {
310 8d82ccef 2020-01-20 rsc static int pid[1024];
311 8d82ccef 2020-01-20 rsc int i, npid, mypid;
312 8d82ccef 2020-01-20 rsc Proc *p;
313 8d82ccef 2020-01-20 rsc
314 8d82ccef 2020-01-20 rsc if(msg == nil)
315 8d82ccef 2020-01-20 rsc msg = "";
316 8d82ccef 2020-01-20 rsc
317 8d82ccef 2020-01-20 rsc /*
318 8d82ccef 2020-01-20 rsc * Only one guy, ever, gets to run this.
319 8d82ccef 2020-01-20 rsc * If two guys do it, inevitably they end up
320 8d82ccef 2020-01-20 rsc * tripping over each other in the underlying
321 8d82ccef 2020-01-20 rsc * C library exit() implementation, which is
322 8d82ccef 2020-01-20 rsc * trying to run the atexit handlers and apparently
323 8d82ccef 2020-01-20 rsc * not thread safe. This has been observed on
324 8d82ccef 2020-01-20 rsc * both Linux and OpenBSD. Sigh.
325 8d82ccef 2020-01-20 rsc */
326 8d82ccef 2020-01-20 rsc {
327 8d82ccef 2020-01-20 rsc static Lock onelock;
328 8d82ccef 2020-01-20 rsc if(!canlock(&onelock))
329 8d82ccef 2020-01-20 rsc _exits(threadexitsmsg);
330 8d82ccef 2020-01-20 rsc threadexitsmsg = msg;
331 8d82ccef 2020-01-20 rsc }
332 8d82ccef 2020-01-20 rsc
333 8d82ccef 2020-01-20 rsc mypid = getpid();
334 8d82ccef 2020-01-20 rsc lock(&_threadprocslock);
335 8d82ccef 2020-01-20 rsc npid = 0;
336 8d82ccef 2020-01-20 rsc for(p=_threadprocs; p; p=p->next)
337 8d82ccef 2020-01-20 rsc if(p->osprocid != mypid && p->osprocid >= 1)
338 8d82ccef 2020-01-20 rsc pid[npid++] = p->osprocid;
339 8d82ccef 2020-01-20 rsc for(i=0; i<npid; i++)
340 8d82ccef 2020-01-20 rsc kill(pid[i], SIGUSR2);
341 8d82ccef 2020-01-20 rsc unlock(&_threadprocslock);
342 8d82ccef 2020-01-20 rsc exits(msg);
343 8d82ccef 2020-01-20 rsc }
344 8d82ccef 2020-01-20 rsc
345 8d82ccef 2020-01-20 rsc /*
346 8d82ccef 2020-01-20 rsc * per-process data, indexed by pid
347 8d82ccef 2020-01-20 rsc *
348 8d82ccef 2020-01-20 rsc * could use modify_ldt and a segment register
349 8d82ccef 2020-01-20 rsc * to avoid the many calls to getpid(), but i don't
350 8d82ccef 2020-01-20 rsc * care -- this is compatibility code. linux 2.6 with
351 8d82ccef 2020-01-20 rsc * nptl is a good enough pthreads to avoid this whole file.
352 8d82ccef 2020-01-20 rsc */
353 8d82ccef 2020-01-20 rsc typedef struct Perproc Perproc;
354 8d82ccef 2020-01-20 rsc struct Perproc
355 8d82ccef 2020-01-20 rsc {
356 8d82ccef 2020-01-20 rsc int pid;
357 8d82ccef 2020-01-20 rsc Proc *proc;
358 8d82ccef 2020-01-20 rsc };
359 8d82ccef 2020-01-20 rsc
360 8d82ccef 2020-01-20 rsc static Lock perlock;
361 8d82ccef 2020-01-20 rsc static Perproc perproc[1024];
362 8d82ccef 2020-01-20 rsc #define P ((Proc*)-1)
363 8d82ccef 2020-01-20 rsc
364 8d82ccef 2020-01-20 rsc static Perproc*
365 8d82ccef 2020-01-20 rsc myperproc(void)
366 8d82ccef 2020-01-20 rsc {
367 8d82ccef 2020-01-20 rsc int i, pid, h;
368 8d82ccef 2020-01-20 rsc Perproc *p;
369 8d82ccef 2020-01-20 rsc
370 8d82ccef 2020-01-20 rsc pid = getpid();
371 8d82ccef 2020-01-20 rsc h = pid%nelem(perproc);
372 8d82ccef 2020-01-20 rsc for(i=0; i<nelem(perproc); i++){
373 8d82ccef 2020-01-20 rsc p = &perproc[(i+h)%nelem(perproc)];
374 8d82ccef 2020-01-20 rsc if(p->pid == pid)
375 8d82ccef 2020-01-20 rsc return p;
376 8d82ccef 2020-01-20 rsc if(p->pid == 0){
377 8d82ccef 2020-01-20 rsc print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
378 8d82ccef 2020-01-20 rsc break;
379 8d82ccef 2020-01-20 rsc }
380 8d82ccef 2020-01-20 rsc }
381 8d82ccef 2020-01-20 rsc fprint(2, "myperproc %d (%s): cannot find self\n", pid, argv0);
382 8d82ccef 2020-01-20 rsc abort();
383 8d82ccef 2020-01-20 rsc return nil;
384 8d82ccef 2020-01-20 rsc }
385 8d82ccef 2020-01-20 rsc
386 8d82ccef 2020-01-20 rsc static Perproc*
387 8d82ccef 2020-01-20 rsc newperproc(void)
388 8d82ccef 2020-01-20 rsc {
389 8d82ccef 2020-01-20 rsc int i, pid, h;
390 8d82ccef 2020-01-20 rsc Perproc *p;
391 8d82ccef 2020-01-20 rsc
392 8d82ccef 2020-01-20 rsc lock(&perlock);
393 8d82ccef 2020-01-20 rsc pid = getpid();
394 8d82ccef 2020-01-20 rsc h = pid%nelem(perproc);
395 8d82ccef 2020-01-20 rsc for(i=0; i<nelem(perproc); i++){
396 8d82ccef 2020-01-20 rsc p = &perproc[(i+h)%nelem(perproc)];
397 8d82ccef 2020-01-20 rsc if(p->pid == pid || p->pid == -1 || p->pid == 0){
398 8d82ccef 2020-01-20 rsc p->pid = pid;
399 8d82ccef 2020-01-20 rsc unlock(&perlock);
400 8d82ccef 2020-01-20 rsc return p;
401 8d82ccef 2020-01-20 rsc }
402 8d82ccef 2020-01-20 rsc }
403 8d82ccef 2020-01-20 rsc fprint(2, "newperproc %d: out of procs\n", pid);
404 8d82ccef 2020-01-20 rsc abort();
405 8d82ccef 2020-01-20 rsc return nil;
406 8d82ccef 2020-01-20 rsc }
407 8d82ccef 2020-01-20 rsc
408 8d82ccef 2020-01-20 rsc Proc*
409 8d82ccef 2020-01-20 rsc _threadproc(void)
410 8d82ccef 2020-01-20 rsc {
411 8d82ccef 2020-01-20 rsc return myperproc()->proc;
412 8d82ccef 2020-01-20 rsc }
413 8d82ccef 2020-01-20 rsc
414 8d82ccef 2020-01-20 rsc void
415 8d82ccef 2020-01-20 rsc _threadsetproc(Proc *p)
416 8d82ccef 2020-01-20 rsc {
417 8d82ccef 2020-01-20 rsc Perproc *pp;
418 8d82ccef 2020-01-20 rsc
419 8d82ccef 2020-01-20 rsc if(p)
420 8d82ccef 2020-01-20 rsc p->osprocid = getpid();
421 8d82ccef 2020-01-20 rsc pp = newperproc();
422 8d82ccef 2020-01-20 rsc pp->proc = p;
423 8d82ccef 2020-01-20 rsc if(p == nil)
424 8d82ccef 2020-01-20 rsc pp->pid = -1;
425 8d82ccef 2020-01-20 rsc }
426 8d82ccef 2020-01-20 rsc
427 8d82ccef 2020-01-20 rsc void
428 8d82ccef 2020-01-20 rsc _pthreadinit(void)
429 8d82ccef 2020-01-20 rsc {
430 8d82ccef 2020-01-20 rsc signal(SIGUSR2, sigusr2handler);
431 8d82ccef 2020-01-20 rsc }
432 8d82ccef 2020-01-20 rsc
433 8d82ccef 2020-01-20 rsc void
434 8d82ccef 2020-01-20 rsc _threadpexit(void)
435 8d82ccef 2020-01-20 rsc {
436 8d82ccef 2020-01-20 rsc _exit(0);
437 8d82ccef 2020-01-20 rsc }