1433d6423SLionel Sambuc /* This file contains the main program of the process manager and some related
2433d6423SLionel Sambuc * procedures. When MINIX starts up, the kernel runs for a little while,
3433d6423SLionel Sambuc * initializing itself and its tasks, and then it runs PM and VFS. Both PM
4433d6423SLionel Sambuc * and VFS initialize themselves as far as they can. PM asks the kernel for
5433d6423SLionel Sambuc * all free memory and starts serving requests.
6433d6423SLionel Sambuc *
7433d6423SLionel Sambuc * The entry points into this file are:
8433d6423SLionel Sambuc * main: starts PM running
9433d6423SLionel Sambuc * reply: send a reply to a process making a PM system call
10433d6423SLionel Sambuc */
11433d6423SLionel Sambuc
12433d6423SLionel Sambuc #include "pm.h"
13433d6423SLionel Sambuc #include <minix/callnr.h>
14433d6423SLionel Sambuc #include <minix/com.h>
15433d6423SLionel Sambuc #include <minix/ds.h>
16433d6423SLionel Sambuc #include <minix/endpoint.h>
17433d6423SLionel Sambuc #include <minix/minlib.h>
18433d6423SLionel Sambuc #include <minix/type.h>
19433d6423SLionel Sambuc #include <minix/vm.h>
20433d6423SLionel Sambuc #include <signal.h>
21433d6423SLionel Sambuc #include <stdlib.h>
22433d6423SLionel Sambuc #include <fcntl.h>
23433d6423SLionel Sambuc #include <sys/resource.h>
24433d6423SLionel Sambuc #include <sys/utsname.h>
25433d6423SLionel Sambuc #include <sys/wait.h>
26433d6423SLionel Sambuc #include <machine/archtypes.h>
27433d6423SLionel Sambuc #include <assert.h>
28433d6423SLionel Sambuc #include "mproc.h"
29433d6423SLionel Sambuc
30433d6423SLionel Sambuc #include "kernel/const.h"
31433d6423SLionel Sambuc #include "kernel/config.h"
32433d6423SLionel Sambuc #include "kernel/proc.h"
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc #if ENABLE_SYSCALL_STATS
35433d6423SLionel Sambuc EXTERN unsigned long calls_stats[NR_PM_CALLS];
36433d6423SLionel Sambuc #endif
37433d6423SLionel Sambuc
38433d6423SLionel Sambuc static int get_nice_value(int queue);
39433d6423SLionel Sambuc static void handle_vfs_reply(void);
40433d6423SLionel Sambuc
41433d6423SLionel Sambuc /* SEF functions and variables. */
42433d6423SLionel Sambuc static void sef_local_startup(void);
43433d6423SLionel Sambuc static int sef_cb_init_fresh(int type, sef_init_info_t *info);
44433d6423SLionel Sambuc
45433d6423SLionel Sambuc /*===========================================================================*
46433d6423SLionel Sambuc * main *
47433d6423SLionel Sambuc *===========================================================================*/
48*637f688fSRichard Sailer int
main(void)49*637f688fSRichard Sailer main(void)
50433d6423SLionel Sambuc {
51433d6423SLionel Sambuc /* Main routine of the process manager. */
52433d6423SLionel Sambuc unsigned int call_index;
53433d6423SLionel Sambuc int ipc_status, result;
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc /* SEF local startup. */
56433d6423SLionel Sambuc sef_local_startup();
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc /* This is PM's main loop- get work and do it, forever and forever. */
59433d6423SLionel Sambuc while (TRUE) {
60433d6423SLionel Sambuc /* Wait for the next message. */
61433d6423SLionel Sambuc if (sef_receive_status(ANY, &m_in, &ipc_status) != OK)
62433d6423SLionel Sambuc panic("PM sef_receive_status error");
63433d6423SLionel Sambuc
64433d6423SLionel Sambuc /* Check for system notifications first. Special cases. */
65433d6423SLionel Sambuc if (is_ipc_notify(ipc_status)) {
66433d6423SLionel Sambuc if (_ENDPOINT_P(m_in.m_source) == CLOCK)
67433d6423SLionel Sambuc expire_timers(m_in.m_notify.timestamp);
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc /* done, continue */
70433d6423SLionel Sambuc continue;
71433d6423SLionel Sambuc }
72433d6423SLionel Sambuc
73433d6423SLionel Sambuc /* Extract useful information from the message. */
74433d6423SLionel Sambuc who_e = m_in.m_source; /* who sent the message */
75433d6423SLionel Sambuc if (pm_isokendpt(who_e, &who_p) != OK)
76433d6423SLionel Sambuc panic("PM got message from invalid endpoint: %d", who_e);
77433d6423SLionel Sambuc mp = &mproc[who_p]; /* process slot of caller */
78433d6423SLionel Sambuc call_nr = m_in.m_type; /* system call number */
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc /* Drop delayed calls from exiting processes. */
81433d6423SLionel Sambuc if (mp->mp_flags & EXITING)
82433d6423SLionel Sambuc continue;
83433d6423SLionel Sambuc
84433d6423SLionel Sambuc if (IS_VFS_PM_RS(call_nr) && who_e == VFS_PROC_NR) {
85433d6423SLionel Sambuc handle_vfs_reply();
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc result = SUSPEND; /* don't reply */
88910831cbSDavid van Moolenbroek } else if (call_nr == PROC_EVENT_REPLY) {
89910831cbSDavid van Moolenbroek result = do_proc_event_reply();
90433d6423SLionel Sambuc } else if (IS_PM_CALL(call_nr)) {
91433d6423SLionel Sambuc /* If the system call number is valid, perform the call. */
92433d6423SLionel Sambuc call_index = (unsigned int) (call_nr - PM_BASE);
93433d6423SLionel Sambuc
94433d6423SLionel Sambuc if (call_index < NR_PM_CALLS && call_vec[call_index] != NULL) {
95433d6423SLionel Sambuc #if ENABLE_SYSCALL_STATS
96433d6423SLionel Sambuc calls_stats[call_index]++;
97433d6423SLionel Sambuc #endif
98433d6423SLionel Sambuc
99433d6423SLionel Sambuc result = (*call_vec[call_index])();
100433d6423SLionel Sambuc } else
101433d6423SLionel Sambuc result = ENOSYS;
102433d6423SLionel Sambuc } else
103433d6423SLionel Sambuc result = ENOSYS;
104433d6423SLionel Sambuc
105433d6423SLionel Sambuc /* Send reply. */
106433d6423SLionel Sambuc if (result != SUSPEND) reply(who_p, result);
107433d6423SLionel Sambuc }
108433d6423SLionel Sambuc return(OK);
109433d6423SLionel Sambuc }
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc /*===========================================================================*
112433d6423SLionel Sambuc * sef_local_startup *
113433d6423SLionel Sambuc *===========================================================================*/
114*637f688fSRichard Sailer static void
sef_local_startup(void)115*637f688fSRichard Sailer sef_local_startup(void)
116433d6423SLionel Sambuc {
117433d6423SLionel Sambuc /* Register init callbacks. */
118433d6423SLionel Sambuc sef_setcb_init_fresh(sef_cb_init_fresh);
1193f82ac6aSCristiano Giuffrida sef_setcb_init_restart(SEF_CB_INIT_RESTART_STATEFUL);
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc /* Register signal callbacks. */
122433d6423SLionel Sambuc sef_setcb_signal_manager(process_ksig);
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc /* Let SEF perform startup. */
125433d6423SLionel Sambuc sef_startup();
126433d6423SLionel Sambuc }
127433d6423SLionel Sambuc
128433d6423SLionel Sambuc /*===========================================================================*
129433d6423SLionel Sambuc * sef_cb_init_fresh *
130433d6423SLionel Sambuc *===========================================================================*/
sef_cb_init_fresh(int UNUSED (type),sef_init_info_t * UNUSED (info))131433d6423SLionel Sambuc static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
132433d6423SLionel Sambuc {
133433d6423SLionel Sambuc /* Initialize the process manager. */
134433d6423SLionel Sambuc int s;
135433d6423SLionel Sambuc static struct boot_image image[NR_BOOT_PROCS];
136433d6423SLionel Sambuc register struct boot_image *ip;
137433d6423SLionel Sambuc static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
138433d6423SLionel Sambuc SIGEMT, SIGFPE, SIGBUS, SIGSEGV };
139433d6423SLionel Sambuc static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT, SIGINFO };
140433d6423SLionel Sambuc static char noign_sigs[] = { SIGILL, SIGTRAP, SIGEMT, SIGFPE,
141433d6423SLionel Sambuc SIGBUS, SIGSEGV };
142433d6423SLionel Sambuc register struct mproc *rmp;
143433d6423SLionel Sambuc register char *sig_ptr;
144433d6423SLionel Sambuc message mess;
145433d6423SLionel Sambuc
146433d6423SLionel Sambuc /* Initialize process table, including timers. */
147433d6423SLionel Sambuc for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
148433d6423SLionel Sambuc init_timer(&rmp->mp_timer);
149433d6423SLionel Sambuc rmp->mp_magic = MP_MAGIC;
1506ad322a9SDavid van Moolenbroek rmp->mp_sigact = mpsigact[rmp - mproc];
151910831cbSDavid van Moolenbroek rmp->mp_eventsub = NO_EVENTSUB;
152433d6423SLionel Sambuc }
153433d6423SLionel Sambuc
154433d6423SLionel Sambuc /* Build the set of signals which cause core dumps, and the set of signals
155433d6423SLionel Sambuc * that are by default ignored.
156433d6423SLionel Sambuc */
157433d6423SLionel Sambuc sigemptyset(&core_sset);
158433d6423SLionel Sambuc for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++)
159433d6423SLionel Sambuc sigaddset(&core_sset, *sig_ptr);
160433d6423SLionel Sambuc sigemptyset(&ign_sset);
161433d6423SLionel Sambuc for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++)
162433d6423SLionel Sambuc sigaddset(&ign_sset, *sig_ptr);
163433d6423SLionel Sambuc sigemptyset(&noign_sset);
164433d6423SLionel Sambuc for (sig_ptr = noign_sigs; sig_ptr < noign_sigs+sizeof(noign_sigs); sig_ptr++)
165433d6423SLionel Sambuc sigaddset(&noign_sset, *sig_ptr);
166433d6423SLionel Sambuc
167433d6423SLionel Sambuc /* Obtain a copy of the boot monitor parameters.
168433d6423SLionel Sambuc */
169433d6423SLionel Sambuc if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK)
170433d6423SLionel Sambuc panic("get monitor params failed: %d", s);
171433d6423SLionel Sambuc
172433d6423SLionel Sambuc /* Initialize PM's process table. Request a copy of the system image table
173433d6423SLionel Sambuc * that is defined at the kernel level to see which slots to fill in.
174433d6423SLionel Sambuc */
175433d6423SLionel Sambuc if (OK != (s=sys_getimage(image)))
176433d6423SLionel Sambuc panic("couldn't get image table: %d", s);
177433d6423SLionel Sambuc procs_in_use = 0; /* start populating table */
178433d6423SLionel Sambuc for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
179433d6423SLionel Sambuc if (ip->proc_nr >= 0) { /* task have negative nrs */
180433d6423SLionel Sambuc procs_in_use += 1; /* found user process */
181433d6423SLionel Sambuc
182433d6423SLionel Sambuc /* Set process details found in the image table. */
183433d6423SLionel Sambuc rmp = &mproc[ip->proc_nr];
184433d6423SLionel Sambuc strlcpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN);
185433d6423SLionel Sambuc (void) sigemptyset(&rmp->mp_ignore);
186433d6423SLionel Sambuc (void) sigemptyset(&rmp->mp_sigmask);
187433d6423SLionel Sambuc (void) sigemptyset(&rmp->mp_catch);
188433d6423SLionel Sambuc if (ip->proc_nr == INIT_PROC_NR) { /* user process */
189433d6423SLionel Sambuc /* INIT is root, we make it father of itself. This is
190433d6423SLionel Sambuc * not really OK, INIT should have no father, i.e.
191433d6423SLionel Sambuc * a father with pid NO_PID. But PM currently assumes
192433d6423SLionel Sambuc * that mp_parent always points to a valid slot number.
193433d6423SLionel Sambuc */
194433d6423SLionel Sambuc rmp->mp_parent = INIT_PROC_NR;
195433d6423SLionel Sambuc rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
196433d6423SLionel Sambuc rmp->mp_flags |= IN_USE;
197433d6423SLionel Sambuc
198433d6423SLionel Sambuc /* Set scheduling info */
199433d6423SLionel Sambuc rmp->mp_scheduler = KERNEL;
200433d6423SLionel Sambuc rmp->mp_nice = get_nice_value(USR_Q);
201433d6423SLionel Sambuc }
202433d6423SLionel Sambuc else { /* system process */
203433d6423SLionel Sambuc if(ip->proc_nr == RS_PROC_NR) {
204433d6423SLionel Sambuc rmp->mp_parent = INIT_PROC_NR;
205433d6423SLionel Sambuc }
206433d6423SLionel Sambuc else {
207433d6423SLionel Sambuc rmp->mp_parent = RS_PROC_NR;
208433d6423SLionel Sambuc }
209433d6423SLionel Sambuc rmp->mp_pid = get_free_pid();
210433d6423SLionel Sambuc rmp->mp_flags |= IN_USE | PRIV_PROC;
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc /* RS schedules this process */
213433d6423SLionel Sambuc rmp->mp_scheduler = NONE;
214433d6423SLionel Sambuc rmp->mp_nice = get_nice_value(SRV_Q);
215433d6423SLionel Sambuc }
216433d6423SLionel Sambuc
217433d6423SLionel Sambuc /* Get kernel endpoint identifier. */
218433d6423SLionel Sambuc rmp->mp_endpoint = ip->endpoint;
219433d6423SLionel Sambuc
220433d6423SLionel Sambuc /* Tell VFS about this system process. */
221433d6423SLionel Sambuc memset(&mess, 0, sizeof(mess));
222433d6423SLionel Sambuc mess.m_type = VFS_PM_INIT;
223433d6423SLionel Sambuc mess.VFS_PM_SLOT = ip->proc_nr;
224433d6423SLionel Sambuc mess.VFS_PM_PID = rmp->mp_pid;
225433d6423SLionel Sambuc mess.VFS_PM_ENDPT = rmp->mp_endpoint;
226433d6423SLionel Sambuc if (OK != (s=ipc_send(VFS_PROC_NR, &mess)))
227433d6423SLionel Sambuc panic("can't sync up with VFS: %d", s);
228433d6423SLionel Sambuc }
229433d6423SLionel Sambuc }
230433d6423SLionel Sambuc
231433d6423SLionel Sambuc /* Tell VFS that no more system processes follow and synchronize. */
232433d6423SLionel Sambuc memset(&mess, 0, sizeof(mess));
233433d6423SLionel Sambuc mess.m_type = VFS_PM_INIT;
234433d6423SLionel Sambuc mess.VFS_PM_ENDPT = NONE;
235433d6423SLionel Sambuc if (ipc_sendrec(VFS_PROC_NR, &mess) != OK || mess.m_type != OK)
236433d6423SLionel Sambuc panic("can't sync up with VFS");
237433d6423SLionel Sambuc
238433d6423SLionel Sambuc system_hz = sys_hz();
239433d6423SLionel Sambuc
240433d6423SLionel Sambuc /* Initialize user-space scheduling. */
241433d6423SLionel Sambuc sched_init();
242433d6423SLionel Sambuc
243433d6423SLionel Sambuc return(OK);
244433d6423SLionel Sambuc }
245433d6423SLionel Sambuc
246433d6423SLionel Sambuc /*===========================================================================*
247433d6423SLionel Sambuc * reply *
248433d6423SLionel Sambuc *===========================================================================*/
249*637f688fSRichard Sailer void
reply(int proc_nr,int result)250*637f688fSRichard Sailer reply(
251*637f688fSRichard Sailer int proc_nr, /* process to reply to */
252*637f688fSRichard Sailer int result /* result of call (usually OK or error #) */
253*637f688fSRichard Sailer )
254433d6423SLionel Sambuc {
255433d6423SLionel Sambuc /* Send a reply to a user process. System calls may occasionally fill in other
256433d6423SLionel Sambuc * fields, this is only for the main return value and for sending the reply.
257433d6423SLionel Sambuc */
258433d6423SLionel Sambuc struct mproc *rmp;
259433d6423SLionel Sambuc int r;
260433d6423SLionel Sambuc
261433d6423SLionel Sambuc if(proc_nr < 0 || proc_nr >= NR_PROCS)
262433d6423SLionel Sambuc panic("reply arg out of range: %d", proc_nr);
263433d6423SLionel Sambuc
264433d6423SLionel Sambuc rmp = &mproc[proc_nr];
265433d6423SLionel Sambuc rmp->mp_reply.m_type = result;
266433d6423SLionel Sambuc
267433d6423SLionel Sambuc if ((r = ipc_sendnb(rmp->mp_endpoint, &rmp->mp_reply)) != OK)
268433d6423SLionel Sambuc printf("PM can't reply to %d (%s): %d\n", rmp->mp_endpoint,
269433d6423SLionel Sambuc rmp->mp_name, r);
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc
272433d6423SLionel Sambuc /*===========================================================================*
273433d6423SLionel Sambuc * get_nice_value *
274433d6423SLionel Sambuc *===========================================================================*/
275*637f688fSRichard Sailer static int
get_nice_value(int queue)276*637f688fSRichard Sailer get_nice_value(
277*637f688fSRichard Sailer int queue /* store mem chunks here */
278*637f688fSRichard Sailer )
279433d6423SLionel Sambuc {
280433d6423SLionel Sambuc /* Processes in the boot image have a priority assigned. The PM doesn't know
281433d6423SLionel Sambuc * about priorities, but uses 'nice' values instead. The priority is between
282433d6423SLionel Sambuc * MIN_USER_Q and MAX_USER_Q. We have to scale between PRIO_MIN and PRIO_MAX.
283433d6423SLionel Sambuc */
284433d6423SLionel Sambuc int nice_val = (queue - USER_Q) * (PRIO_MAX-PRIO_MIN+1) /
285433d6423SLionel Sambuc (MIN_USER_Q-MAX_USER_Q+1);
286433d6423SLionel Sambuc if (nice_val > PRIO_MAX) nice_val = PRIO_MAX; /* shouldn't happen */
287433d6423SLionel Sambuc if (nice_val < PRIO_MIN) nice_val = PRIO_MIN; /* shouldn't happen */
288433d6423SLionel Sambuc return nice_val;
289433d6423SLionel Sambuc }
290433d6423SLionel Sambuc
291433d6423SLionel Sambuc /*===========================================================================*
292433d6423SLionel Sambuc * handle_vfs_reply *
293433d6423SLionel Sambuc *===========================================================================*/
294*637f688fSRichard Sailer static void
handle_vfs_reply(void)295*637f688fSRichard Sailer handle_vfs_reply(void)
296433d6423SLionel Sambuc {
297433d6423SLionel Sambuc struct mproc *rmp;
298433d6423SLionel Sambuc endpoint_t proc_e;
299433d6423SLionel Sambuc int r, proc_n, new_parent;
300433d6423SLionel Sambuc
301433d6423SLionel Sambuc /* VFS_PM_REBOOT is the only request not associated with a process.
302433d6423SLionel Sambuc * Handle its reply first.
303433d6423SLionel Sambuc */
304433d6423SLionel Sambuc if (call_nr == VFS_PM_REBOOT_REPLY) {
305433d6423SLionel Sambuc /* Ask the kernel to abort. All system services, including
306433d6423SLionel Sambuc * the PM, will get a HARD_STOP notification. Await the
307433d6423SLionel Sambuc * notification in the main loop.
308433d6423SLionel Sambuc */
309433d6423SLionel Sambuc sys_abort(abort_flag);
310433d6423SLionel Sambuc
311433d6423SLionel Sambuc return;
312433d6423SLionel Sambuc }
313433d6423SLionel Sambuc
314433d6423SLionel Sambuc /* Get the process associated with this call */
315433d6423SLionel Sambuc proc_e = m_in.VFS_PM_ENDPT;
316433d6423SLionel Sambuc
317433d6423SLionel Sambuc if (pm_isokendpt(proc_e, &proc_n) != OK) {
318433d6423SLionel Sambuc panic("handle_vfs_reply: got bad endpoint from VFS: %d", proc_e);
319433d6423SLionel Sambuc }
320433d6423SLionel Sambuc
321433d6423SLionel Sambuc rmp = &mproc[proc_n];
322433d6423SLionel Sambuc
323433d6423SLionel Sambuc /* Now that VFS replied, mark the process as VFS-idle again */
324433d6423SLionel Sambuc if (!(rmp->mp_flags & VFS_CALL))
325433d6423SLionel Sambuc panic("handle_vfs_reply: reply without request: %d", call_nr);
326433d6423SLionel Sambuc
327433d6423SLionel Sambuc new_parent = rmp->mp_flags & NEW_PARENT;
328433d6423SLionel Sambuc rmp->mp_flags &= ~(VFS_CALL | NEW_PARENT);
329433d6423SLionel Sambuc
330433d6423SLionel Sambuc if (rmp->mp_flags & UNPAUSED)
331433d6423SLionel Sambuc panic("handle_vfs_reply: UNPAUSED set on entry: %d", call_nr);
332433d6423SLionel Sambuc
333433d6423SLionel Sambuc /* Call-specific handler code */
334433d6423SLionel Sambuc switch (call_nr) {
335433d6423SLionel Sambuc case VFS_PM_SETUID_REPLY:
336433d6423SLionel Sambuc case VFS_PM_SETGID_REPLY:
337433d6423SLionel Sambuc case VFS_PM_SETGROUPS_REPLY:
338433d6423SLionel Sambuc /* Wake up the original caller */
339433d6423SLionel Sambuc reply(rmp-mproc, OK);
340433d6423SLionel Sambuc
341433d6423SLionel Sambuc break;
342433d6423SLionel Sambuc
343433d6423SLionel Sambuc case VFS_PM_SETSID_REPLY:
344433d6423SLionel Sambuc /* Wake up the original caller */
345433d6423SLionel Sambuc reply(rmp-mproc, rmp->mp_procgrp);
346433d6423SLionel Sambuc
347433d6423SLionel Sambuc break;
348433d6423SLionel Sambuc
349433d6423SLionel Sambuc case VFS_PM_EXEC_REPLY:
350433d6423SLionel Sambuc exec_restart(rmp, m_in.VFS_PM_STATUS, (vir_bytes)m_in.VFS_PM_PC,
351433d6423SLionel Sambuc (vir_bytes)m_in.VFS_PM_NEWSP,
352433d6423SLionel Sambuc (vir_bytes)m_in.VFS_PM_NEWPS_STR);
353433d6423SLionel Sambuc
354433d6423SLionel Sambuc break;
355433d6423SLionel Sambuc
356433d6423SLionel Sambuc case VFS_PM_CORE_REPLY:
357433d6423SLionel Sambuc if (m_in.VFS_PM_STATUS == OK)
358433d6423SLionel Sambuc rmp->mp_sigstatus |= WCOREFLAG;
359433d6423SLionel Sambuc
360910831cbSDavid van Moolenbroek /* FALLTHROUGH */
361910831cbSDavid van Moolenbroek case VFS_PM_EXIT_REPLY:
362910831cbSDavid van Moolenbroek assert(rmp->mp_flags & EXITING);
363433d6423SLionel Sambuc
364910831cbSDavid van Moolenbroek /* Publish the exit event. Continue exiting the process after that. */
365910831cbSDavid van Moolenbroek publish_event(rmp);
366910831cbSDavid van Moolenbroek
367910831cbSDavid van Moolenbroek return; /* do not take the default action */
368433d6423SLionel Sambuc
369433d6423SLionel Sambuc case VFS_PM_FORK_REPLY:
370433d6423SLionel Sambuc /* Schedule the newly created process ... */
371433d6423SLionel Sambuc r = OK;
372433d6423SLionel Sambuc if (rmp->mp_scheduler != KERNEL && rmp->mp_scheduler != NONE) {
373433d6423SLionel Sambuc r = sched_start_user(rmp->mp_scheduler, rmp);
374433d6423SLionel Sambuc }
375433d6423SLionel Sambuc
376433d6423SLionel Sambuc /* If scheduling the process failed, we want to tear down the process
377433d6423SLionel Sambuc * and fail the fork */
378433d6423SLionel Sambuc if (r != OK) {
379433d6423SLionel Sambuc /* Tear down the newly created process */
380433d6423SLionel Sambuc rmp->mp_scheduler = NONE; /* don't try to stop scheduling */
381433d6423SLionel Sambuc exit_proc(rmp, -1, FALSE /*dump_core*/);
382433d6423SLionel Sambuc
383433d6423SLionel Sambuc /* Wake up the parent with a failed fork (unless dead) */
384433d6423SLionel Sambuc if (!new_parent)
385433d6423SLionel Sambuc reply(rmp->mp_parent, -1);
386433d6423SLionel Sambuc }
387433d6423SLionel Sambuc else {
388433d6423SLionel Sambuc /* Wake up the child */
389433d6423SLionel Sambuc reply(proc_n, OK);
390433d6423SLionel Sambuc
391433d6423SLionel Sambuc /* Wake up the parent, unless the parent is already dead */
392433d6423SLionel Sambuc if (!new_parent)
393433d6423SLionel Sambuc reply(rmp->mp_parent, rmp->mp_pid);
394433d6423SLionel Sambuc }
395433d6423SLionel Sambuc
396433d6423SLionel Sambuc break;
397433d6423SLionel Sambuc
398433d6423SLionel Sambuc case VFS_PM_SRV_FORK_REPLY:
399433d6423SLionel Sambuc /* Nothing to do */
400433d6423SLionel Sambuc
401433d6423SLionel Sambuc break;
402433d6423SLionel Sambuc
403433d6423SLionel Sambuc case VFS_PM_UNPAUSE_REPLY:
404433d6423SLionel Sambuc /* The target process must always be stopped while unpausing; otherwise
405433d6423SLionel Sambuc * it could just end up pausing itself on a new call afterwards.
406433d6423SLionel Sambuc */
407433d6423SLionel Sambuc assert(rmp->mp_flags & PROC_STOPPED);
408433d6423SLionel Sambuc
409433d6423SLionel Sambuc /* Process is now unpaused */
410433d6423SLionel Sambuc rmp->mp_flags |= UNPAUSED;
411433d6423SLionel Sambuc
412910831cbSDavid van Moolenbroek /* Publish the signal event. Continue with signals only after that. */
413910831cbSDavid van Moolenbroek publish_event(rmp);
414910831cbSDavid van Moolenbroek
415910831cbSDavid van Moolenbroek return; /* do not take the default action */
416433d6423SLionel Sambuc
417433d6423SLionel Sambuc default:
418433d6423SLionel Sambuc panic("handle_vfs_reply: unknown reply code: %d", call_nr);
419433d6423SLionel Sambuc }
420433d6423SLionel Sambuc
421433d6423SLionel Sambuc /* Now that the process is idle again, look at pending signals */
422433d6423SLionel Sambuc if ((rmp->mp_flags & (IN_USE | EXITING)) == IN_USE)
423433d6423SLionel Sambuc restart_sigs(rmp);
424433d6423SLionel Sambuc }
425