Annotation of src/sys/rump/librump/rumpkern/lwproc.c, Revision 1.7
1.7 ! pooka 1: /* $NetBSD: lwproc.c,v 1.6 2010/11/22 20:42:19 pooka Exp $ */
1.1 pooka 2:
3: /*
1.7 ! pooka 4: * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
1.1 pooka 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>
1.7 ! pooka 29: __KERNEL_RCSID(0, "$NetBSD: lwproc.c,v 1.6 2010/11/22 20:42:19 pooka Exp $");
1.1 pooka 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 == SIDL || p->p_stat == SDEAD);
57:
58: LIST_REMOVE(p, p_list);
59: LIST_REMOVE(p, p_sibling);
60: proc_free_pid(p->p_pid); /* decrements nprocs */
61: proc_leavepgrp(p); /* releases proc_lock */
62:
63: cred = p->p_cred;
64: chgproccnt(kauth_cred_getuid(cred), -1);
65: if (rump_proc_vfs_release)
66: rump_proc_vfs_release(p);
67:
68: limfree(p->p_limit);
69: pstatsfree(p->p_stats);
70: kauth_cred_free(p->p_cred);
71: proc_finispecific(p);
72:
73: mutex_obj_free(p->p_lock);
74: mutex_destroy(&p->p_stmutex);
75: mutex_destroy(&p->p_auxlock);
76: rw_destroy(&p->p_reflock);
77: cv_destroy(&p->p_waitcv);
78: cv_destroy(&p->p_lwpcv);
79:
1.6 pooka 80: /* non-kernel vmspaces are not shared */
81: if (p->p_vmspace != vmspace_kernel()) {
82: KASSERT(p->p_vmspace->vm_refcnt == 1);
83: kmem_free(p->p_vmspace, sizeof(*p->p_vmspace));
84: }
85:
1.1 pooka 86: proc_free_mem(p);
87: }
88:
89: /*
90: * Allocate a new process. Mostly mimic fork by
91: * copying the properties of the parent. However, there are some
92: * differences. For example, we never share the fd table.
93: *
94: * Switch to the new lwp and return a pointer to it.
95: */
96: static struct proc *
1.7 ! pooka 97: lwproc_newproc(struct proc *parent, int flags)
1.1 pooka 98: {
99: uid_t uid = kauth_cred_getuid(parent->p_cred);
100: struct proc *p;
101:
102: /* maxproc not enforced */
103: atomic_inc_uint(&nprocs);
104:
105: /* allocate process */
106: p = proc_alloc();
107: memset(&p->p_startzero, 0,
108: offsetof(struct proc, p_endzero)
109: - offsetof(struct proc, p_startzero));
110: memcpy(&p->p_startcopy, &parent->p_startcopy,
111: offsetof(struct proc, p_endcopy)
112: - offsetof(struct proc, p_startcopy));
113:
114: p->p_stats = pstatscopy(parent->p_stats);
115:
1.5 pooka 116: p->p_vmspace = vmspace_kernel();
1.1 pooka 117: p->p_emul = &emul_netbsd;
1.7 ! pooka 118:
! 119: if ((flags & RUMP_RFCFDG) == 0)
! 120: KASSERT(parent == curproc);
! 121: if (flags & RUMP_RFFDG)
! 122: p->p_fd = fd_copy();
! 123: else if (flags & RUMP_RFCFDG)
! 124: p->p_fd = fd_init(NULL);
! 125: else
! 126: fd_share(p);
! 127:
1.1 pooka 128: lim_addref(parent->p_limit);
129: p->p_limit = parent->p_limit;
130:
131: LIST_INIT(&p->p_lwps);
132: LIST_INIT(&p->p_children);
133:
134: p->p_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
135: mutex_init(&p->p_stmutex, MUTEX_DEFAULT, IPL_NONE);
136: mutex_init(&p->p_auxlock, MUTEX_DEFAULT, IPL_NONE);
137: rw_init(&p->p_reflock);
138: cv_init(&p->p_waitcv, "pwait");
139: cv_init(&p->p_lwpcv, "plwp");
140:
141: p->p_pptr = parent;
142: p->p_ppid = parent->p_pid;
143:
144: kauth_proc_fork(parent, p);
145:
146: /* initialize cwd in rump kernels with vfs */
147: if (rump_proc_vfs_init)
148: rump_proc_vfs_init(p);
149:
150: chgproccnt(uid, 1); /* not enforced */
151:
152: /* publish proc various proc lists */
153: mutex_enter(proc_lock);
154: LIST_INSERT_HEAD(&allproc, p, p_list);
155: LIST_INSERT_HEAD(&parent->p_children, p, p_sibling);
156: LIST_INSERT_AFTER(parent, p, p_pglist);
157: mutex_exit(proc_lock);
158:
159: return p;
160: }
161:
162: static void
163: lwproc_freelwp(struct lwp *l)
164: {
165: struct proc *p;
166: bool freeproc;
167:
168: p = l->l_proc;
169: mutex_enter(p->p_lock);
170:
171: /* XXX: l_refcnt */
172: KASSERT(l->l_flag & LW_WEXIT);
173: KASSERT(l->l_refcnt == 0);
174:
175: /* ok, zero references, continue with nuke */
176: LIST_REMOVE(l, l_sibling);
177: KASSERT(p->p_nlwps >= 1);
178: if (--p->p_nlwps == 0) {
179: KASSERT(p != &proc0);
180: p->p_stat = SDEAD;
181: }
182: freeproc = p->p_nlwps == 0;
183: cv_broadcast(&p->p_lwpcv); /* nobody sleeps on this in rump? */
184: kauth_cred_free(l->l_cred);
185: mutex_exit(p->p_lock);
186:
187: mutex_enter(proc_lock);
188: LIST_REMOVE(l, l_list);
189: mutex_exit(proc_lock);
190:
191: if (l->l_name)
192: kmem_free(l->l_name, MAXCOMLEN);
193: lwp_finispecific(l);
194:
195: kmem_free(l, sizeof(*l));
196:
197: if (p->p_stat == SDEAD)
198: lwproc_proc_free(p);
199: }
200:
201: /*
202: * called with p_lock held, releases lock before return
203: */
204: static void
205: lwproc_makelwp(struct proc *p, struct lwp *l, bool doswitch, bool procmake)
206: {
207:
208: p->p_nlwps++;
209: l->l_refcnt = 1;
210: l->l_proc = p;
211:
212: l->l_lid = p->p_nlwpid++;
213: LIST_INSERT_HEAD(&p->p_lwps, l, l_sibling);
214: mutex_exit(p->p_lock);
215:
216: lwp_update_creds(l);
217:
218: l->l_fd = p->p_fd;
219: l->l_cpu = NULL;
220: l->l_target_cpu = rump_cpu; /* Initial target CPU always the same */
221:
222: lwp_initspecific(l);
223:
224: if (doswitch) {
225: rump_lwproc_switch(l);
226: }
227:
228: /* filedesc already has refcount 1 when process is created */
229: if (!procmake) {
230: fd_hold(l);
231: }
232:
233: mutex_enter(proc_lock);
234: LIST_INSERT_HEAD(&alllwp, l, l_list);
235: mutex_exit(proc_lock);
236: }
237:
238: struct lwp *
1.3 pooka 239: rump__lwproc_alloclwp(struct proc *p)
1.1 pooka 240: {
241: struct lwp *l;
1.3 pooka 242: bool newproc = false;
243:
244: if (p == NULL) {
1.7 ! pooka 245: p = lwproc_newproc(&proc0, 0);
1.3 pooka 246: newproc = true;
247: }
1.1 pooka 248:
249: l = kmem_zalloc(sizeof(*l), KM_SLEEP);
250:
251: mutex_enter(p->p_lock);
1.3 pooka 252: lwproc_makelwp(p, l, false, newproc);
1.1 pooka 253:
254: return l;
255: }
256:
257: int
258: rump_lwproc_newlwp(pid_t pid)
259: {
260: struct proc *p;
261: struct lwp *l;
262:
263: l = kmem_zalloc(sizeof(*l), KM_SLEEP);
264: mutex_enter(proc_lock);
265: p = proc_find_raw(pid);
266: if (p == NULL) {
267: mutex_exit(proc_lock);
268: kmem_free(l, sizeof(*l));
269: return ESRCH;
270: }
271: mutex_enter(p->p_lock);
272: mutex_exit(proc_lock);
273: lwproc_makelwp(p, l, true, false);
274:
275: return 0;
276: }
277:
278: int
1.7 ! pooka 279: rump_lwproc_rfork(int flags)
1.1 pooka 280: {
281: struct proc *p;
282: struct lwp *l;
283:
1.7 ! pooka 284: if (flags & ~(RUMP_RFFDG|RUMP_RFCFDG) ||
! 285: (~flags & (RUMP_RFFDG|RUMP_RFCFDG)) == 0)
! 286: return EINVAL;
! 287:
! 288: p = lwproc_newproc(curproc, flags);
1.1 pooka 289: l = kmem_zalloc(sizeof(*l), KM_SLEEP);
290: mutex_enter(p->p_lock);
291: lwproc_makelwp(p, l, true, true);
292:
293: return 0;
294: }
295:
296: /*
297: * Switch to a new process/thread. Release previous one if
1.4 pooka 298: * deemed to be exiting. This is considered a slow path for
299: * rump kernel entry.
1.1 pooka 300: */
301: void
302: rump_lwproc_switch(struct lwp *newlwp)
303: {
304: struct lwp *l = curlwp;
305:
306: KASSERT(!(l->l_flag & LW_WEXIT) || newlwp);
307:
308: if (__predict_false(newlwp && (newlwp->l_pflag & LP_RUNNING)))
309: panic("lwp %p (%d:%d) already running",
310: newlwp, newlwp->l_proc->p_pid, newlwp->l_lid);
311:
312: if (newlwp == NULL) {
313: l->l_pflag &= ~LP_RUNNING;
314: l->l_flag |= LW_RUMP_CLEAR;
315: return;
316: }
317:
318: /* fd_free() must be called from curlwp context. talk about ugh */
319: if (l->l_flag & LW_WEXIT) {
320: fd_free();
321: }
322:
323: rumpuser_set_curlwp(NULL);
324:
325: newlwp->l_cpu = newlwp->l_target_cpu = l->l_cpu;
326: newlwp->l_mutex = l->l_mutex;
327: newlwp->l_pflag |= LP_RUNNING;
328:
329: rumpuser_set_curlwp(newlwp);
330:
1.4 pooka 331: /*
332: * Check if the thread should get a signal. This is
333: * mostly to satisfy the "record" rump sigmodel.
334: */
335: mutex_enter(newlwp->l_proc->p_lock);
336: if (sigispending(newlwp, 0)) {
337: newlwp->l_flag |= LW_PENDSIG;
338: }
339: mutex_exit(newlwp->l_proc->p_lock);
340:
1.1 pooka 341: l->l_mutex = NULL;
342: l->l_cpu = NULL;
343: l->l_pflag &= ~LP_RUNNING;
1.4 pooka 344: l->l_flag &= ~LW_PENDSIG;
1.1 pooka 345:
346: if (l->l_flag & LW_WEXIT) {
347: lwproc_freelwp(l);
348: }
349: }
350:
351: void
352: rump_lwproc_releaselwp(void)
353: {
354: struct proc *p;
355: struct lwp *l = curlwp;
356:
1.2 pooka 357: if (l->l_refcnt == 0 && l->l_flag & LW_WEXIT)
358: panic("releasing non-pertinent lwp");
359:
1.1 pooka 360: p = l->l_proc;
361: mutex_enter(p->p_lock);
362: KASSERT(l->l_refcnt != 0);
363: l->l_refcnt--;
364: mutex_exit(p->p_lock);
365: l->l_flag |= LW_WEXIT; /* will be released when unscheduled */
366: }
367:
368: struct lwp *
369: rump_lwproc_curlwp(void)
370: {
371: struct lwp *l = curlwp;
372:
373: if (l->l_flag & LW_WEXIT)
374: return NULL;
375: return l;
376: }
CVSweb <webmaster@jp.NetBSD.org>