xref: /netbsd/sys/rump/librump/rumpkern/lwproc.c (revision 6550d01e)
1 /*      $NetBSD: lwproc.c,v 1.13 2011/01/28 18:48:21 pooka Exp $	*/
2 
3 /*
4  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: lwproc.c,v 1.13 2011/01/28 18:48:21 pooka Exp $");
30 
31 #include <sys/param.h>
32 #include <sys/atomic.h>
33 #include <sys/filedesc.h>
34 #include <sys/kauth.h>
35 #include <sys/kmem.h>
36 #include <sys/lwp.h>
37 #include <sys/pool.h>
38 #include <sys/proc.h>
39 #include <sys/queue.h>
40 #include <sys/resourcevar.h>
41 #include <sys/uidinfo.h>
42 
43 #include <rump/rumpuser.h>
44 
45 #include "rump_private.h"
46 
47 static void
48 lwproc_proc_free(struct proc *p)
49 {
50 	kauth_cred_t cred;
51 
52 	mutex_enter(proc_lock);
53 
54 	KASSERT(p->p_nlwps == 0);
55 	KASSERT(LIST_EMPTY(&p->p_lwps));
56 	KASSERT(p->p_stat == SACTIVE || p->p_stat == SDYING ||
57 	    p->p_stat == SDEAD);
58 
59 	LIST_REMOVE(p, p_list);
60 	LIST_REMOVE(p, p_sibling);
61 	proc_free_pid(p->p_pid); /* decrements nprocs */
62 	proc_leavepgrp(p); /* releases proc_lock */
63 
64 	cred = p->p_cred;
65 	chgproccnt(kauth_cred_getuid(cred), -1);
66 	if (rump_proc_vfs_release)
67 		rump_proc_vfs_release(p);
68 
69 	limfree(p->p_limit);
70 	pstatsfree(p->p_stats);
71 	kauth_cred_free(p->p_cred);
72 	proc_finispecific(p);
73 
74 	mutex_obj_free(p->p_lock);
75 	mutex_destroy(&p->p_stmutex);
76 	mutex_destroy(&p->p_auxlock);
77 	rw_destroy(&p->p_reflock);
78 	cv_destroy(&p->p_waitcv);
79 	cv_destroy(&p->p_lwpcv);
80 
81 	/* non-kernel vmspaces are not shared */
82 	if (!RUMP_LOCALPROC_P(p)) {
83 		KASSERT(p->p_vmspace->vm_refcnt == 1);
84 		kmem_free(p->p_vmspace, sizeof(*p->p_vmspace));
85 	}
86 
87 	proc_free_mem(p);
88 }
89 
90 /*
91  * Allocate a new process.  Mostly mimic fork by
92  * copying the properties of the parent.  However, there are some
93  * differences.  For example, we never share the fd table.
94  *
95  * Switch to the new lwp and return a pointer to it.
96  */
97 static struct proc *
98 lwproc_newproc(struct proc *parent, int flags)
99 {
100 	uid_t uid = kauth_cred_getuid(parent->p_cred);
101 	struct proc *p;
102 
103 	/* maxproc not enforced */
104 	atomic_inc_uint(&nprocs);
105 
106 	/* allocate process */
107 	p = proc_alloc();
108 	memset(&p->p_startzero, 0,
109 	    offsetof(struct proc, p_endzero)
110 	      - offsetof(struct proc, p_startzero));
111 	memcpy(&p->p_startcopy, &parent->p_startcopy,
112 	    offsetof(struct proc, p_endcopy)
113 	      - offsetof(struct proc, p_startcopy));
114 
115 	p->p_stats = pstatscopy(parent->p_stats);
116 
117 	p->p_vmspace = vmspace_kernel();
118 	p->p_emul = &emul_netbsd;
119 	strcpy(p->p_comm, "rumproc");
120 
121 	if ((flags & RUMP_RFCFDG) == 0)
122 		KASSERT(parent == curproc);
123 	if (flags & RUMP_RFFDG)
124 		p->p_fd = fd_copy();
125 	else if (flags & RUMP_RFCFDG)
126 		p->p_fd = fd_init(NULL);
127 	else
128 		fd_share(p);
129 
130 	lim_addref(parent->p_limit);
131 	p->p_limit = parent->p_limit;
132 
133 	LIST_INIT(&p->p_lwps);
134 	LIST_INIT(&p->p_children);
135 
136 	p->p_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
137 	mutex_init(&p->p_stmutex, MUTEX_DEFAULT, IPL_NONE);
138 	mutex_init(&p->p_auxlock, MUTEX_DEFAULT, IPL_NONE);
139 	rw_init(&p->p_reflock);
140 	cv_init(&p->p_waitcv, "pwait");
141 	cv_init(&p->p_lwpcv, "plwp");
142 
143 	p->p_pptr = parent;
144 	p->p_ppid = parent->p_pid;
145 	p->p_stat = SACTIVE;
146 
147 	kauth_proc_fork(parent, p);
148 
149 	/* initialize cwd in rump kernels with vfs */
150 	if (rump_proc_vfs_init)
151 		rump_proc_vfs_init(p);
152 
153 	chgproccnt(uid, 1); /* not enforced */
154 
155 	/* publish proc various proc lists */
156 	mutex_enter(proc_lock);
157 	LIST_INSERT_HEAD(&allproc, p, p_list);
158 	LIST_INSERT_HEAD(&parent->p_children, p, p_sibling);
159 	LIST_INSERT_AFTER(parent, p, p_pglist);
160 	mutex_exit(proc_lock);
161 
162 	return p;
163 }
164 
165 static void
166 lwproc_freelwp(struct lwp *l)
167 {
168 	struct proc *p;
169 	bool freeproc;
170 
171 	p = l->l_proc;
172 	mutex_enter(p->p_lock);
173 
174 	/* XXX: l_refcnt */
175 	KASSERT(l->l_flag & LW_WEXIT);
176 	KASSERT(l->l_refcnt == 0);
177 
178 	/* ok, zero references, continue with nuke */
179 	LIST_REMOVE(l, l_sibling);
180 	KASSERT(p->p_nlwps >= 1);
181 	if (--p->p_nlwps == 0) {
182 		KASSERT(p != &proc0);
183 		p->p_stat = SDEAD;
184 	}
185 	freeproc = p->p_nlwps == 0;
186 	cv_broadcast(&p->p_lwpcv); /* nobody sleeps on this in rump? */
187 	kauth_cred_free(l->l_cred);
188 	mutex_exit(p->p_lock);
189 
190 	mutex_enter(proc_lock);
191 	LIST_REMOVE(l, l_list);
192 	mutex_exit(proc_lock);
193 
194 	if (l->l_name)
195 		kmem_free(l->l_name, MAXCOMLEN);
196 	lwp_finispecific(l);
197 
198 	kmem_free(l, sizeof(*l));
199 
200 	if (p->p_stat == SDEAD)
201 		lwproc_proc_free(p);
202 }
203 
204 extern kmutex_t unruntime_lock;
205 
206 /*
207  * called with p_lock held, releases lock before return
208  */
209 static void
210 lwproc_makelwp(struct proc *p, struct lwp *l, bool doswitch, bool procmake)
211 {
212 
213 	p->p_nlwps++;
214 	l->l_refcnt = 1;
215 	l->l_proc = p;
216 
217 	l->l_lid = p->p_nlwpid++;
218 	LIST_INSERT_HEAD(&p->p_lwps, l, l_sibling);
219 	mutex_exit(p->p_lock);
220 
221 	lwp_update_creds(l);
222 
223 	l->l_fd = p->p_fd;
224 	l->l_cpu = rump_cpu;
225 	l->l_target_cpu = rump_cpu; /* Initial target CPU always the same */
226 	l->l_stat = LSRUN;
227 	l->l_mutex = &unruntime_lock;
228 	TAILQ_INIT(&l->l_ld_locks);
229 
230 	lwp_initspecific(l);
231 
232 	if (doswitch) {
233 		rump_lwproc_switch(l);
234 	}
235 
236 	/* filedesc already has refcount 1 when process is created */
237 	if (!procmake) {
238 		fd_hold(l);
239 	}
240 
241 	mutex_enter(proc_lock);
242 	LIST_INSERT_HEAD(&alllwp, l, l_list);
243 	mutex_exit(proc_lock);
244 }
245 
246 struct lwp *
247 rump__lwproc_alloclwp(struct proc *p)
248 {
249 	struct lwp *l;
250 	bool newproc = false;
251 
252 	if (p == NULL) {
253 		p = lwproc_newproc(&proc0, 0);
254 		newproc = true;
255 	}
256 
257 	l = kmem_zalloc(sizeof(*l), KM_SLEEP);
258 
259 	mutex_enter(p->p_lock);
260 	lwproc_makelwp(p, l, false, newproc);
261 
262 	return l;
263 }
264 
265 int
266 rump_lwproc_newlwp(pid_t pid)
267 {
268 	struct proc *p;
269 	struct lwp *l;
270 
271 	l = kmem_zalloc(sizeof(*l), KM_SLEEP);
272 	mutex_enter(proc_lock);
273 	p = proc_find_raw(pid);
274 	if (p == NULL) {
275 		mutex_exit(proc_lock);
276 		kmem_free(l, sizeof(*l));
277 		return ESRCH;
278 	}
279 	mutex_enter(p->p_lock);
280 	mutex_exit(proc_lock);
281 	lwproc_makelwp(p, l, true, false);
282 
283 	return 0;
284 }
285 
286 int
287 rump_lwproc_rfork(int flags)
288 {
289 	struct proc *p;
290 	struct lwp *l;
291 
292 	if (flags & ~(RUMP_RFFDG|RUMP_RFCFDG) ||
293 	    (~flags & (RUMP_RFFDG|RUMP_RFCFDG)) == 0)
294 		return EINVAL;
295 
296 	p = lwproc_newproc(curproc, flags);
297 	l = kmem_zalloc(sizeof(*l), KM_SLEEP);
298 	mutex_enter(p->p_lock);
299 	lwproc_makelwp(p, l, true, true);
300 
301 	return 0;
302 }
303 
304 /*
305  * Switch to a new process/thread.  Release previous one if
306  * deemed to be exiting.  This is considered a slow path for
307  * rump kernel entry.
308  */
309 void
310 rump_lwproc_switch(struct lwp *newlwp)
311 {
312 	struct lwp *l = curlwp;
313 
314 	KASSERT(!(l->l_flag & LW_WEXIT) || newlwp);
315 
316 	if (__predict_false(newlwp && (newlwp->l_pflag & LP_RUNNING)))
317 		panic("lwp %p (%d:%d) already running",
318 		    newlwp, newlwp->l_proc->p_pid, newlwp->l_lid);
319 
320 	if (newlwp == NULL) {
321 		l->l_pflag &= ~LP_RUNNING;
322 		l->l_flag |= LW_RUMP_CLEAR;
323 		return;
324 	}
325 
326 	/* fd_free() must be called from curlwp context.  talk about ugh */
327 	if (l->l_flag & LW_WEXIT) {
328 		fd_free();
329 	}
330 
331 	rumpuser_set_curlwp(NULL);
332 
333 	newlwp->l_cpu = newlwp->l_target_cpu = l->l_cpu;
334 	newlwp->l_mutex = l->l_mutex;
335 	newlwp->l_pflag |= LP_RUNNING;
336 
337 	rumpuser_set_curlwp(newlwp);
338 
339 	/*
340 	 * Check if the thread should get a signal.  This is
341 	 * mostly to satisfy the "record" rump sigmodel.
342 	 */
343 	mutex_enter(newlwp->l_proc->p_lock);
344 	if (sigispending(newlwp, 0)) {
345 		newlwp->l_flag |= LW_PENDSIG;
346 	}
347 	mutex_exit(newlwp->l_proc->p_lock);
348 
349 	l->l_mutex = &unruntime_lock;
350 	l->l_pflag &= ~LP_RUNNING;
351 	l->l_flag &= ~LW_PENDSIG;
352 	l->l_stat = LSRUN;
353 
354 	if (l->l_flag & LW_WEXIT) {
355 		lwproc_freelwp(l);
356 	}
357 }
358 
359 void
360 rump_lwproc_releaselwp(void)
361 {
362 	struct proc *p;
363 	struct lwp *l = curlwp;
364 
365 	if (l->l_refcnt == 0 && l->l_flag & LW_WEXIT)
366 		panic("releasing non-pertinent lwp");
367 
368 	p = l->l_proc;
369 	mutex_enter(p->p_lock);
370 	KASSERT(l->l_refcnt != 0);
371 	l->l_refcnt--;
372 	mutex_exit(p->p_lock);
373 	l->l_flag |= LW_WEXIT; /* will be released when unscheduled */
374 }
375 
376 struct lwp *
377 rump_lwproc_curlwp(void)
378 {
379 	struct lwp *l = curlwp;
380 
381 	if (l->l_flag & LW_WEXIT)
382 		return NULL;
383 	return l;
384 }
385