}
#endif
- /* We're definitely not shutting down. */
- shutdown_started = 0;
-
/* MINIX is now ready. All boot image processes are on the ready queue.
* Return to the assembly code to start running the current process.
*/
register struct proc *rp;
message m;
- /* Show debugging dumps on panics. Make sure that the TTY task is still
- * available to handle them. This is done with help of a non-blocking send.
- * We rely on TTY to call sys_abort() when it is done with the dumps.
- */
- if (how == RBT_PANIC) {
- m.m_type = PANIC_DUMPS;
- if (nb_send(TTY_PROC_NR,&m)==OK) /* don't block if TTY isn't ready */
- return; /* await sys_abort() from TTY */
- }
-
/* Send a signal to all system processes that are still alive to inform
* them that the MINIX kernel is shutting down. A proper shutdown sequence
* should be implemented by a user-space server. This mechanism is useful
send_sig(proc_nr(rp), SIGKSTOP);
}
- /* We're shutting down. Diagnostics may behave differently now. */
- shutdown_started = 1;
-
- /* Notify system processes of the upcoming shutdown and allow them to be
- * scheduled by setting a watchog timer that calls shutdown(). The timer
+ /* Continue after 1 second, to give processes a chance to get scheduled to
+ * do shutdown work. Set a watchog timer to call shutdown(). The timer
* argument passes the shutdown status.
*/
kprintf("MINIX will now be shut down ...\n");
tmr_arg(&shutdown_timer)->ta_int = how;
-
- /* Continue after 1 second, to give processes a chance to get
- * scheduled to do shutdown work.
- */
set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
}
-
/*===========================================================================*
* shutdown *
*===========================================================================*/
}
/* Require a valid source and/ or destination process, unless echoing. */
- if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO)) {
- kprintf("sys_call: invalid src_dst, src_dst %d, caller %d\n",
- src_dst, proc_nr(caller_ptr));
- return(EBADSRCDST); /* invalid process number */
+ if (src_dst != ANY && function != ECHO) {
+ if (! isokprocn(src_dst)) {
+ kprintf("sys_call: invalid src_dst, src_dst %d, caller %d\n",
+ src_dst, proc_nr(caller_ptr));
+ return(EBADSRCDST); /* invalid process number */
+ }
+ if (isemptyn(src_dst)) {
+ kprintf("sys_call: dead src_dst; trap %d, from %d, to %d\n",
+ function, proc_nr(caller_ptr), src_dst);
+ return(EDEADSRCDST);
+ }
}
/* If the call involves a message buffer, i.e., for SEND, RECEIVE, SENDREC,
}
/* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY,
- * verify that the caller is allowed to send to the given destination and
- * that the destination is still alive.
+ * verify that the caller is allowed to send to the given destination.
*/
if (function & CHECK_DST) {
if (! get_sys_bit(priv(caller_ptr)->s_ipc_to, nr_to_id(src_dst))) {
proc_nr(caller_ptr), src_dst);
return(ECALLDENIED); /* call denied by ipc mask */
}
-
- if (isemptyn(src_dst) && !shutdown_started) {
- kprintf("sys_call: dead dest; %d, %d, %d\n",
- function, proc_nr(caller_ptr), src_dst);
- return(EDEADDST); /* cannot send to the dead */
- }
}
/* Now check if the call is known and try to perform the request. The only
* a normal exit), then it must be removed from the message queues.
*/
if (rc->p_rts_flags & SENDING) {
- /* Check all proc slots to see if the exiting process is queued. */
- for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
- if (rp->p_caller_q == NIL_PROC) continue;
- /* Make sure that the exiting process is not on the queue. */
- xpp = &rp->p_caller_q;
- while (*xpp != NIL_PROC) { /* check entire queue */
- if (*xpp == rc) { /* process is on the queue */
- *xpp = (*xpp)->p_q_link; /* replace by next process */
- break;
- }
- xpp = &(*xpp)->p_q_link; /* proceed to next queued */
+ xpp = &proc[rc->p_sendto].p_caller_q; /* destination's queue */
+ while (*xpp != NIL_PROC) { /* check entire queue */
+ if (*xpp == rc) { /* process is on the queue */
+ *xpp = (*xpp)->p_q_link; /* replace by next process */
+ break; /* done, can only send one */
}
+ xpp = &(*xpp)->p_q_link; /* proceed to next queued */
}
}
+ /* Likewise, if another process was sending or receive a message to or from
+ * the exiting process, it must be alerted that process no longer is alive.
+ * Check all processes.
+ */
+ for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
+
+ /* Check if process is receiving from exiting process. */
+ if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom == proc_nr(rc)) {
+ rp->p_reg.retreg = EDEADSRCDST; /* report source died */
+ rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
+ lock_enqueue(rp); /* let process run again */
+ }
+ else if ((rp->p_rts_flags & SENDING) && rp->p_sendto == proc_nr(rc)) {
+ rp->p_reg.retreg = EDEADSRCDST; /* report destination died */
+ rp->p_rts_flags &= ~SENDING; /* no longer sending */
+ lock_enqueue(rp); /* let process run again */
+ }
+ }
+
/* Check the table with IRQ hooks to see if hooks should be released. */
for (i=0; i < NR_IRQ_HOOKS; i++) {
if (irq_hooks[i].proc_nr == proc_nr(rc)) {
PUBLIC struct boot_image image[] = {
/* process nr, pc, flags, qs, queue, stack, traps, ipcto, call, name */
{ IDLE, idle_task, IDL_F, 8, IDLE_Q, IDL_S, 0, 0, 0, "IDLE" },
- { CLOCK,clock_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "CLOCK" },
- { SYSTEM, sys_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "SYSTEM"},
- { HARDWARE, 0, TSK_F, 64, TASK_Q, HRD_S, 0, 0, 0, "KERNEL"},
+ { CLOCK,clock_task, TSK_F, 0, TASK_Q, TSK_S, TSK_T, 0, 0, "CLOCK" },
+ { SYSTEM, sys_task, TSK_F, 0, TASK_Q, TSK_S, TSK_T, 0, 0, "SYSTEM"},
+ { HARDWARE, 0, TSK_F, 0, TASK_Q, HRD_S, 0, 0, 0, "KERNEL"},
{ PM_PROC_NR, 0, SRV_F, 32, 3, 0, SRV_T, SRV_M, PM_C, "pm" },
{ FS_PROC_NR, 0, SRV_F, 32, 4, 0, SRV_T, SRV_M, FS_C, "fs" },
{ RS_PROC_NR, 0, SRV_F, 4, 3, 0, SRV_T, SYS_M, RS_C, "rs" },
{ MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, DRV_M, MEM_C, "memory"},
{ LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
{ DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
- { INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" },
+#if DEAD_CODE
+ ... WARNING: replace ~0 with USR_T / USR_M
+#endif
+ { INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, ~0, ~0, 0, "init" },
};
/* Verify the size of the system image table at compile time. Also verify that
int d;
unsigned long u; /* hold number argument */
int base; /* base of number arg */
- int negative = 0; /* print minus sign */
+ int negative; /* print minus sign */
static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
- char *s = NULL; /* string to be printed */
+ char *s; /* string to be printed */
va_list argp; /* optional arguments */
va_start(argp, fmt); /* init variable arguments */
while((c=*fmt++) != 0) {
if (c == '%') { /* expect format '%key' */
+ negative = 0; /* (re)initialize */
+ s = NULL; /* (re)initialize */
switch(c = *fmt++) { /* determine what to do */
/* Known keys are %d, %u, %x, %s, and %%. This is easily extended
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
- s = NULL; /* reset for next round */
}
else {
kputc(c); /* print and continue */
#define COM1_BASE 0x3F8
#define COM1_THR (COM1_BASE + 0)
-#define LSR_THRE 0x20
+#define LSR_THRE 0x20
#define COM1_LSR (COM1_BASE + 5)
PRIVATE void ser_putc(char c)