[BACK]Return to lwproc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / rump / librump / rumpkern

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>