1 /* This file contains the main program of the process manager and some related
2 * procedures. When MINIX starts up, the kernel runs for a little while,
3 * initializing itself and its tasks, and then it runs PM and FS. Both PM
4 * and FS initialize themselves as far as they can. PM asks the kernel for
5 * all free memory and starts serving requests.
7 * The entry points into this file are:
8 * main: starts PM running
9 * setreply: set the reply to be sent to process making an PM system call
13 #include <minix/keymap.h>
14 #include <minix/callnr.h>
15 #include <minix/com.h>
16 #include <minix/endpoint.h>
17 #include <minix/minlib.h>
18 #include <minix/type.h>
22 #include <sys/resource.h>
23 #include <sys/utsname.h>
25 #include <archconst.h>
26 #include <archtypes.h>
31 #include "../../kernel/const.h"
32 #include "../../kernel/config.h"
33 #include "../../kernel/proc.h"
35 #if ENABLE_SYSCALL_STATS
36 EXTERN
unsigned long calls_stats
[NCALLS
];
39 FORWARD
_PROTOTYPE( void get_work
, (void) );
40 FORWARD
_PROTOTYPE( void pm_init
, (void) );
41 FORWARD
_PROTOTYPE( int get_nice_value
, (int queue
) );
42 FORWARD
_PROTOTYPE( void get_mem_chunks
, (struct memory
*mem_chunks
) );
43 FORWARD
_PROTOTYPE( void patch_mem_chunks
, (struct memory
*mem_chunks
,
44 struct mem_map
*map_ptr
) );
45 FORWARD
_PROTOTYPE( void do_x86_vm
, (struct memory mem_chunks
[NR_MEMS
]) );
46 FORWARD
_PROTOTYPE( void send_work
, (void) );
47 FORWARD
_PROTOTYPE( void handle_fs_reply
, (message
*m_ptr
) );
49 #define click_to_round_k(n) \
50 ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
52 /*===========================================================================*
54 *===========================================================================*/
57 /* Main routine of the process manager. */
58 int result
, s
, proc_nr
;
62 pm_init(); /* initialize process manager tables */
64 /* This is PM's main loop- get work and do it, forever and forever. */
66 get_work(); /* wait for an PM system call */
68 /* Check for system notifications first. Special cases. */
72 pm_expire_timers(m_in
.NOTIFY_TIMESTAMP
);
73 result
= SUSPEND
; /* don't reply */
75 case SYS_SIG
: /* signals pending */
76 sigset
= m_in
.NOTIFY_ARG
;
77 if (sigismember(&sigset
, SIGKSIG
)) {
78 (void) ksig_pending();
80 result
= SUSPEND
; /* don't reply */
83 if (who_e
== FS_PROC_NR
)
86 result
= SUSPEND
; /* don't reply */
95 case PM_EXIT_REPLY_TR
:
96 if (who_e
== FS_PROC_NR
)
98 handle_fs_reply(&m_in
);
99 result
= SUSPEND
; /* don't reply */
105 result
= do_allocmem();
108 result
= do_fork_nb();
111 result
= exec_newmem();
114 result
= do_execrestart();
117 result
= do_procstat();
120 result
= do_getprocnr();
123 /* Else, if the system call number is valid, perform the
126 if ((unsigned) call_nr
>= NCALLS
) {
129 #if ENABLE_SYSCALL_STATS
130 calls_stats
[call_nr
]++;
132 result
= (*call_vec
[call_nr
])();
137 /* Send the results back to the user to indicate completion. */
138 if (result
!= SUSPEND
) setreply(who_p
, result
);
140 swap_in(); /* maybe a process can be swapped in? */
142 /* Send out all pending reply messages, including the answer to
143 * the call just made above. The processes must not be swapped out.
145 for (proc_nr
=0, rmp
=mproc
; proc_nr
< NR_PROCS
; proc_nr
++, rmp
++) {
146 /* In the meantime, the process may have been killed by a
147 * signal (e.g. if a lethal pending signal was unblocked)
148 * without the PM realizing it. If the slot is no longer in
149 * use or just a zombie, don't try to reply.
151 if ((rmp
->mp_flags
& (REPLY
| ONSWAP
| IN_USE
| ZOMBIE
)) ==
153 if ((s
=send(rmp
->mp_endpoint
, &rmp
->mp_reply
)) != OK
) {
154 printf("PM can't reply to %d (%s)\n",
155 rmp
->mp_endpoint
, rmp
->mp_name
);
156 panic(__FILE__
, "PM can't reply", NO_NUM
);
158 rmp
->mp_flags
&= ~REPLY
;
165 /*===========================================================================*
167 *===========================================================================*/
168 PRIVATE
void get_work()
170 /* Wait for the next message and extract useful information from it. */
171 if (receive(ANY
, &m_in
) != OK
)
172 panic(__FILE__
,"PM receive error", NO_NUM
);
173 who_e
= m_in
.m_source
; /* who sent the message */
174 if(pm_isokendpt(who_e
, &who_p
) != OK
)
175 panic(__FILE__
, "PM got message from invalid endpoint", who_e
);
176 call_nr
= m_in
.m_type
; /* system call number */
178 /* Process slot of caller. Misuse PM's own process slot if the kernel is
179 * calling. This can happen in case of synchronous alarms (CLOCK) or or
180 * event like pending kernel signals (SYSTEM).
182 mp
= &mproc
[who_p
< 0 ? PM_PROC_NR
: who_p
];
183 if(who_p
>= 0 && mp
->mp_endpoint
!= who_e
) {
184 panic(__FILE__
, "PM endpoint number out of sync with source",
189 /*===========================================================================*
191 *===========================================================================*/
192 PUBLIC
void setreply(proc_nr
, result
)
193 int proc_nr
; /* process to reply to */
194 int result
; /* result of call (usually OK or error #) */
196 /* Fill in a reply message to be sent later to a user process. System calls
197 * may occasionally fill in other fields, this is only for the main return
198 * value, and for setting the "must send reply" flag.
200 register struct mproc
*rmp
= &mproc
[proc_nr
];
202 if(proc_nr
< 0 || proc_nr
>= NR_PROCS
)
203 panic(__FILE__
,"setreply arg out of range", proc_nr
);
205 rmp
->mp_reply
.reply_res
= result
;
206 rmp
->mp_flags
|= REPLY
; /* reply pending */
208 if (rmp
->mp_flags
& ONSWAP
)
209 swap_inqueue(rmp
); /* must swap this process back in */
212 /*===========================================================================*
214 *===========================================================================*/
215 PRIVATE
void pm_init()
217 /* Initialize the process manager.
218 * Memory use info is collected from the boot monitor, the kernel, and
219 * all processes compiled into the system image. Initially this information
220 * is put into an array mem_chunks. Elements of mem_chunks are struct memory,
221 * and hold base, size pairs in units of clicks. This array is small, there
222 * should be no more than 8 chunks. After the array of chunks has been built
223 * the contents are used to initialize the hole list. Space for the hole list
224 * is reserved as an array with twice as many elements as the maximum number
225 * of processes allowed. It is managed as a linked list, and elements of the
226 * array are struct hole, which, in addition to storage for a base and size in
227 * click units also contain space for a link, a pointer to another element.
230 static struct boot_image image
[NR_BOOT_PROCS
];
231 register struct boot_image
*ip
;
232 static char core_sigs
[] = { SIGQUIT
, SIGILL
, SIGTRAP
, SIGABRT
,
233 SIGEMT
, SIGFPE
, SIGUSR1
, SIGSEGV
, SIGUSR2
};
234 static char ign_sigs
[] = { SIGCHLD
, SIGWINCH
, SIGCONT
};
235 static char mess_sigs
[] = { SIGTERM
, SIGHUP
, SIGABRT
, SIGQUIT
};
236 register struct mproc
*rmp
;
237 register char *sig_ptr
;
238 phys_clicks total_clicks
, minix_clicks
, free_clicks
;
240 struct mem_map mem_map
[NR_LOCAL_SEGS
];
241 struct memory mem_chunks
[NR_MEMS
];
243 /* Initialize process table, including timers. */
244 for (rmp
=&mproc
[0]; rmp
<&mproc
[NR_PROCS
]; rmp
++) {
245 tmr_inittimer(&rmp
->mp_timer
);
247 rmp
->mp_fs_call
= PM_IDLE
;
248 rmp
->mp_fs_call2
= PM_IDLE
;
251 /* Build the set of signals which cause core dumps, and the set of signals
252 * that are by default ignored.
254 sigemptyset(&core_sset
);
255 for (sig_ptr
= core_sigs
; sig_ptr
< core_sigs
+sizeof(core_sigs
); sig_ptr
++)
256 sigaddset(&core_sset
, *sig_ptr
);
257 sigemptyset(&ign_sset
);
258 for (sig_ptr
= ign_sigs
; sig_ptr
< ign_sigs
+sizeof(ign_sigs
); sig_ptr
++)
259 sigaddset(&ign_sset
, *sig_ptr
);
261 /* Obtain a copy of the boot monitor parameters and the kernel info struct.
262 * Parse the list of free memory chunks. This list is what the boot monitor
263 * reported, but it must be corrected for the kernel and system processes.
265 if ((s
=sys_getmonparams(monitor_params
, sizeof(monitor_params
))) != OK
)
266 panic(__FILE__
,"get monitor params failed",s
);
267 get_mem_chunks(mem_chunks
);
268 if ((s
=sys_getkinfo(&kinfo
)) != OK
)
269 panic(__FILE__
,"get kernel info failed",s
);
271 /* Get the memory map of the kernel to see how much memory it uses. */
272 if ((s
=get_mem_map(SYSTASK
, mem_map
)) != OK
)
273 panic(__FILE__
,"couldn't get memory map of SYSTASK",s
);
274 minix_clicks
= (mem_map
[S
].mem_phys
+mem_map
[S
].mem_len
)-mem_map
[T
].mem_phys
;
275 patch_mem_chunks(mem_chunks
, mem_map
);
277 /* Initialize PM's process table. Request a copy of the system image table
278 * that is defined at the kernel level to see which slots to fill in.
280 if (OK
!= (s
=sys_getimage(image
)))
281 panic(__FILE__
,"couldn't get image table: %d\n", s
);
282 procs_in_use
= 0; /* start populating table */
283 for (ip
= &image
[0]; ip
< &image
[NR_BOOT_PROCS
]; ip
++) {
284 if (ip
->proc_nr
>= 0) { /* task have negative nrs */
285 procs_in_use
+= 1; /* found user process */
287 /* Set process details found in the image table. */
288 rmp
= &mproc
[ip
->proc_nr
];
289 strncpy(rmp
->mp_name
, ip
->proc_name
, PROC_NAME_LEN
);
290 rmp
->mp_parent
= RS_PROC_NR
;
291 rmp
->mp_nice
= get_nice_value(ip
->priority
);
292 sigemptyset(&rmp
->mp_sig2mess
);
293 sigemptyset(&rmp
->mp_ignore
);
294 sigemptyset(&rmp
->mp_sigmask
);
295 sigemptyset(&rmp
->mp_catch
);
296 if (ip
->proc_nr
== INIT_PROC_NR
) { /* user process */
297 rmp
->mp_procgrp
= rmp
->mp_pid
= INIT_PID
;
298 rmp
->mp_flags
|= IN_USE
;
300 else { /* system process */
301 rmp
->mp_pid
= get_free_pid();
302 rmp
->mp_flags
|= IN_USE
| DONT_SWAP
| PRIV_PROC
;
303 for (sig_ptr
= mess_sigs
;
304 sig_ptr
< mess_sigs
+sizeof(mess_sigs
);
306 sigaddset(&rmp
->mp_sig2mess
, *sig_ptr
);
309 /* Get kernel endpoint identifier. */
310 rmp
->mp_endpoint
= ip
->endpoint
;
312 /* Get memory map for this process from the kernel. */
313 if ((s
=get_mem_map(ip
->proc_nr
, rmp
->mp_seg
)) != OK
)
314 panic(__FILE__
,"couldn't get process entry",s
);
315 if (rmp
->mp_seg
[T
].mem_len
!= 0) rmp
->mp_flags
|= SEPARATE
;
316 minix_clicks
+= rmp
->mp_seg
[S
].mem_phys
+
317 rmp
->mp_seg
[S
].mem_len
- rmp
->mp_seg
[T
].mem_phys
;
318 patch_mem_chunks(mem_chunks
, rmp
->mp_seg
);
320 /* Tell FS about this system process. */
321 mess
.PR_SLOT
= ip
->proc_nr
;
322 mess
.PR_PID
= rmp
->mp_pid
;
323 mess
.PR_ENDPT
= rmp
->mp_endpoint
;
324 if (OK
!= (s
=send(FS_PROC_NR
, &mess
)))
325 panic(__FILE__
,"can't sync up with FS", s
);
329 /* Override some details. INIT, PM, FS and RS are somewhat special. */
330 mproc
[PM_PROC_NR
].mp_pid
= PM_PID
; /* PM has magic pid */
331 mproc
[RS_PROC_NR
].mp_parent
= INIT_PROC_NR
; /* INIT is root */
332 sigfillset(&mproc
[PM_PROC_NR
].mp_ignore
); /* guard against signals */
334 /* Tell FS that no more system processes follow and synchronize. */
335 mess
.PR_ENDPT
= NONE
;
336 if (sendrec(FS_PROC_NR
, &mess
) != OK
|| mess
.m_type
!= OK
)
337 panic(__FILE__
,"can't sync up with FS", NO_NUM
);
340 /* Possibly we must correct the memory chunks for the boot device. */
341 if (kinfo
.bootdev_size
> 0) {
342 mem_map
[T
].mem_phys
= kinfo
.bootdev_base
>> CLICK_SHIFT
;
343 mem_map
[T
].mem_len
= 0;
344 mem_map
[D
].mem_len
= (kinfo
.bootdev_size
+CLICK_SIZE
-1) >> CLICK_SHIFT
;
345 patch_mem_chunks(mem_chunks
, mem_map
);
347 #endif /* ENABLE_BOOTDEV */
349 /* Withhold some memory from x86 VM */
350 do_x86_vm(mem_chunks
);
352 /* Initialize tables to all physical memory and print memory information. */
353 printf("Physical memory:");
354 mem_init(mem_chunks
, &free_clicks
);
355 total_clicks
= minix_clicks
+ free_clicks
;
356 printf(" total %u KB,", click_to_round_k(total_clicks
));
357 printf(" system %u KB,", click_to_round_k(minix_clicks
));
358 printf(" free %u KB.\n", click_to_round_k(free_clicks
));
360 uts_val
.machine
[0] = 'i';
361 strcpy(uts_val
.machine
+ 1, itoa(getprocessor()));
365 /*===========================================================================*
367 *===========================================================================*/
368 PRIVATE
int get_nice_value(queue
)
369 int queue
; /* store mem chunks here */
371 /* Processes in the boot image have a priority assigned. The PM doesn't know
372 * about priorities, but uses 'nice' values instead. The priority is between
373 * MIN_USER_Q and MAX_USER_Q. We have to scale between PRIO_MIN and PRIO_MAX.
375 int nice_val
= (queue
- USER_Q
) * (PRIO_MAX
-PRIO_MIN
+1) /
376 (MIN_USER_Q
-MAX_USER_Q
+1);
377 if (nice_val
> PRIO_MAX
) nice_val
= PRIO_MAX
; /* shouldn't happen */
378 if (nice_val
< PRIO_MIN
) nice_val
= PRIO_MIN
; /* shouldn't happen */
382 /*===========================================================================*
384 *===========================================================================*/
385 PRIVATE
void get_mem_chunks(mem_chunks
)
386 struct memory
*mem_chunks
; /* store mem chunks here */
388 /* Initialize the free memory list from the 'memory' boot variable. Translate
389 * the byte offsets and sizes in this list to clicks, properly truncated.
391 long base
, size
, limit
;
395 /* Obtain and parse memory from system environment. */
396 if(env_memory_parse(mem_chunks
, NR_MEMS
) != OK
)
397 panic(__FILE__
,"couldn't obtain memory chunks", NO_NUM
);
399 /* Round physical memory to clicks. */
400 for (i
= 0; i
< NR_MEMS
; i
++) {
401 memp
= &mem_chunks
[i
]; /* next mem chunk is stored here */
402 base
= mem_chunks
[i
].base
;
403 size
= mem_chunks
[i
].size
;
405 base
= (base
+ CLICK_SIZE
-1) & ~(long)(CLICK_SIZE
-1);
406 limit
&= ~(long)(CLICK_SIZE
-1);
408 memp
->base
= memp
->size
= 0;
410 memp
->base
= base
>> CLICK_SHIFT
;
411 memp
->size
= (limit
- base
) >> CLICK_SHIFT
;
416 /*===========================================================================*
418 *===========================================================================*/
419 PRIVATE
void patch_mem_chunks(mem_chunks
, map_ptr
)
420 struct memory
*mem_chunks
; /* store mem chunks here */
421 struct mem_map
*map_ptr
; /* memory to remove */
423 /* Remove server memory from the free memory list. The boot monitor
424 * promises to put processes at the start of memory chunks. The
425 * tasks all use same base address, so only the first task changes
426 * the memory lists. The servers and init have their own memory
427 * spaces and their memory will be removed from the list.
430 for (memp
= mem_chunks
; memp
< &mem_chunks
[NR_MEMS
]; memp
++) {
431 if (memp
->base
== map_ptr
[T
].mem_phys
) {
432 memp
->base
+= map_ptr
[T
].mem_len
+ map_ptr
[S
].mem_vir
;
433 memp
->size
-= map_ptr
[T
].mem_len
+ map_ptr
[S
].mem_vir
;
437 if (memp
>= &mem_chunks
[NR_MEMS
])
439 panic(__FILE__
,"patch_mem_chunks: can't find map in mem_chunks, start",
440 map_ptr
[T
].mem_phys
);
444 #define PAGE_SIZE 4096
445 #define PAGE_TABLE_COVER (1024*PAGE_SIZE)
446 /*=========================================================================*
448 *=========================================================================*/
449 PRIVATE
void do_x86_vm(mem_chunks
)
450 struct memory mem_chunks
[NR_MEMS
];
452 phys_bytes high
, bytes
;
453 phys_clicks clicks
, base_click
;
457 /* Compute the highest memory location */
459 for (i
= 0; i
<NR_MEMS
; i
++)
461 if (mem_chunks
[i
].size
== 0)
463 if (mem_chunks
[i
].base
+ mem_chunks
[i
].size
> high
)
464 high
= mem_chunks
[i
].base
+ mem_chunks
[i
].size
;
467 high
<<= CLICK_SHIFT
;
469 printf("do_x86_vm: found high 0x%x\n", high
);
472 /* The number of pages we need is one for the page directory, enough
473 * page tables to cover the memory, and one page for alignement.
475 pages
= 1 + (high
+ PAGE_TABLE_COVER
-1)/PAGE_TABLE_COVER
+ 1;
476 bytes
= pages
*PAGE_SIZE
;
477 clicks
= (bytes
+ CLICK_SIZE
-1) >> CLICK_SHIFT
;
480 printf("do_x86_vm: need %d pages\n", pages
);
481 printf("do_x86_vm: need %d bytes\n", bytes
);
482 printf("do_x86_vm: need %d clicks\n", clicks
);
485 for (i
= 0; i
<NR_MEMS
; i
++)
487 if (mem_chunks
[i
].size
<= clicks
)
492 panic("PM", "not enough memory for VM page tables?", NO_NUM
);
493 base_click
= mem_chunks
[i
].base
;
494 mem_chunks
[i
].base
+= clicks
;
495 mem_chunks
[i
].size
-= clicks
;
498 printf("do_x86_vm: using 0x%x clicks @ 0x%x\n", clicks
, base_click
);
500 r
= sys_vm_setbuf(base_click
<< CLICK_SHIFT
, clicks
<< CLICK_SHIFT
,
503 printf("do_x86_vm: sys_vm_setbuf failed: %d\n", r
);
506 /*=========================================================================*
508 *=========================================================================*/
509 PRIVATE
void send_work()
516 for (rmp
= mproc
; rmp
< &mproc
[NR_PROCS
]; rmp
++)
518 call
= rmp
->mp_fs_call
;
520 call
= rmp
->mp_fs_call2
;
527 m
.PM_STIME_TIME
= boottime
;
529 /* FS does not reply */
530 rmp
->mp_fs_call
= PM_IDLE
;
532 /* Wakeup the original caller */
533 setreply(rmp
-mproc
, OK
);
538 m
.PM_SETSID_PROC
= rmp
->mp_endpoint
;
540 /* FS does not reply */
541 rmp
->mp_fs_call
= PM_IDLE
;
543 /* Wakeup the original caller */
544 setreply(rmp
-mproc
, rmp
->mp_procgrp
);
549 m
.PM_SETGID_PROC
= rmp
->mp_endpoint
;
550 m
.PM_SETGID_EGID
= rmp
->mp_effgid
;
551 m
.PM_SETGID_RGID
= rmp
->mp_realgid
;
553 /* FS does not reply */
554 rmp
->mp_fs_call
= PM_IDLE
;
556 /* Wakeup the original caller */
557 setreply(rmp
-mproc
, OK
);
562 m
.PM_SETUID_PROC
= rmp
->mp_endpoint
;
563 m
.PM_SETUID_EGID
= rmp
->mp_effuid
;
564 m
.PM_SETUID_RGID
= rmp
->mp_realuid
;
566 /* FS does not reply */
567 rmp
->mp_fs_call
= PM_IDLE
;
569 /* Wakeup the original caller */
570 setreply(rmp
-mproc
, OK
);
576 struct mproc
*parent_mp
;
578 parent_p
= rmp
->mp_parent
;
579 parent_mp
= &mproc
[parent_p
];
582 m
.PM_FORK_PPROC
= parent_mp
->mp_endpoint
;
583 m
.PM_FORK_CPROC
= rmp
->mp_endpoint
;
584 m
.PM_FORK_CPID
= rmp
->mp_pid
;
586 /* FS does not reply */
587 rmp
->mp_fs_call
= PM_IDLE
;
589 /* Wakeup the newly created process */
590 setreply(rmp
-mproc
, OK
);
592 /* Wakeup the parent */
593 setreply(parent_mp
-mproc
, rmp
->mp_pid
);
600 m
.PM_EXIT_PROC
= rmp
->mp_endpoint
;
602 /* Mark the process as busy */
603 rmp
->mp_fs_call
= PM_BUSY
;
609 m
.PM_UNPAUSE_PROC
= rmp
->mp_endpoint
;
611 /* FS does not reply */
612 rmp
->mp_fs_call2
= PM_IDLE
;
614 /* Ask the kernel to deliver the signal */
615 r
= sys_sigsend(rmp
->mp_endpoint
,
618 panic(__FILE__
,"sys_sigsend failed",r
);
624 m
.PM_UNPAUSE_PROC
= rmp
->mp_endpoint
;
626 /* FS does not reply */
627 rmp
->mp_fs_call
= PM_IDLE
;
633 m
.PM_EXEC_PROC
= rmp
->mp_endpoint
;
634 m
.PM_EXEC_PATH
= rmp
->mp_exec_path
;
635 m
.PM_EXEC_PATH_LEN
= rmp
->mp_exec_path_len
;
636 m
.PM_EXEC_FRAME
= rmp
->mp_exec_frame
;
637 m
.PM_EXEC_FRAME_LEN
= rmp
->mp_exec_frame_len
;
639 /* Mark the process as busy */
640 rmp
->mp_fs_call
= PM_BUSY
;
647 struct mproc
*parent_mp
;
649 parent_p
= rmp
->mp_parent
;
650 parent_mp
= &mproc
[parent_p
];
653 m
.PM_FORK_PPROC
= parent_mp
->mp_endpoint
;
654 m
.PM_FORK_CPROC
= rmp
->mp_endpoint
;
655 m
.PM_FORK_CPID
= rmp
->mp_pid
;
657 /* FS does not reply */
658 rmp
->mp_fs_call
= PM_IDLE
;
665 m
.PM_CORE_PROC
= rmp
->mp_endpoint
;
666 m
.PM_CORE_SEGPTR
= (char *)rmp
->mp_seg
;
668 /* Mark the process as busy */
669 rmp
->mp_fs_call
= PM_BUSY
;
674 printf("send_work: should report call 0x%x to FS\n",
680 if (m
.m_type
!= PM_IDLE
)
682 if (rmp
->mp_fs_call
== PM_IDLE
&&
683 rmp
->mp_fs_call2
== PM_IDLE
&&
684 (rmp
->mp_flags
& PM_SIG_PENDING
))
686 rmp
->mp_flags
&= ~PM_SIG_PENDING
;
688 if (!(rmp
->mp_flags
& PM_SIG_PENDING
))
690 /* Allow the process to be scheduled */
691 sys_nice(rmp
->mp_endpoint
, rmp
->mp_nice
);
695 else if (report_reboot
)
698 report_reboot
= FALSE
;
700 r
= send(FS_PROC_NR
, &m
);
701 if (r
!= OK
) panic("pm", "send_work: send failed", r
);
704 PRIVATE
void handle_fs_reply(m_ptr
)
707 int r
, proc_e
, proc_n
;
710 switch(m_ptr
->m_type
)
713 case PM_EXIT_REPLY_TR
:
714 proc_e
= m_ptr
->PM_EXIT_PROC
;
715 if (pm_isokendpt(proc_e
, &proc_n
) != OK
)
718 "PM_EXIT_REPLY: got bad endpoint from FS",
723 /* Call is finished */
724 rmp
->mp_fs_call
= PM_IDLE
;
726 if (!(rmp
->mp_flags
& PRIV_PROC
))
728 /* destroy the (user) process */
729 if((r
=sys_exit(proc_e
)) != OK
)
732 "PM_EXIT_REPLY: sys_exit failed", r
);
736 /* Release the memory occupied by the child. */
737 if (find_share(rmp
, rmp
->mp_ino
, rmp
->mp_dev
,
738 rmp
->mp_ctime
) == NULL
) {
739 /* No other process shares the text segment,
742 free_mem(rmp
->mp_seg
[T
].mem_phys
,
743 rmp
->mp_seg
[T
].mem_len
);
745 /* Free the data and stack segments. */
746 free_mem(rmp
->mp_seg
[D
].mem_phys
, rmp
->mp_seg
[S
].mem_vir
+
747 rmp
->mp_seg
[S
].mem_len
- rmp
->mp_seg
[D
].mem_vir
);
749 if (m_ptr
->m_type
== PM_EXIT_REPLY_TR
&&
750 rmp
->mp_parent
!= INIT_PROC_NR
)
752 /* Wake up the parent */
753 mproc
[rmp
->mp_parent
].mp_reply
.reply_trace
= 0;
754 setreply(rmp
->mp_parent
, OK
);
757 /* Clean up if the parent has collected the exit
760 if (rmp
->mp_flags
& TOLD_PARENT
)
765 case PM_REBOOT_REPLY
:
770 /* Ask the kernel to abort. All system services, including
771 * the PM, will get a HARD_STOP notification. Await the
772 * notification in the main loop.
774 code_addr
= (vir_bytes
) monitor_code
;
775 code_size
= strlen(monitor_code
) + 1;
776 sys_abort(abort_flag
, PM_PROC_NR
, code_addr
, code_size
);
781 proc_e
= m_ptr
->PM_EXEC_PROC
;
782 if (pm_isokendpt(proc_e
, &proc_n
) != OK
)
785 "PM_EXIT_REPLY: got bad endpoint from FS",
790 /* Call is finished */
791 rmp
->mp_fs_call
= PM_IDLE
;
793 exec_restart(rmp
, m_ptr
->PM_EXEC_STATUS
);
795 if (rmp
->mp_flags
& PM_SIG_PENDING
)
797 printf("handle_fs_reply: restarting signals\n");
798 rmp
->mp_flags
&= ~PM_SIG_PENDING
;
800 if (!(rmp
->mp_flags
& PM_SIG_PENDING
))
802 printf("handle_fs_reply: calling sys_nice\n");
803 /* Allow the process to be scheduled */
804 sys_nice(rmp
->mp_endpoint
, rmp
->mp_nice
);
807 printf("handle_fs_reply: more signals\n");
813 int parent_waiting
, right_child
;
817 proc_e
= m_ptr
->PM_CORE_PROC
;
818 if (pm_isokendpt(proc_e
, &proc_n
) != OK
)
821 "PM_EXIT_REPLY: got bad endpoint from FS",
826 if (m_ptr
->PM_CORE_STATUS
== OK
)
827 rmp
->mp_sigstatus
|= DUMPED
;
829 /* Call is finished */
830 rmp
->mp_fs_call
= PM_IDLE
;
832 p_mp
= &mproc
[rmp
->mp_parent
]; /* process' parent */
833 pidarg
= p_mp
->mp_wpid
; /* who's being waited for? */
834 parent_waiting
= p_mp
->mp_flags
& WAITING
;
835 right_child
= /* child meets one of the 3 tests? */
836 (pidarg
== -1 || pidarg
== rmp
->mp_pid
||
837 -pidarg
== rmp
->mp_procgrp
);
839 if (parent_waiting
&& right_child
) {
840 tell_parent(rmp
); /* tell parent */
842 /* parent not waiting, zombify child */
843 rmp
->mp_flags
&= (IN_USE
|PRIV_PROC
);
844 rmp
->mp_flags
|= ZOMBIE
;
845 /* send parent a "child died" signal */
846 sig_proc(p_mp
, SIGCHLD
);
849 if (!(rmp
->mp_flags
& PRIV_PROC
))
851 /* destroy the (user) process */
852 if((r
=sys_exit(proc_e
)) != OK
)
855 "PM_CORE_REPLY: sys_exit failed", r
);
859 /* Release the memory occupied by the child. */
860 if (find_share(rmp
, rmp
->mp_ino
, rmp
->mp_dev
,
861 rmp
->mp_ctime
) == NULL
) {
862 /* No other process shares the text segment,
865 free_mem(rmp
->mp_seg
[T
].mem_phys
,
866 rmp
->mp_seg
[T
].mem_len
);
868 /* Free the data and stack segments. */
869 free_mem(rmp
->mp_seg
[D
].mem_phys
, rmp
->mp_seg
[S
].mem_vir
+
870 rmp
->mp_seg
[S
].mem_len
- rmp
->mp_seg
[D
].mem_vir
);
872 /* Clean up if the parent has collected the exit
875 if (rmp
->mp_flags
& TOLD_PARENT
)
881 panic(__FILE__
, "handle_fs_reply: unknown reply type",