Blob


1 /*
2 * This needs to be callable from a signal handler, so it has been
3 * written to avoid locks. The only lock is the one used to acquire
4 * an entry in the table, and we make sure that acquiring is done
5 * when not in a handler. Lookup and delete do not need locks.
6 * It's a scan-forward hash table. To avoid breaking chains,
7 * T ((void*)-1) is used as a non-breaking nil.
8 */
10 #include <u.h>
11 #include <libc.h>
12 #include "9proc.h"
14 enum { PIDHASH = 1021 };
16 #define T ((void*)-1)
17 static Uproc *alluproc[PIDHASH];
18 static int allupid[PIDHASH];
19 static Lock uproclock;
21 Uproc*
22 _p9uproc(int inhandler)
23 {
24 int i, h, pid;
25 Uproc *up;
27 /* for now, assume getpid is fast or cached */
28 pid = getpid();
30 /*
31 * this part - the lookup - needs to run without locks
32 * so that it can safely be called from within the notify handler.
33 * notify calls _p9uproc, and fork and rfork call _p9uproc
34 * in both parent and child, so if we're in a signal handler,
35 * we should find something in the table.
36 */
37 h = pid%PIDHASH;
38 for(i=0; i<PIDHASH; i++){
39 up = alluproc[h];
40 if(up == nil)
41 break;
42 if(allupid[h] == pid)
43 return up;
44 if(++h == PIDHASH)
45 h = 0;
46 }
48 if(inhandler)
49 sysfatal("did not find uproc in signal handler");
51 /* need to allocate */
52 while((up = mallocz(sizeof(Uproc), 1)) == nil)
53 sleep(1000);
55 up = mallocz(sizeof(Uproc), 1);
56 lock(&uproclock);
57 h = pid%PIDHASH;
58 for(i=0; i<PIDHASH; i++){
59 if(alluproc[h]==T || alluproc[h]==nil){
60 alluproc[h] = up;
61 allupid[h] = pid;
62 unlock(&uproclock);
63 return up;
64 }
65 if(++h == PIDHASH)
66 h = 0;
67 }
68 unlock(&uproclock);
70 /* out of pids! */
71 sysfatal("too many processes in uproc table");
72 return nil;
73 }
75 void
76 _p9uprocdie(void)
77 {
78 Uproc *up;
79 int pid, i, h;
81 pid = getpid();
82 h = pid%PIDHASH;
83 for(i=0; i<PIDHASH; i++){
84 up = alluproc[h];
85 if(up == nil)
86 break;
87 if(up == T)
88 continue;
89 if(allupid[h] == pid){
90 up = alluproc[h];
91 alluproc[h] = T;
92 free(up);
93 allupid[h] = 0;
94 }
95 }
96 }