Blame


1 8d4a3514 2004-09-17 devnull /*
2 8d4a3514 2004-09-17 devnull * Is nothing simple?
3 8d4a3514 2004-09-17 devnull *
4 8d4a3514 2004-09-17 devnull * We can't free the stack until we've finished executing,
5 8d4a3514 2004-09-17 devnull * but once we've finished executing, we can't do anything
6 8d4a3514 2004-09-17 devnull * at all, including call free. So instead we keep a linked list
7 8d4a3514 2004-09-17 devnull * of all stacks for all processes, and every few times we try
8 8d4a3514 2004-09-17 devnull * to allocate a new stack we scan the current stack list for
9 8d4a3514 2004-09-17 devnull * dead processes and reclaim those stacks.
10 8d4a3514 2004-09-17 devnull */
11 8d4a3514 2004-09-17 devnull
12 8d4a3514 2004-09-17 devnull #include <u.h>
13 8d4a3514 2004-09-17 devnull #include <sys/types.h>
14 8d4a3514 2004-09-17 devnull #include <sys/wait.h>
15 8d4a3514 2004-09-17 devnull #include <sched.h>
16 8d4a3514 2004-09-17 devnull #include <signal.h>
17 8d4a3514 2004-09-17 devnull #include <errno.h>
18 8d4a3514 2004-09-17 devnull #include <libc.h>
19 8d4a3514 2004-09-17 devnull #include "9proc.h"
20 8d4a3514 2004-09-17 devnull
21 8d4a3514 2004-09-17 devnull int fforkstacksize = 16384;
22 8d4a3514 2004-09-17 devnull
23 8d4a3514 2004-09-17 devnull typedef struct Stack Stack;
24 8d4a3514 2004-09-17 devnull struct Stack
25 8d4a3514 2004-09-17 devnull {
26 8d4a3514 2004-09-17 devnull Stack *next;
27 8d4a3514 2004-09-17 devnull Stack *fnext;
28 8d4a3514 2004-09-17 devnull int pid;
29 8d4a3514 2004-09-17 devnull };
30 8d4a3514 2004-09-17 devnull
31 8d4a3514 2004-09-17 devnull static Lock stacklock;
32 8d4a3514 2004-09-17 devnull static Stack *freestacks;
33 8d4a3514 2004-09-17 devnull static Stack *allstacks;
34 8d4a3514 2004-09-17 devnull static int stackmallocs;
35 8d4a3514 2004-09-17 devnull static void gc(void);
36 8d4a3514 2004-09-17 devnull
37 8d4a3514 2004-09-17 devnull static void*
38 8d4a3514 2004-09-17 devnull mallocstack(void)
39 8d4a3514 2004-09-17 devnull {
40 8d4a3514 2004-09-17 devnull Stack *p;
41 8d4a3514 2004-09-17 devnull
42 8d4a3514 2004-09-17 devnull lock(&stacklock);
43 8d4a3514 2004-09-17 devnull top:
44 8d4a3514 2004-09-17 devnull p = freestacks;
45 8d4a3514 2004-09-17 devnull if(p)
46 8d4a3514 2004-09-17 devnull freestacks = p->fnext;
47 8d4a3514 2004-09-17 devnull else{
48 8d4a3514 2004-09-17 devnull if(stackmallocs++%1 == 0)
49 8d4a3514 2004-09-17 devnull gc();
50 8d4a3514 2004-09-17 devnull if(freestacks)
51 8d4a3514 2004-09-17 devnull goto top;
52 8d4a3514 2004-09-17 devnull p = malloc(fforkstacksize);
53 8d4a3514 2004-09-17 devnull p->next = allstacks;
54 8d4a3514 2004-09-17 devnull allstacks = p;
55 8d4a3514 2004-09-17 devnull }
56 8d4a3514 2004-09-17 devnull if(p)
57 8d4a3514 2004-09-17 devnull p->pid = 1;
58 8d4a3514 2004-09-17 devnull unlock(&stacklock);
59 8d4a3514 2004-09-17 devnull return p;
60 8d4a3514 2004-09-17 devnull }
61 8d4a3514 2004-09-17 devnull
62 8d4a3514 2004-09-17 devnull static void
63 8d4a3514 2004-09-17 devnull gc(void)
64 8d4a3514 2004-09-17 devnull {
65 8d4a3514 2004-09-17 devnull Stack *p;
66 8d4a3514 2004-09-17 devnull
67 8d4a3514 2004-09-17 devnull for(p=allstacks; p; p=p->next){
68 8d4a3514 2004-09-17 devnull if(p->pid > 1)
69 8d4a3514 2004-09-17 devnull if(kill(p->pid, 0) < 0 && errno == ESRCH){
70 8d4a3514 2004-09-17 devnull if(0) fprint(2, "reclaim stack from %d\n", p->pid);
71 8d4a3514 2004-09-17 devnull p->pid = 0;
72 8d4a3514 2004-09-17 devnull }
73 8d4a3514 2004-09-17 devnull if(p->pid == 0){
74 8d4a3514 2004-09-17 devnull p->fnext = freestacks;
75 8d4a3514 2004-09-17 devnull freestacks = p;
76 8d4a3514 2004-09-17 devnull }
77 8d4a3514 2004-09-17 devnull }
78 8d4a3514 2004-09-17 devnull }
79 8d4a3514 2004-09-17 devnull
80 8d4a3514 2004-09-17 devnull static void
81 8d4a3514 2004-09-17 devnull freestack(void *v)
82 8d4a3514 2004-09-17 devnull {
83 8d4a3514 2004-09-17 devnull Stack *p;
84 8d4a3514 2004-09-17 devnull
85 8d4a3514 2004-09-17 devnull p = v;
86 8d4a3514 2004-09-17 devnull if(p == nil)
87 8d4a3514 2004-09-17 devnull return;
88 8d4a3514 2004-09-17 devnull lock(&stacklock);
89 8d4a3514 2004-09-17 devnull p->fnext = freestacks;
90 8d4a3514 2004-09-17 devnull p->pid = 0;
91 8d4a3514 2004-09-17 devnull freestacks = p;
92 8d4a3514 2004-09-17 devnull unlock(&stacklock);
93 8d4a3514 2004-09-17 devnull return;
94 8d4a3514 2004-09-17 devnull }
95 8d4a3514 2004-09-17 devnull
96 8d4a3514 2004-09-17 devnull static int
97 8d4a3514 2004-09-17 devnull tramp(void *v)
98 8d4a3514 2004-09-17 devnull {
99 8d4a3514 2004-09-17 devnull void (*fn)(void*), *arg;
100 8d4a3514 2004-09-17 devnull void **v2;
101 8d4a3514 2004-09-17 devnull void *p;
102 8d4a3514 2004-09-17 devnull
103 8d4a3514 2004-09-17 devnull _p9uproc(0);
104 8d4a3514 2004-09-17 devnull v2 = v;
105 8d4a3514 2004-09-17 devnull fn = v2[0];
106 8d4a3514 2004-09-17 devnull arg = v2[1];
107 8d4a3514 2004-09-17 devnull p = v2[2];
108 8d4a3514 2004-09-17 devnull free(v2);
109 8d4a3514 2004-09-17 devnull fn(arg);
110 8d4a3514 2004-09-17 devnull _exit(0);
111 8d4a3514 2004-09-17 devnull return 0;
112 8d4a3514 2004-09-17 devnull }
113 8d4a3514 2004-09-17 devnull
114 8d4a3514 2004-09-17 devnull static int
115 8d4a3514 2004-09-17 devnull trampnowait(void *v)
116 8d4a3514 2004-09-17 devnull {
117 8d4a3514 2004-09-17 devnull int pid;
118 8d4a3514 2004-09-17 devnull int cloneflag;
119 8d4a3514 2004-09-17 devnull void **v2;
120 8d4a3514 2004-09-17 devnull int *pidp;
121 8d4a3514 2004-09-17 devnull void *p;
122 8d4a3514 2004-09-17 devnull
123 8d4a3514 2004-09-17 devnull v2 = v;
124 8d4a3514 2004-09-17 devnull cloneflag = (int)v2[4];
125 8d4a3514 2004-09-17 devnull pidp = v2[3];
126 8d4a3514 2004-09-17 devnull p = v2[2];
127 8d4a3514 2004-09-17 devnull pid = clone(tramp, p+fforkstacksize-512, cloneflag, v);
128 8d4a3514 2004-09-17 devnull *pidp = pid;
129 8d4a3514 2004-09-17 devnull _exit(0);
130 8d4a3514 2004-09-17 devnull return 0;
131 8d4a3514 2004-09-17 devnull }
132 8d4a3514 2004-09-17 devnull
133 8d4a3514 2004-09-17 devnull int
134 8d4a3514 2004-09-17 devnull ffork(int flags, void (*fn)(void*), void *arg)
135 8d4a3514 2004-09-17 devnull {
136 8d4a3514 2004-09-17 devnull void **v;
137 8d4a3514 2004-09-17 devnull char *p;
138 8d4a3514 2004-09-17 devnull int cloneflag, pid, thepid, status, nowait;
139 8d4a3514 2004-09-17 devnull
140 8d4a3514 2004-09-17 devnull _p9uproc(0);
141 8d4a3514 2004-09-17 devnull p = mallocstack();
142 8d4a3514 2004-09-17 devnull v = malloc(sizeof(void*)*5);
143 8d4a3514 2004-09-17 devnull if(p==nil || v==nil){
144 8d4a3514 2004-09-17 devnull freestack(p);
145 8d4a3514 2004-09-17 devnull free(v);
146 8d4a3514 2004-09-17 devnull return -1;
147 8d4a3514 2004-09-17 devnull }
148 8d4a3514 2004-09-17 devnull cloneflag = 0;
149 8d4a3514 2004-09-17 devnull flags &= ~RFPROC;
150 8d4a3514 2004-09-17 devnull if(flags&RFMEM){
151 8d4a3514 2004-09-17 devnull cloneflag |= CLONE_VM;
152 8d4a3514 2004-09-17 devnull flags &= ~RFMEM;
153 8d4a3514 2004-09-17 devnull }
154 8d4a3514 2004-09-17 devnull if(!(flags&RFFDG))
155 8d4a3514 2004-09-17 devnull cloneflag |= CLONE_FILES;
156 8d4a3514 2004-09-17 devnull else
157 8d4a3514 2004-09-17 devnull flags &= ~RFFDG;
158 8d4a3514 2004-09-17 devnull nowait = flags&RFNOWAIT;
159 8d4a3514 2004-09-17 devnull if(!(flags&RFNOWAIT))
160 8d4a3514 2004-09-17 devnull cloneflag |= SIGCHLD;
161 8d4a3514 2004-09-17 devnull else
162 8d4a3514 2004-09-17 devnull flags &= ~RFNOWAIT;
163 8d4a3514 2004-09-17 devnull if(flags){
164 8d4a3514 2004-09-17 devnull fprint(2, "unknown rfork flags %x\n", flags);
165 8d4a3514 2004-09-17 devnull freestack(p);
166 8d4a3514 2004-09-17 devnull free(v);
167 8d4a3514 2004-09-17 devnull return -1;
168 8d4a3514 2004-09-17 devnull }
169 8d4a3514 2004-09-17 devnull v[0] = fn;
170 8d4a3514 2004-09-17 devnull v[1] = arg;
171 8d4a3514 2004-09-17 devnull v[2] = p;
172 8d4a3514 2004-09-17 devnull v[3] = &thepid;
173 8d4a3514 2004-09-17 devnull v[4] = (void*)cloneflag;
174 8d4a3514 2004-09-17 devnull thepid = -1;
175 8d4a3514 2004-09-17 devnull pid = clone(nowait ? trampnowait : tramp, p+fforkstacksize-16, cloneflag, v);
176 8d4a3514 2004-09-17 devnull if(pid > 0 && nowait){
177 8d4a3514 2004-09-17 devnull if(wait4(pid, &status, __WALL, 0) < 0)
178 8d4a3514 2004-09-17 devnull fprint(2, "ffork wait4: %r\n");
179 8d4a3514 2004-09-17 devnull }else
180 8d4a3514 2004-09-17 devnull thepid = pid;
181 8d4a3514 2004-09-17 devnull if(thepid == -1)
182 8d4a3514 2004-09-17 devnull freestack(p);
183 8d4a3514 2004-09-17 devnull else
184 8d4a3514 2004-09-17 devnull ((Stack*)p)->pid = thepid;
185 8d4a3514 2004-09-17 devnull return thepid;
186 8d4a3514 2004-09-17 devnull }
187 8d4a3514 2004-09-17 devnull
188 8d4a3514 2004-09-17 devnull int
189 8d4a3514 2004-09-17 devnull getfforkid(void)
190 8d4a3514 2004-09-17 devnull {
191 8d4a3514 2004-09-17 devnull return getpid();
192 8d4a3514 2004-09-17 devnull }
193 8d4a3514 2004-09-17 devnull