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