[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / proc

Annotation of prex-old/usr/server/proc/main.c, Revision 1.1.1.1.2.1

1.1       nbrk        1: /*
1.1.1.1.2.1! nbrk        2:  * Copyright (c) 2005-2008, Kohsuke Ohtani
1.1       nbrk        3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the author nor the names of any co-contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
                     30: /*
                     31:  * Process server:
                     32:  *
1.1.1.1.2.1! nbrk       33:  * A process server is responsible to handle process ID, group
        !            34:  * ID, signal and fork()/exec() state. Since Prex microkernel
        !            35:  * does not have the concept about process or process group, the
        !            36:  * process server will map each Prex task to POSIX process.
1.1       nbrk       37:  *
                     38:  * Prex does not support uid (user ID) and gid (group ID) because
                     39:  * it runs only in a single user mode. The value of uid and gid is
                     40:  * always returned as 1 for all process. These are handled by the
                     41:  * library stubs, and it is out of scope in this server.
                     42:  *
                     43:  * Important Notice:
1.1.1.1.2.1! nbrk       44:  * This server is made as a single thread program to reduce many
        !            45:  * locks and to keep the code clean. So, we should not block in
        !            46:  * the kernel for any service. If some service must wait an
        !            47:  * event, it should wait within the library stub in the client
        !            48:  * application.
1.1       nbrk       49:  */
                     50:
                     51: #include <prex/prex.h>
                     52: #include <server/proc.h>
                     53: #include <server/stdmsg.h>
                     54: #include <server/object.h>
                     55: #include <sys/list.h>
                     56:
                     57: #include <unistd.h>
                     58: #include <errno.h>
                     59: #include <stdlib.h>
                     60:
                     61: #include "proc.h"
                     62:
                     63: /* forward declarations */
1.1.1.1.2.1! nbrk       64: static int proc_debug(struct msg *);
        !            65: static int proc_shutdown(struct msg *);
        !            66: static int proc_exec(struct msg *);
        !            67: static int proc_pstat(struct msg *);
        !            68: static int proc_register(struct msg *);
        !            69: static int proc_setinit(struct msg *);
1.1       nbrk       70:
                     71: /*
                     72:  * Message mapping
                     73:  */
                     74: struct msg_map {
                     75:        int code;
                     76:        int (*func)(struct msg *);
                     77: };
                     78:
                     79: static const struct msg_map procmsg_map[] = {
                     80:        {STD_DEBUG,     proc_debug},
                     81:        {STD_SHUTDOWN,  proc_shutdown},
                     82:        {PS_GETPID,     proc_getpid},
                     83:        {PS_GETPPID,    proc_getppid},
                     84:        {PS_GETPGID,    proc_getpgid},
                     85:        {PS_SETPGID,    proc_setpgid},
1.1.1.1.2.1! nbrk       86:        {PS_GETSID,     proc_getsid},
        !            87:        {PS_SETSID,     proc_setsid},
1.1       nbrk       88:        {PS_FORK,       proc_fork},
                     89:        {PS_EXIT,       proc_exit},
                     90:        {PS_STOP,       proc_stop},
                     91:        {PS_WAITPID,    proc_waitpid},
                     92:        {PS_KILL,       proc_kill},
                     93:        {PS_EXEC,       proc_exec},
                     94:        {PS_PSTAT,      proc_pstat},
                     95:        {PS_REGISTER,   proc_register},
                     96:        {PS_SETINIT,    proc_setinit},
1.1.1.1.2.1! nbrk       97:        {0,             NULL},
1.1       nbrk       98: };
                     99:
                    100: static struct proc proc0;      /* process data of this server (pid=0) */
1.1.1.1.2.1! nbrk      101: static struct pgrp pgrp0;      /* process group for first process */
        !           102: static struct session session0;        /* session for first process */
1.1       nbrk      103:
                    104: struct proc initproc;          /* process slot for init process (pid=1) */
                    105: struct proc *curproc;          /* current (caller) process */
                    106: struct list allproc;           /* list of all processes */
                    107:
1.1.1.1.2.1! nbrk      108: /*
        !           109:  * Create a new process.
        !           110:  */
1.1       nbrk      111: static void
                    112: newproc(struct proc *p, pid_t pid, task_t task)
                    113: {
                    114:
1.1.1.1.2.1! nbrk      115:        p->p_parent = &proc0;
        !           116:        p->p_pgrp = &pgrp0;
        !           117:        p->p_stat = SRUN;
        !           118:        p->p_exitcode = 0;
        !           119:        p->p_vforked = 0;
        !           120:        p->p_pid = pid;
        !           121:        p->p_task = task;
        !           122:        list_init(&p->p_children);
        !           123:        list_insert(&allproc, &p->p_link);
1.1       nbrk      124:        proc_add(p);
1.1.1.1.2.1! nbrk      125:        list_insert(&proc0.p_children, &p->p_sibling);
        !           126:        list_insert(&pgrp0.pg_members, &p->p_pgrp_link);
1.1       nbrk      127: }
                    128:
                    129: /*
                    130:  * exec() - Update pid to track the mapping with task id.
1.1.1.1.2.1! nbrk      131:  * The almost all work is done by a exec server for exec()
        !           132:  * emulation. So, there is not so many jobs here...
1.1       nbrk      133:  */
                    134: static int
                    135: proc_exec(struct msg *msg)
                    136: {
1.1.1.1.2.1! nbrk      137:        task_t orgtask, newtask;
1.1       nbrk      138:        struct proc *p, *parent;
                    139:
1.1.1.1.2.1! nbrk      140:        DPRINTF(("proc_exec: pid=%x\n", curproc->p_pid));
        !           141:
        !           142:        orgtask = (task_t)msg->data[0];
        !           143:        newtask = (task_t)msg->data[1];
        !           144:        if ((p = task_to_proc(orgtask)) == NULL)
1.1       nbrk      145:                return EINVAL;
                    146:
                    147:        proc_remove(p);
1.1.1.1.2.1! nbrk      148:        p->p_task = newtask;
1.1       nbrk      149:        proc_add(p);
1.1.1.1.2.1! nbrk      150:        p->p_stackbase = (void *)msg->data[2];
1.1       nbrk      151:
1.1.1.1.2.1! nbrk      152:        parent = p->p_parent;
        !           153:        if (parent != NULL && parent->p_vforked)
1.1       nbrk      154:                vfork_end(parent);
                    155:        return 0;
                    156: }
                    157:
                    158: /*
                    159:  * Get process status.
                    160:  */
                    161: static int
                    162: proc_pstat(struct msg *msg)
                    163: {
                    164:        task_t task;
                    165:        struct proc *p;
                    166:
1.1.1.1.2.1! nbrk      167:        DPRINTF(("proc_pstat: task=%x\n", msg->data[0]));
        !           168:
        !           169:        task = (task_t)msg->data[0];
1.1       nbrk      170:        if ((p = task_to_proc(task)) == NULL)
                    171:                return EINVAL;
                    172:
1.1.1.1.2.1! nbrk      173:        msg->data[0] = (int)p->p_pid;
        !           174:        msg->data[2] = (int)p->p_stat;
        !           175:        if (p->p_parent == NULL)
1.1       nbrk      176:                msg->data[1] = (int)0;
                    177:        else
1.1.1.1.2.1! nbrk      178:                msg->data[1] = (int)p->p_parent->p_pid;
1.1       nbrk      179:        return 0;
                    180: }
                    181:
                    182: /*
                    183:  * Set init process (pid=1).
                    184:  */
                    185: static int
                    186: proc_setinit(struct msg *msg)
                    187: {
                    188:        struct proc *p;
                    189:
                    190:        p = &initproc;
1.1.1.1.2.1! nbrk      191:        if (p->p_stat == SRUN)
1.1       nbrk      192:                return EPERM;
                    193:
                    194:        newproc(p, 1, msg->hdr.task);
                    195:        return 0;
                    196: }
                    197:
                    198: /*
                    199:  * Register boot task.
                    200:  */
                    201: static int
                    202: proc_register(struct msg *msg)
                    203: {
                    204:        struct proc *p;
                    205:        pid_t pid;
                    206:
                    207:        if ((p = malloc(sizeof(struct proc))) == NULL)
                    208:                return ENOMEM;
                    209:
1.1.1.1.2.1! nbrk      210:        if ((pid = pid_assign()) == 0) {
        !           211:                free(p);
1.1       nbrk      212:                return EAGAIN;  /* Too many processes */
1.1.1.1.2.1! nbrk      213:        }
1.1       nbrk      214:        newproc(p, pid, msg->hdr.task);
                    215:        return 0;
                    216: }
                    217:
                    218: static int
                    219: proc_shutdown(struct msg *msg)
                    220: {
                    221:
                    222:        return 0;
                    223: }
                    224:
                    225: static int
                    226: proc_debug(struct msg *msg)
                    227: {
                    228: #ifdef DEBUG_PROC
                    229:        struct proc *p;
                    230:        list_t n;
1.1.1.1.2.1! nbrk      231:        char stat[][5] = { "    ", "RUN ", "ZOMB", "STOP" };
        !           232:
        !           233:        dprintf("<Process Server>\n");
        !           234:        dprintf("Dump process\n");
        !           235:        dprintf(" pid    ppid   pgid   sid    stat task\n");
        !           236:        dprintf(" ------ ------ ------ ------ ---- --------\n");
1.1       nbrk      237:
                    238:        for (n = list_first(&allproc); n != &allproc;
                    239:             n = list_next(n)) {
1.1.1.1.2.1! nbrk      240:                p = list_entry(n, struct proc, p_link);
        !           241:                dprintf(" %6d %6d %6d %6d %s %08x\n", p->p_pid,
        !           242:                        p->p_parent->p_pid, p->p_pgrp->pg_pgid,
        !           243:                        p->p_pgrp->pg_session->s_leader->p_pid,
        !           244:                        stat[p->p_stat], p->p_task);
1.1       nbrk      245:        }
1.1.1.1.2.1! nbrk      246:        dprintf("\n");
1.1       nbrk      247: #endif
                    248:        return 0;
                    249: }
                    250:
                    251: static void
                    252: init(void)
                    253: {
                    254:        struct proc *p;
                    255:
1.1.1.1.2.1! nbrk      256:        p = &proc0;
        !           257:        curproc = p;
        !           258:
1.1       nbrk      259:        tty_init();
                    260:        table_init();
1.1.1.1.2.1! nbrk      261:        list_init(&allproc);
1.1       nbrk      262:
                    263:        /*
1.1.1.1.2.1! nbrk      264:         * Create process 0 (the process server)
1.1       nbrk      265:         */
1.1.1.1.2.1! nbrk      266:        pgrp0.pg_pgid = 0;
        !           267:        list_init(&pgrp0.pg_members);
1.1       nbrk      268:        pgrp_add(&pgrp0);
1.1.1.1.2.1! nbrk      269:
        !           270:        pgrp0.pg_session = &session0;
        !           271:        session0.s_refcnt = 1;
        !           272:        session0.s_leader = p;
        !           273:        session0.s_ttyhold = 0;
        !           274:
        !           275:        p->p_pgrp = &pgrp0;
        !           276:        p->p_parent = 0;
        !           277:        p->p_stat = SRUN;
        !           278:        p->p_exitcode = 0;
        !           279:        p->p_vforked = 0;
        !           280:        p->p_pid = 0;
        !           281:        p->p_task = task_self();
        !           282:        list_init(&p->p_children);
        !           283:        proc_add(p);
        !           284:        list_insert(&pgrp0.pg_members, &p->p_pgrp_link);
        !           285:
        !           286:        DPRINTF(("proc0=%x init=%x\n", &proc0, &initproc));
1.1       nbrk      287: }
                    288:
                    289: /*
                    290:  * Main routine for process service.
                    291:  */
                    292: int
                    293: main(int argc, char *argv[])
                    294: {
                    295:        static struct msg msg;
                    296:        const struct msg_map *map;
                    297:        object_t obj;
                    298:        int err;
                    299:
                    300:        sys_log("Starting Process Server\n");
                    301:
                    302:        /*
                    303:         * Boost current priority.
                    304:         */
                    305:        thread_setprio(thread_self(), PRIO_PROC);
                    306:
                    307:        /*
                    308:         * Initialize everything.
                    309:         */
                    310:        init();
                    311:
                    312:        /*
                    313:         * Create an object to expose our service.
                    314:         */
                    315:        if ((err = object_create(OBJNAME_PROC, &obj)) != 0)
                    316:                sys_panic("proc: fail to create object");
                    317:
                    318:        /*
                    319:         * Message loop
                    320:         */
                    321:        for (;;) {
                    322:                /*
                    323:                 * Wait for an incoming request.
                    324:                 */
                    325:                err = msg_receive(obj, &msg, sizeof(msg));
                    326:                if (err)
                    327:                        continue;
                    328:
                    329:                err = EINVAL;
                    330:                map = &procmsg_map[0];
                    331:                while (map->code != 0) {
                    332:                        if (map->code == msg.hdr.code) {
                    333:
                    334:                                /* Get current process */
                    335:                                curproc = task_to_proc(msg.hdr.task);
                    336:
                    337:                                /* Update the capability of caller task. */
1.1.1.1.2.1! nbrk      338:                                if (curproc &&
        !           339:                                    task_getcap(msg.hdr.task, &curproc->p_cap))
1.1       nbrk      340:                                        break;
                    341:
1.1.1.1.2.1! nbrk      342:                                err = (*map->func)(&msg);
1.1       nbrk      343:                                break;
                    344:                        }
                    345:                        map++;
                    346:                }
                    347:                /*
                    348:                 * Reply to the client.
                    349:                 */
                    350:                msg.hdr.status = err;
                    351:                msg_reply(obj, &msg, sizeof(msg));
                    352: #ifdef DEBUG_PROC
                    353:                if (err)
1.1.1.1.2.1! nbrk      354:                        DPRINTF(("proc: msg code=%x error=%d\n", map->code,
        !           355:                                 err));
1.1       nbrk      356: #endif
                    357:        }
                    358:        return 0;
                    359: }

CVSweb