2 8d4a3514 2004-09-17 devnull * Is nothing simple?
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.
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"
21 8d4a3514 2004-09-17 devnull int fforkstacksize = 16384;
23 8d4a3514 2004-09-17 devnull typedef struct Stack Stack;
24 8d4a3514 2004-09-17 devnull struct Stack
26 8d4a3514 2004-09-17 devnull Stack *next;
27 8d4a3514 2004-09-17 devnull Stack *fnext;
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);
37 8d4a3514 2004-09-17 devnull static void*
38 8d4a3514 2004-09-17 devnull mallocstack(void)
40 8d4a3514 2004-09-17 devnull Stack *p;
42 8d4a3514 2004-09-17 devnull lock(&stacklock);
44 8d4a3514 2004-09-17 devnull p = freestacks;
46 8d4a3514 2004-09-17 devnull freestacks = p->fnext;
48 8d4a3514 2004-09-17 devnull if(stackmallocs++%1 == 0)
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;
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;
62 8d4a3514 2004-09-17 devnull static void
65 8d4a3514 2004-09-17 devnull Stack *p;
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;
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;
80 8d4a3514 2004-09-17 devnull static void
81 8d4a3514 2004-09-17 devnull freestack(void *v)
83 8d4a3514 2004-09-17 devnull Stack *p;
86 8d4a3514 2004-09-17 devnull if(p == nil)
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);
96 8d4a3514 2004-09-17 devnull static int
97 8d4a3514 2004-09-17 devnull tramp(void *v)
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;
103 8d4a3514 2004-09-17 devnull _p9uproc(0);
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;
114 8d4a3514 2004-09-17 devnull static int
115 8d4a3514 2004-09-17 devnull trampnowait(void *v)
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;
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;
134 8d4a3514 2004-09-17 devnull ffork(int flags, void (*fn)(void*), void *arg)
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;
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;
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;
154 8d4a3514 2004-09-17 devnull if(!(flags&RFFDG))
155 8d4a3514 2004-09-17 devnull cloneflag |= CLONE_FILES;
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;
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;
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");
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);
184 8d4a3514 2004-09-17 devnull ((Stack*)p)->pid = thepid;
185 8d4a3514 2004-09-17 devnull return thepid;
189 8d4a3514 2004-09-17 devnull getfforkid(void)
191 8d4a3514 2004-09-17 devnull return getpid();