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 void
22 _clearuproc(void)
23 {
24 int i;
26 /* called right after fork - no locking needed */
27 for(i=0; i<PIDHASH; i++)
28 if(alluproc[i] != T && alluproc[i] != 0)
29 free(alluproc[i]);
30 memset(alluproc, 0, sizeof alluproc);
31 memset(allupid, 0, sizeof allupid);
32 }
34 Uproc*
35 _p9uproc(int inhandler)
36 {
37 int i, h, pid;
38 Uproc *up;
40 /* for now, assume getpid is fast or cached */
41 pid = getpid();
43 /*
44 * this part - the lookup - needs to run without locks
45 * so that it can safely be called from within the notify handler.
46 * notify calls _p9uproc, and fork and rfork call _p9uproc
47 * in both parent and child, so if we're in a signal handler,
48 * we should find something in the table.
49 */
50 h = pid%PIDHASH;
51 for(i=0; i<PIDHASH; i++){
52 up = alluproc[h];
53 if(up == nil)
54 break;
55 if(allupid[h] == pid)
56 return up;
57 if(++h == PIDHASH)
58 h = 0;
59 }
61 if(inhandler){
62 fprint(2, "%s: did not find uproc for pid %d in signal handler\n", argv0, pid);
63 abort();
64 }
66 /* need to allocate */
67 while((up = mallocz(sizeof(Uproc), 1)) == nil)
68 sleep(1000);
70 /* fprint(2, "alloc uproc for pid %d\n", pid); */
71 up->pid = pid;
72 lock(&uproclock);
73 h = pid%PIDHASH;
74 for(i=0; i<PIDHASH; i++){
75 if(alluproc[h]==T || alluproc[h]==nil){
76 alluproc[h] = up;
77 allupid[h] = pid;
78 unlock(&uproclock);
79 return up;
80 }
81 if(++h == PIDHASH)
82 h = 0;
83 }
84 unlock(&uproclock);
86 /* out of pids! */
87 sysfatal("too many processes in uproc table");
88 return nil;
89 }
91 void
92 _p9uprocdie(void)
93 {
94 Uproc *up;
95 int pid, i, h;
97 pid = getpid();
98 /* fprint(2, "reap uproc for pid %d\n", pid); */
99 h = pid%PIDHASH;
100 for(i=0; i<PIDHASH; i++){
101 up = alluproc[h];
102 if(up == nil)
103 break;
104 if(up == T)
105 continue;
106 if(allupid[h] == pid){
107 up = alluproc[h];
108 alluproc[h] = T;
109 free(up);
110 allupid[h] = 0;