Annotation of prex/usr/server/proc/main.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005-2008, 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
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.
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
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.
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 */
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 *);
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},
86: {PS_GETSID, proc_getsid},
87: {PS_SETSID, proc_setsid},
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},
97: {0, NULL},
98: };
99:
100: static struct proc proc0; /* process data of this server (pid=0) */
101: static struct pgrp pgrp0; /* process group for first process */
102: static struct session session0; /* session for first process */
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:
108: /*
109: * Create a new process.
110: */
111: static void
112: newproc(struct proc *p, pid_t pid, task_t task)
113: {
114:
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);
124: proc_add(p);
125: list_insert(&proc0.p_children, &p->p_sibling);
126: list_insert(&pgrp0.pg_members, &p->p_pgrp_link);
127: }
128:
129: /*
130: * exec() - Update pid to track the mapping with task id.
131: * The almost all work is done by a exec server for exec()
132: * emulation. So, there is not so many jobs here...
133: */
134: static int
135: proc_exec(struct msg *msg)
136: {
137: task_t orgtask, newtask;
138: struct proc *p, *parent;
139:
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)
145: return EINVAL;
146:
147: proc_remove(p);
148: p->p_task = newtask;
149: proc_add(p);
150: p->p_stackbase = (void *)msg->data[2];
151:
152: parent = p->p_parent;
153: if (parent != NULL && parent->p_vforked)
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:
167: DPRINTF(("proc_pstat: task=%x\n", msg->data[0]));
168:
169: task = (task_t)msg->data[0];
170: if ((p = task_to_proc(task)) == NULL)
171: return EINVAL;
172:
173: msg->data[0] = (int)p->p_pid;
174: msg->data[2] = (int)p->p_stat;
175: if (p->p_parent == NULL)
176: msg->data[1] = (int)0;
177: else
178: msg->data[1] = (int)p->p_parent->p_pid;
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;
191: if (p->p_stat == SRUN)
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:
210: if ((pid = pid_assign()) == 0) {
211: free(p);
212: return EAGAIN; /* Too many processes */
213: }
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;
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");
237:
238: for (n = list_first(&allproc); n != &allproc;
239: n = list_next(n)) {
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);
245: }
246: dprintf("\n");
247: #endif
248: return 0;
249: }
250:
251: static void
252: init(void)
253: {
254: struct proc *p;
255:
256: p = &proc0;
257: curproc = p;
258:
259: tty_init();
260: table_init();
261: list_init(&allproc);
262:
263: /*
264: * Create process 0 (the process server)
265: */
266: pgrp0.pg_pgid = 0;
267: list_init(&pgrp0.pg_members);
268: pgrp_add(&pgrp0);
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));
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. */
338: if (curproc &&
339: task_getcap(msg.hdr.task, &curproc->p_cap))
340: break;
341:
342: err = (*map->func)(&msg);
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)
354: DPRINTF(("proc: msg code=%x error=%d\n", map->code,
355: err));
356: #endif
357: }
358: return 0;
359: }
CVSweb