Blame


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