Annotation of prex-old/usr/server/proc/main.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
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: *
33: * A process server is responsible to handle process ID, group ID,
34: * signal and fork()/exec() state. Since Prex microkernel does not
35: * have the concept about process or process group, the process
36: * server will map each Prex task to POSIX process.
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:
44: * This server is made as a single thread program to reduce many locks
45: * and to keep the code clean. So, we should not block in the kernel
46: * for any service. If some service must wait an event, it should wait
47: * within the library stub in the client application.
48: */
49:
50: #include <prex/prex.h>
51: #include <server/proc.h>
52: #include <server/stdmsg.h>
53: #include <server/object.h>
54: #include <sys/list.h>
55:
56: #include <unistd.h>
57: #include <errno.h>
58: #include <stdlib.h>
59:
60: #include "proc.h"
61:
62: /* forward declarations */
63: static int proc_version(struct msg *msg);
64: static int proc_debug(struct msg *msg);
65: static int proc_shutdown(struct msg *msg);
66: static int proc_exec(struct msg *msg);
67: static int proc_pstat(struct msg *msg);
68: static int proc_register(struct msg *msg);
69: static int proc_setinit(struct msg *msg);
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_VERSION, proc_version},
81: {STD_DEBUG, proc_debug},
82: {STD_SHUTDOWN, proc_shutdown},
83: {PS_GETPID, proc_getpid},
84: {PS_GETPPID, proc_getppid},
85: {PS_GETPGID, proc_getpgid},
86: {PS_SETPGID, proc_setpgid},
87: {PS_FORK, proc_fork},
88: {PS_EXIT, proc_exit},
89: {PS_STOP, proc_stop},
90: {PS_WAITPID, proc_waitpid},
91: {PS_KILL, proc_kill},
92: {PS_EXEC, proc_exec},
93: {PS_PSTAT, proc_pstat},
94: {PS_REGISTER, proc_register},
95: {PS_SETINIT, proc_setinit},
96: {0, 0},
97: };
98:
99: static struct proc proc0; /* process data of this server (pid=0) */
100: static struct pgrp pgrp0; /* process group for process server */
101:
102: struct proc initproc; /* process slot for init process (pid=1) */
103: struct proc *curproc; /* current (caller) process */
104: struct list allproc; /* list of all processes */
105:
106: static void
107: newproc(struct proc *p, pid_t pid, task_t task)
108: {
109:
110: p->parent = &proc0;
111: p->pgrp = &pgrp0;
112: p->stat = SRUN;
113: p->exit_code = 0;
114: p->wait_vfork = 0;
115: p->pid = pid;
116: p->task = task;
117: list_init(&p->children);
118: list_insert(&allproc, &p->link);
119: proc_add(p);
120: list_insert(&proc0.children, &p->sibling);
121: list_insert(&pgrp0.members, &p->pgrp_link);
122: }
123:
124: /*
125: * exec() - Update pid to track the mapping with task id.
126: *
127: * The almost all work is done by a exec server for exec() emulation.
128: * So, there is not so many jobs here...
129: */
130: static int
131: proc_exec(struct msg *msg)
132: {
133: task_t org_task, new_task;
134: struct proc *p, *parent;
135:
136: dprintf("proc_exec: proc=%x\n", curproc);
137: org_task = msg->data[0];
138: new_task = msg->data[1];
139: if ((p = task_to_proc(org_task)) == NULL)
140: return EINVAL;
141:
142: proc_remove(p);
143: p->task = new_task;
144: proc_add(p);
145: p->stack_base = (void *)msg->data[2];
146:
147: parent = p->parent;
148: if (parent != NULL && parent->wait_vfork)
149: vfork_end(parent);
150: return 0;
151: }
152:
153: /*
154: * Get process status.
155: */
156: static int
157: proc_pstat(struct msg *msg)
158: {
159: task_t task;
160: struct proc *p;
161:
162: dprintf("proc_pstat: task=%x\n", msg->data[0]);
163: task = msg->data[0];
164: if ((p = task_to_proc(task)) == NULL)
165: return EINVAL;
166:
167: msg->data[0] = (int)p->pid;
168: msg->data[2] = (int)p->stat;
169: if (p->parent == NULL)
170: msg->data[1] = (int)0;
171: else
172: msg->data[1] = (int)p->parent->pid;
173: return 0;
174: }
175:
176: /*
177: * Set init process (pid=1).
178: */
179: static int
180: proc_setinit(struct msg *msg)
181: {
182: struct proc *p;
183:
184: p = &initproc;
185: if (p->stat == SRUN)
186: return EPERM;
187:
188: newproc(p, 1, msg->hdr.task);
189: return 0;
190: }
191:
192: /*
193: * Register boot task.
194: */
195: static int
196: proc_register(struct msg *msg)
197: {
198: struct proc *p;
199: pid_t pid;
200:
201: if ((p = malloc(sizeof(struct proc))) == NULL)
202: return ENOMEM;
203:
204: if ((pid = pid_assign()) == 0)
205: return EAGAIN; /* Too many processes */
206:
207: newproc(p, pid, msg->hdr.task);
208: return 0;
209: }
210:
211: static int
212: proc_version(struct msg *msg)
213: {
214:
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;
231: char stat[][5] = { "RUN ", "ZOMB", "STOP" };
232:
233: printf("<Process Server>\n");
234: printf("Dump process\n");
235: printf(" pid ppid stat task\n");
236: printf(" ------ ------ ---- --------\n");
237: for (n = list_first(&allproc); n != &allproc;
238: n = list_next(n)) {
239: p = list_entry(n, struct proc, link);
240: printf(" %6d %6d %s %08x\n",
241: p->pid, p->parent->pid, stat[p->stat], p->task);
242: }
243: printf("\n");
244: #endif
245: return 0;
246: }
247:
248: static void
249: init(void)
250: {
251: struct proc *p;
252:
253: tty_init();
254: table_init();
255:
256: /*
257: * Setup a process for ourselves.
258: * pid=0 is always reserved by process server.
259: */
260: p = &proc0;
261: p->parent = 0;
262: p->pgrp = &pgrp0;
263: p->stat = SRUN;
264: p->exit_code = 0;
265: p->wait_vfork = 0;
266: p->pid = 0;
267: p->task = task_self();
268: list_init(&p->children);
269: list_init(&allproc);
270: list_init(&pgrp0.members);
271: proc_add(p);
272: pgrp_add(&pgrp0);
273: list_insert(&pgrp0.members, &p->pgrp_link);
274: }
275:
276: /*
277: * Main routine for process service.
278: */
279: int
280: main(int argc, char *argv[])
281: {
282: static struct msg msg;
283: const struct msg_map *map;
284: object_t obj;
285: int err;
286:
287: sys_log("Starting Process Server\n");
288:
289: /*
290: * Boost current priority.
291: */
292: thread_setprio(thread_self(), PRIO_PROC);
293:
294: /*
295: * Initialize everything.
296: */
297: init();
298:
299: /*
300: * Create an object to expose our service.
301: */
302: if ((err = object_create(OBJNAME_PROC, &obj)) != 0)
303: sys_panic("proc: fail to create object");
304:
305: /*
306: * Message loop
307: */
308: for (;;) {
309: /*
310: * Wait for an incoming request.
311: */
312: err = msg_receive(obj, &msg, sizeof(msg));
313: if (err)
314: continue;
315:
316: err = EINVAL;
317: map = &procmsg_map[0];
318: while (map->code != 0) {
319: if (map->code == msg.hdr.code) {
320:
321: /* Get current process */
322: curproc = task_to_proc(msg.hdr.task);
323:
324: /* Update the capability of caller task. */
325: if (curproc && task_getcap(msg.hdr.task,
326: &curproc->cap))
327: break;
328:
329: err = map->func(&msg);
330: break;
331: }
332: map++;
333: }
334: /*
335: * Reply to the client.
336: */
337: msg.hdr.status = err;
338: msg_reply(obj, &msg, sizeof(msg));
339: #ifdef DEBUG_PROC
340: if (err)
341: dprintf("msg code=%x error=%d\n", map->code, err);
342: #endif
343: }
344: return 0;
345: }
CVSweb