diff --git a/include/minix/callnr.h b/include/minix/callnr.h index 5c5520bde..571ddf9db 100755 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -69,7 +69,7 @@ /* MINIX specific calls, e.g., to support system services. */ #define SVRCTL 77 - /* unused */ +#define PROCSTAT 78 /* to PM */ #define GETSYSINFO 79 /* to PM or FS */ #define GETPROCNR 80 /* to PM */ #define DEVCTL 81 /* to FS */ diff --git a/include/minix/com.h b/include/minix/com.h index 5869138b2..ae70ace53 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -58,6 +58,7 @@ */ #define NOTIFY_MESSAGE 0x1000 #define NOTIFY_FROM(p_nr) (NOTIFY_MESSAGE | ((p_nr) + NR_TASKS)) +# define PROC_EVENT NOTIFY_FROM(PM_PROC_NR) /* process status change */ # define SYN_ALARM NOTIFY_FROM(CLOCK) /* synchronous alarm */ # define SYS_SIG NOTIFY_FROM(SYSTEM) /* system signal */ # define HARD_INT NOTIFY_FROM(HARDWARE) /* hardware interrupt */ @@ -489,7 +490,6 @@ *===========================================================================*/ /* Miscellaneous request types and field names, e.g. used by IS server. */ -#define PANIC_DUMPS 97 /* debug dumps at the TTY on RBT_PANIC */ #define FKEY_CONTROL 98 /* control a function key at the TTY */ # define FKEY_REQUEST m2_i1 /* request to perform at TTY */ # define FKEY_MAP 10 /* observe function key */ diff --git a/include/minix/ipc.h b/include/minix/ipc.h index d73acde2d..db03435df 100644 --- a/include/minix/ipc.h +++ b/include/minix/ipc.h @@ -90,15 +90,22 @@ typedef struct { #define sendrec _sendrec #define receive _receive #define send _send -#define nb_receive _nb_receive -#define nb_send _nb_send _PROTOTYPE( int echo, (message *m_ptr) ); _PROTOTYPE( int notify, (int dest) ); _PROTOTYPE( int sendrec, (int src_dest, message *m_ptr) ); _PROTOTYPE( int receive, (int src, message *m_ptr) ); _PROTOTYPE( int send, (int dest, message *m_ptr) ); -_PROTOTYPE( int nb_receive, (int src, message *m_ptr) ); -_PROTOTYPE( int nb_send, (int dest, message *m_ptr) ); + +#define ipc_request _ipc_request +#define ipc_reply _ipc_reply +#define ipc_notify _ipc_notify +#define ipc_select _ipc_select + +_PROTOTYPE( int ipc_request, (int dst, message *m_ptr) ); +_PROTOTYPE( int ipc_reply, (int dst, message *m_ptr) ); +_PROTOTYPE( int ipc_notify, (int dst, long event_set) ); +_PROTOTYPE( int ipc_receive, (int src, long events, message *m_ptr) ); + #endif /* _IPC_H */ diff --git a/include/signal.h b/include/signal.h index 5986f52e7..efc282fb7 100755 --- a/include/signal.h +++ b/include/signal.h @@ -25,6 +25,7 @@ typedef unsigned long sigset_t; #endif #endif +/* Regular signals. */ #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt (DEL) */ #define SIGQUIT 3 /* quit (ASCII FS) */ @@ -42,27 +43,25 @@ typedef unsigned long sigset_t; #define SIGTERM 15 /* software termination signal from kill */ #define SIGEMT 16 /* EMT instruction */ #define SIGCHLD 17 /* child process terminated or stopped */ +#define SIGWINCH 21 /* window size has changed */ /* MINIX specific signals. These signals are not used by user proceses, * but meant to inform system processes, like the PM, about system events. */ -#define SIGKMESS 18 /* new kernel message */ -#define SIGKSIG 19 /* kernel signal pending */ -#define SIGKSTOP 20 /* kernel shutting down */ +#define SIGKMESS 23 /* new kernel message */ +#define SIGKSIG 24 /* kernel signal pending */ +#define SIGKSTOP 25 /* kernel shutting down */ -/* Regular signals. */ -#define SIGWINCH 21 /* window size has changed */ - -#define _NSIG 21 /* number of signals used */ +#define _NSIG 25 /* number of signals used */ /* POSIX requires the following signals to be defined, even if they are * not supported. Here are the definitions, but they are not supported. */ -#define SIGCONT 18 /* continue if stopped */ -#define SIGSTOP 19 /* stop signal */ -#define SIGTSTP 20 /* interactive stop signal */ -#define SIGTTIN 21 /* background process wants to read */ -#define SIGTTOU 22 /* background process wants to write */ +#define SIGCONT 28 /* continue if stopped */ +#define SIGSTOP 29 /* stop signal */ +#define SIGTSTP 30 /* interactive stop signal */ +#define SIGTTIN 31 /* background process wants to read */ +#define SIGTTOU 32 /* background process wants to write */ #ifdef _MINIX #define SIGIOT SIGABRT /* for people who speak PDP-11 */ diff --git a/include/sys/resource.h b/include/sys/resource.h index 6dc5bd869..1b14af4e2 100755 --- a/include/sys/resource.h +++ b/include/sys/resource.h @@ -8,6 +8,9 @@ #define PRIO_MIN -20 #define PRIO_MAX 20 +/* Magic, invalid priority to stop the process. */ +#define PRIO_STOP 76 + #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 diff --git a/include/unistd.h b/include/unistd.h index 69511735c..af796bba1 100755 --- a/include/unistd.h +++ b/include/unistd.h @@ -28,11 +28,13 @@ #ifdef _MINIX /* How to exit the system or stop a server process. */ -#define RBT_HALT 0 -#define RBT_REBOOT 1 +#define RBT_HALT 0 /* shutdown and return to monitor */ +#define RBT_REBOOT 1 /* reboot the system through the monitor */ #define RBT_PANIC 2 /* a server panics */ #define RBT_MONITOR 3 /* let the monitor do this */ #define RBT_RESET 4 /* hard reset the system */ +#define RBT_INVALID 5 /* first invalid reboot flag */ + #define _PM_SEG_FLAG (1L << 30) /* for read() and write() to FS by PM */ #endif @@ -171,6 +173,7 @@ _PROTOTYPE( int ttyslot, (void) ); _PROTOTYPE( int fttyslot, (int _fd) ); _PROTOTYPE( char *crypt, (const char *_key, const char *_salt) ); _PROTOTYPE( int getsysinfo, (int who, int what, void *where) ); +_PROTOTYPE( int getsigset, (sigset_t *sigset) ); _PROTOTYPE( int getprocnr, (void) ); _PROTOTYPE( int getnprocnr, (pid_t pid) ); _PROTOTYPE( int getpprocnr, (void) ); diff --git a/kernel/clock.c b/kernel/clock.c index 6417d1921..3eaed0654 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -133,12 +133,17 @@ PRIVATE void init_clock() /* Initialize the CLOCK's interrupt hook. */ clock_hook.proc_nr_e = CLOCK; - /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz. */ + /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz, and register + * the CLOCK task's interrupt handler to be run on every clock tick. + */ outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */ outb(TIMER0, TIMER_COUNT); /* load timer low byte */ outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */ - put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);/* register handler */ + put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler); enable_irq(&clock_hook); /* ready for clock interrupts */ + + /* Set a watchdog timer to periodically balance the scheduling queues. */ + balance_queues(NULL); /* side-effect sets new timer */ } /*===========================================================================* @@ -146,7 +151,7 @@ PRIVATE void init_clock() *===========================================================================*/ PUBLIC void clock_stop() { -/* Reset the clock to the BIOS rate. (For rebooting) */ +/* Reset the clock to the BIOS rate. (For rebooting.) */ outb(TIMER_MODE, 0x36); outb(TIMER0, 0); outb(TIMER0, 0); diff --git a/kernel/ipc.h b/kernel/ipc.h index 4cef03e25..8bd910428 100644 --- a/kernel/ipc.h +++ b/kernel/ipc.h @@ -7,24 +7,28 @@ #include /* Masks and flags for system calls. */ -#define SYSCALL_FUNC 0x0F /* mask for system call function */ -#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */ -#define NON_BLOCKING 0x10 /* prevent blocking, return error */ +#define SYSCALL_FUNC 0x00FF /* mask for system call function */ +#define SYSCALL_FLAGS 0xFF00 /* mask for system call flags */ +#define NON_BLOCKING 0x0100 /* do not block if target not ready */ /* System call numbers that are passed when trapping to the kernel. The * numbers are carefully defined so that it can easily be seen (based on * the bits that are on) which checks should be done in sys_call(). */ -#define SEND 1 /* 0 0 0 1 : blocking send */ -#define RECEIVE 2 /* 0 0 1 0 : blocking receive */ -#define SENDREC 3 /* 0 0 1 1 : SEND + RECEIVE */ -#define NOTIFY 4 /* 0 1 0 0 : nonblocking notify */ -#define ECHO 8 /* 1 0 0 0 : echo a message */ +#define SEND 1 /* 0000 0001 : blocking send */ +#define RECEIVE 2 /* 0000 0010 : blocking receive */ +#define SENDREC 3 /* 0000 0011 : SEND + RECEIVE */ +#define NOTIFY 4 /* 0000 0100 : nonblocking notify */ +#define ECHO 8 /* 0000 1000 : echo a message */ + +#define IPC_REQUEST 0x10 /* 0001 0000 : blocking request */ +#define IPC_REPLY 0x20 /* 0010 0000 : nonblocking reply */ +#define IPC_NOTIFY 0x40 /* 0100 0000 : nonblocking notification */ +#define IPC_RECEIVE 0x80 /* 1000 0000 : blocking receive */ /* The following bit masks determine what checks that should be done. */ -#define CHECK_PTR 0x0B /* 1 0 1 1 : validate message buffer */ -#define CHECK_DST 0x05 /* 0 1 0 1 : validate message destination */ -#define CHECK_SRC 0x02 /* 0 0 1 0 : validate message source */ -#define CHECK_DEADLOCK 0x03 /* 0 0 1 1 : check for deadlock */ +#define CHECK_PTR 0xBB /* 1011 1011 : validate message buffer */ +#define CHECK_DST 0x55 /* 0101 0101 : validate message destination */ +#define CHECK_DEADLOCK 0x93 /* 1001 0011 : check for deadlock */ #endif /* IPC_H */ diff --git a/kernel/main.c b/kernel/main.c index 275fff8f0..001ec6d70 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -203,11 +203,13 @@ int how; * run their shutdown code, e.g, to synchronize the FS or to let the TTY * switch to the first console. */ +#if DEAD_CODE kprintf("Sending SIGKSTOP to system processes ...\n"); for (rp=BEG_PROC_ADDR; rps_flags & SYS_PROC) && !iskernelp(rp)) send_sig(proc_nr(rp), SIGKSTOP); } +#endif /* 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 diff --git a/kernel/mpx386.s b/kernel/mpx386.s index 3eb8ec315..0b5eee027 100755 --- a/kernel/mpx386.s +++ b/kernel/mpx386.s @@ -358,19 +358,20 @@ _p_s_call: o16 push es o16 push fs o16 push gs - mov dx, ss - mov ds, dx - mov es, dx - incb (_k_reenter) + mov si, ss ! ss is kernel data segment + mov ds, si ! load rest of kernel segments + mov es, si ! kernel does not use fs, gs + incb (_k_reenter) ! increment kernel entry count mov esi, esp ! assumes P_STACKBASE == 0 mov esp, k_stktop xor ebp, ebp ! for stacktrace ! end of inline save ! now set up parameters for sys_call() + push edx ! event set or flags bit map push ebx ! pointer to user message - push eax ! src/dest - push ecx ! SEND/RECEIVE/BOTH - call _sys_call ! sys_call(function, src_dest, m_ptr) + push eax ! source / destination + push ecx ! call number (ipc primitive to use) + call _sys_call ! sys_call(call_nr, src_dst, m_ptr, bit_map) ! caller is now explicitly in proc_ptr mov AXREG(esi), eax ! sys_call MUST PRESERVE si diff --git a/kernel/priv.h b/kernel/priv.h index 04adfbeba..02c1d0ca1 100755 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -43,13 +43,13 @@ struct priv { struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */ reg_t *s_stack_guard; /* stack guard word for kernel tasks */ - int s_nr_io_range; + int s_nr_io_range; /* allowed I/O ports */ struct io_range s_io_tab[NR_IO_RANGE]; - int s_nr_mem_range; + int s_nr_mem_range; /* allowed memory ranges */ struct mem_range s_mem_tab[NR_MEM_RANGE]; - int s_nr_irq; + int s_nr_irq; /* allowed IRQ lines */ int s_irq_tab[NR_IRQ]; }; @@ -57,15 +57,13 @@ struct priv { #define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF)) /* Bits for the system property flags. */ -#define PREEMPTIBLE 0x01 /* kernel tasks are not preemptible */ +#define PREEMPTIBLE 0x02 /* kernel tasks are not preemptible */ #define BILLABLE 0x04 /* some processes are not billable */ -#define SYS_PROC 0x10 /* system processes are privileged */ -#define SENDREC_BUSY 0x20 /* sendrec() in progress */ -#define CHECK_IO_PORT 0x40 /* Check whether an I/O request is allowed */ -#define CHECK_MEM 0x80 /* Check whether a (vm) memory map request is - * allowed - */ -#define CHECK_IRQ 0x100 /* Check whether an IRQ can be used */ + +#define SYS_PROC 0x10 /* system processes have own priv structure */ +#define CHECK_IO_PORT 0x20 /* check if I/O request is allowed */ +#define CHECK_IRQ 0x40 /* check if IRQ can be used */ +#define CHECK_MEM 0x80 /* check if (VM) mem map request is allowed */ /* Magic system structure table addresses. */ #define BEG_PRIV_ADDR (&priv[0]) diff --git a/kernel/proc.c b/kernel/proc.c index 0e8a083dd..286feb473 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -90,10 +90,11 @@ FORWARD _PROTOTYPE( void pick_proc, (void)); /*===========================================================================* * sys_call * *===========================================================================*/ -PUBLIC int sys_call(call_nr, src_dst_e, m_ptr) +PUBLIC int sys_call(call_nr, src_dst_e, m_ptr, bit_map) int call_nr; /* system call number and flags */ int src_dst_e; /* src to receive from or dst to send to */ message *m_ptr; /* pointer to message in the caller's space */ +long bit_map; /* notification event set or flags */ { /* System calls are done by trapping to the kernel with an INT instruction. * The trap is caught and sys_call() is called to send or receive a message @@ -195,7 +196,7 @@ message *m_ptr; /* pointer to message in the caller's space */ switch(function) { case SENDREC: /* A flag is set so that notifications cannot interrupt SENDREC. */ - priv(caller_ptr)->s_flags |= SENDREC_BUSY; + caller_ptr->p_misc_flags |= REPLY_PENDING; /* fall through */ case SEND: result = mini_send(caller_ptr, src_dst_e, m_ptr, flags); @@ -204,7 +205,7 @@ message *m_ptr; /* pointer to message in the caller's space */ } /* fall through for SENDREC */ case RECEIVE: if (function == RECEIVE) - priv(caller_ptr)->s_flags &= ~SENDREC_BUSY; + caller_ptr->p_misc_flags &= ~REPLY_PENDING; result = mini_receive(caller_ptr, src_dst_e, m_ptr, flags); break; case NOTIFY: @@ -353,7 +354,7 @@ unsigned flags; /* system call flags */ if (!(caller_ptr->p_rts_flags & SENDING)) { /* Check if there are pending notifications, except for SENDREC. */ - if (! (priv(caller_ptr)->s_flags & SENDREC_BUSY)) { + if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) { map = &priv(caller_ptr)->s_notify_pending; for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) { @@ -430,9 +431,9 @@ int dst; /* which process to notify */ * can be both sending and receiving during a SENDREC system call. */ if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && - ! (priv(dst_ptr)->s_flags & SENDREC_BUSY) && - (dst_ptr->p_getfrom_e == ANY - || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { + ! (dst_ptr->p_misc_flags & REPLY_PENDING) && + (dst_ptr->p_getfrom_e == ANY || + dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { /* Destination is indeed waiting for a message. Assemble a notification * message and deliver it. Copy from pseudo-source HARDWARE, since the @@ -600,32 +601,17 @@ int *front; /* return: front or back */ * process must be added to one of the scheduling queues to decide where to * insert it. As a side-effect the process' priority may be updated. */ - static struct proc *prev_ptr = NIL_PROC; /* previous without time */ int time_left = (rp->p_ticks_left > 0); /* quantum fully consumed */ - int penalty = 0; /* change in priority */ /* Check whether the process has time left. Otherwise give a new quantum - * and possibly raise the priority. Processes using multiple quantums - * in a row get a lower priority to catch infinite loops in high priority - * processes (system servers and drivers). + * and lower the process' priority, unless the process already is in the + * lowest queue. */ - if ( ! time_left) { /* quantum consumed ? */ + if (! time_left) { /* quantum consumed ? */ rp->p_ticks_left = rp->p_quantum_size; /* give new quantum */ - if (prev_ptr == rp) penalty ++; /* catch infinite loops */ - else penalty --; /* give slow way back */ - prev_ptr = rp; /* store ptr for next */ - } - - /* Determine the new priority of this process. The bounds are determined - * by IDLE's queue and the maximum priority of this process. Kernel task - * and the idle process are never changed in priority. - */ - if (penalty != 0 && ! iskernelp(rp)) { - rp->p_priority += penalty; /* update with penalty */ - if (rp->p_priority < rp->p_max_priority) /* check upper bound */ - rp->p_priority=rp->p_max_priority; - else if (rp->p_priority > IDLE_Q-1) /* check lower bound */ - rp->p_priority = IDLE_Q-1; + if (rp->p_priority < (IDLE_Q-1)) { + rp->p_priority += 1; /* lower priority */ + } } /* If there is time left, the process is added to the front of its queue, @@ -662,6 +648,47 @@ PRIVATE void pick_proc() } } +/*===========================================================================* + * balance_queues * + *===========================================================================*/ +#define Q_BALANCE_TICKS 100 +PUBLIC void balance_queues(tp) +timer_t *tp; /* watchdog timer pointer */ +{ +/* Check entire process table and give all process a higher priority. This + * effectively means giving a new quantum. If a process already is at its + * maximum priority, its quantum will be renewed. + */ + static timer_t queue_timer; /* timer structure to use */ + register struct proc* rp; /* process table pointer */ + clock_t next_period; /* time of next period */ + int ticks_added = 0; /* total time added */ + + for (rp=BEG_PROC_ADDR; rpp_priority > rp->p_max_priority) { /* update priority? */ + if (rp->p_rts_flags == 0) dequeue(rp); /* take off queue */ + ticks_added += rp->p_quantum_size; /* do accounting */ + rp->p_priority -= 1; /* raise priority */ + if (rp->p_rts_flags == 0) enqueue(rp); /* put on queue */ + } + else { + ticks_added += rp->p_quantum_size - rp->p_ticks_left; + rp->p_ticks_left = rp->p_quantum_size; /* give new quantum */ + } + unlock(5); + } + } + kprintf("ticks_added: %d\n", ticks_added); + + /* Now schedule a new watchdog timer to balance the queues again. The + * period depends on the total amount of quantum ticks added. + */ + next_period = MAX(Q_BALANCE_TICKS, ticks_added); /* calculate next */ + set_timer(&queue_timer, get_uptime() + next_period, balance_queues); +} + /*===========================================================================* * lock_send * *===========================================================================*/ @@ -697,7 +724,7 @@ struct proc *rp; /* this process is no longer runnable */ { /* Safe gateway to dequeue() for tasks. */ if (k_reenter >= 0) { - /* We're in an exception or interrupt, so don't lock (and.. + /* We're in an exception or interrupt, so don't lock (and ... * don't unlock). */ dequeue(rp); diff --git a/kernel/proc.h b/kernel/proc.h index 2c57e039d..df4462413 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -28,9 +28,8 @@ struct proc { proc_nr_t p_nr; /* number of this process (for fast access) */ struct priv *p_priv; /* system privileges structure */ - char p_rts_flags; /* SENDING, RECEIVING, etc. */ - - char p_misc_flags; /* Flags that do suspend the process */ + short p_rts_flags; /* process is runnable only if zero */ + short p_misc_flags; /* flags that do suspend the process */ char p_priority; /* current scheduling priority */ char p_max_priority; /* maximum scheduling priority */ @@ -63,15 +62,17 @@ struct proc { /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ #define SLOT_FREE 0x01 /* process slot is free */ #define NO_MAP 0x02 /* keeps unmapped forked child from running */ -#define SENDING 0x04 /* process blocked trying to SEND */ -#define RECEIVING 0x08 /* process blocked trying to RECEIVE */ +#define SENDING 0x04 /* process blocked trying to send */ +#define RECEIVING 0x08 /* process blocked trying to receive */ #define SIGNALED 0x10 /* set when new kernel signal arrives */ #define SIG_PENDING 0x20 /* unready while signal being processed */ #define P_STOP 0x40 /* set when process is being traced */ #define NO_PRIV 0x80 /* keep forked system process from running */ +#define NO_PRIORITY 0x100 /* process has been stopped */ /* Misc flags */ -#define MF_VM 0x01 /* Process uses VM */ +#define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */ +#define MF_VM 0x08 /* process uses VM */ /* Scheduling priorities for p_priority. Values must start at zero (highest * priority) and increment. Priorities of the processes in the boot image diff --git a/kernel/proto.h b/kernel/proto.h index 3bb1f413b..071364ba6 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -24,11 +24,13 @@ _PROTOTYPE( void kprintf, (const char *fmt, ...) ); _PROTOTYPE( void panic, (_CONST char *s, int n) ); /* proc.c */ -_PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) ); +_PROTOTYPE( int sys_call, (int call_nr, int src_dst, + message *m_ptr, long bit_map) ); _PROTOTYPE( int lock_notify, (int src, int dst) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( void lock_enqueue, (struct proc *rp) ); _PROTOTYPE( void lock_dequeue, (struct proc *rp) ); +_PROTOTYPE( void balance_queues, (struct timer *tp) ); #if DEBUG_ENABLE_IPC_WARNINGS _PROTOTYPE( int isokendpt_f, (char *file, int line, int e, int *p, int f)); #define isokendpt_d(e, p, f) isokendpt_f(__FILE__, __LINE__, (e), (p), (f)) diff --git a/kernel/system/do_kill.c b/kernel/system/do_kill.c index 1c6f99c32..eab947d7d 100644 --- a/kernel/system/do_kill.c +++ b/kernel/system/do_kill.c @@ -33,14 +33,8 @@ message *m_ptr; /* pointer to request message */ if (sig_nr > _NSIG) return(EINVAL); if (iskerneln(proc_nr)) return(EPERM); - if (m_ptr->m_source == PM_PROC_NR) { - /* Directly send signal notification to a system process. */ - if (! (priv(proc_addr(proc_nr))->s_flags & SYS_PROC)) return(EPERM); - send_sig(proc_nr, sig_nr); - } else { - /* Set pending signal to be processed by the PM. */ - cause_sig(proc_nr, sig_nr); - } + /* Set pending signal to be processed by the PM. */ + cause_sig(proc_nr, sig_nr); return(OK); } diff --git a/kernel/system/do_nice.c b/kernel/system/do_nice.c index 855e4e067..51430a512 100644 --- a/kernel/system/do_nice.c +++ b/kernel/system/do_nice.c @@ -17,6 +17,7 @@ *===========================================================================*/ PUBLIC int do_nice(message *m_ptr) { +/* Change process priority or stop the process. */ int proc_nr, pri, new_q ; register struct proc *rp; @@ -24,26 +25,36 @@ PUBLIC int do_nice(message *m_ptr) if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return EINVAL; if (iskerneln(proc_nr)) return(EPERM); pri = m_ptr->PR_PRIORITY; - if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL); - - /* The priority is currently between PRIO_MIN and PRIO_MAX. We have to - * scale this between MIN_USER_Q and MAX_USER_Q. - */ - new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / - (PRIO_MAX-PRIO_MIN+1); - if (new_q < MAX_USER_Q) new_q = MAX_USER_Q; /* shouldn't happen */ - if (new_q > MIN_USER_Q) new_q = MIN_USER_Q; /* shouldn't happen */ - - /* Make sure the process is not running while changing its priority; the - * max_priority is the base priority. Put the process back in its new - * queue if it is runnable. - */ rp = proc_addr(proc_nr); - lock_dequeue(rp); - rp->p_max_priority = rp->p_priority = new_q; - if (! rp->p_rts_flags) lock_enqueue(rp); - return(OK); + if (pri == PRIO_STOP) { + + /* Take process off the scheduling queues. */ + lock_dequeue(rp); + rp->p_rts_flags |= NO_PRIORITY; + return(OK); + } + else if (pri >= PRIO_MIN && pri <= PRIO_MAX) { + + /* The value passed in is currently between PRIO_MIN and PRIO_MAX. + * We have to scale this between MIN_USER_Q and MAX_USER_Q to match + * the kernel's scheduling queues. + */ + new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / + (PRIO_MAX-PRIO_MIN+1); + if (new_q < MAX_USER_Q) new_q = MAX_USER_Q; /* shouldn't happen */ + if (new_q > MIN_USER_Q) new_q = MIN_USER_Q; /* shouldn't happen */ + + /* Make sure the process is not running while changing its priority. + * Put the process back in its new queue if it is runnable. + */ + lock_dequeue(rp); + rp->p_max_priority = rp->p_priority = new_q; + if (! rp->p_rts_flags) lock_enqueue(rp); + + return(OK); + } + return(EINVAL); } #endif /* USE_NICE */ diff --git a/kernel/table.c b/kernel/table.c index c4c3ff38d..a5b5a7273 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -81,8 +81,7 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; #define DS_C ~0 #define PM_C ~(c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO) | c(SYS_IRQCTL) | c(SYS_INT86)) #define FS_C (c(SYS_KILL) | c(SYS_VIRCOPY) | c(SYS_VIRVCOPY) | c(SYS_UMAP) | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM)) -#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO)) -#define PCI_C (c(SYS_VIRCOPY) | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO) | c(SYS_PRIVCTL) | c(SYS_GETINFO)) +#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) | c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO)) #define TTY_C (DRV_C | c(SYS_ABORT) | c(SYS_VM_MAP) | c(SYS_IOPENABLE)) #define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP) | \ c(SYS_IOPENABLE)) @@ -90,27 +89,26 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; /* The system image table lists all programs that are part of the boot image. * The order of the entries here MUST agree with the order of the programs * in the boot image and all kernel tasks must come first. - * Each entry provides the process number, flags, quantum size (qs), scheduling + * + * Each entry provides the process number, flags, quantum size, scheduling * queue, allowed traps, ipc mask, and a name for the process table. The * initial program counter and stack size is also provided for kernel tasks. + * + * Note: the quantum size must be positive in all cases! */ 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, 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"}, + { IDLE, idle_task, IDL_F, 8, IDLE_Q, IDL_S, 0, 0, 0, "idle" }, + { CLOCK,clock_task, TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, 0, "clock" }, + { SYSTEM, sys_task, TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, 0, "system"}, + { HARDWARE, 0, TSK_F, 8, 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" }, { DS_PROC_NR, 0, SRV_F, 4, 3, 0, SRV_T, SYS_M, DS_C, "ds" }, { TTY_PROC_NR, 0, SRV_F, 4, 1, 0, SRV_T, SYS_M, TTY_C, "tty" }, - { MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, MEM_C, "memory"}, + { MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, MEM_C, "mem" }, { LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" }, -#if 0 - { DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"}, - { PCI_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, PCI_C, "pci"}, -#endif { INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" }, }; diff --git a/servers/ds/main.c b/servers/ds/main.c index a0770aff0..d90c994cf 100644 --- a/servers/ds/main.c +++ b/servers/ds/main.c @@ -20,6 +20,7 @@ extern int errno; /* error number set by system library */ /* Declare some local functions. */ FORWARD _PROTOTYPE(void init_server, (int argc, char **argv) ); FORWARD _PROTOTYPE(void exit_server, (void) ); +FORWARD _PROTOTYPE(void sig_handler, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_ptr) ); FORWARD _PROTOTYPE(void reply, (int whom, message *m_ptr) ); @@ -46,11 +47,8 @@ PUBLIC int main(int argc, char **argv) get_work(&m); switch (callnr) { - case SYS_SIG: - sigset = (sigset_t) m.NOTIFY_ARG; - if (sigismember(&sigset,SIGTERM) || sigismember(&sigset,SIGKSTOP)) { - exit_server(); - } + case PROC_EVENT: + sig_handler(); continue; case DS_PUBLISH: result = do_publish(&m); @@ -95,6 +93,24 @@ PRIVATE void init_server(int argc, char **argv) report("DS","warning, sigaction() failed", errno); } +/*===========================================================================* + * sig_handler * + *===========================================================================*/ +PRIVATE void sig_handler() +{ +/* Signal handler. */ + sigset_t sigset; + int sig; + + /* Try to obtain signal set from PM. */ + if (getsigset(&sigset) != 0) return; + + /* Check for known signals. */ + if (sigismember(&sigset, SIGTERM)) { + exit_server(); + } +} + /*===========================================================================* * exit_server * *===========================================================================*/ diff --git a/servers/fs/main.c b/servers/fs/main.c index eb6aa36fd..3d34fd35b 100644 --- a/servers/fs/main.c +++ b/servers/fs/main.c @@ -34,8 +34,7 @@ struct super_block; /* proto.h needs to know this */ FORWARD _PROTOTYPE( void fs_init, (void) ); FORWARD _PROTOTYPE( int igetenv, (char *var, int optional) ); FORWARD _PROTOTYPE( void get_work, (void) ); -FORWARD _PROTOTYPE( void load_ram, (void) ); -FORWARD _PROTOTYPE( void load_super, (Dev_t super_dev) ); +FORWARD _PROTOTYPE( void init_root, (void) ); /*===========================================================================* * main * @@ -55,21 +54,15 @@ PUBLIC int main() /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { get_work(); /* sets who and call_nr */ - fp = &fproc[who_p]; /* pointer to proc table struct */ super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ /* Check for special control messages first. */ - if (call_nr == SYS_SIG) { - sigset = m_in.NOTIFY_ARG; - if (sigismember(&sigset, SIGKSTOP)) { - do_sync(); - sys_exit(0); /* never returns */ - } + if (call_nr == PROC_EVENT) { + /* Assume FS got signal. Synchronize, but don't exit. */ + do_sync(); } else if (call_nr == SYN_ALARM) { - /* Not a user request; system has expired one of our timers, - * currently only in use for select(). Check it. - */ + /* Alarm timer expired. Used only for select(). Check it. */ fs_expire_timers(m_in.NOTIFY_TIMESTAMP); } else if ((call_nr & NOTIFY_MESSAGE)) { /* Device notifies us of an event. */ @@ -78,6 +71,7 @@ PUBLIC int main() /* Call the internal function that does the work. */ if (call_nr < 0 || call_nr >= NCALLS) { error = ENOSYS; + /* Not supposed to happen. */ printf("FS, warning illegal %d system call by %d\n", call_nr, who_e); } else if (fp->fp_pid == PID_FREE) { error = ENOSYS; @@ -184,10 +178,7 @@ PUBLIC void reply(whom, result) int whom; /* process to reply to */ int result; /* result of the call (usually OK or error #) */ { -/* Send a reply to a user process. It may fail (if the process has just - * been killed by a signal), so don't check the return code. If the send - * fails, just ignore it. - */ +/* Send a reply to a user process. If the send fails, just ignore it. */ int s; m_out.reply_type = result; s = send(whom, &m_out); @@ -247,8 +238,7 @@ PRIVATE void fs_init() buf_pool(); /* initialize buffer pool */ build_dmap(); /* build device table and map boot driver */ - load_ram(); /* init RAM disk, load if it is root */ - load_super(root_dev); /* load super block for root device */ + init_root(); /* init root device and load super block */ init_select(); /* init select() structures */ /* The root device can now be accessed; set process directories. */ @@ -283,206 +273,37 @@ int optional; } /*===========================================================================* - * load_ram * + * init_root * *===========================================================================*/ -PRIVATE void load_ram(void) +PRIVATE void init_root() { -/* Allocate a RAM disk with size given in the boot parameters. If a RAM disk - * image is given, the copy the entire image device block-by-block to a RAM - * disk with the same size as the image. - * If the root device is not set, the RAM disk will be used as root instead. - */ - register struct buf *bp, *bp1; - u32_t lcount, ram_size_kb; - zone_t zones; - struct super_block *sp, *dsp; - block_t b; - Dev_t image_dev; - static char sbbuf[_MIN_BLOCK_SIZE]; - int block_size_image, block_size_ram, ramfs_block_size; + int bad; + register struct super_block *sp; + register struct inode *rip; int s; - /* Get some boot environment variables. */ - root_dev = igetenv("rootdev", 0); - root_dev = DEV_IMGRD; - image_dev = igetenv("ramimagedev", 0); - ram_size_kb = igetenv("ramsize", 0); - /* Open the root device. */ - if (dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT) != OK) - panic(__FILE__,"Cannot open root device",NO_NUM); - -#if 0 - /* If we must initialize a ram disk, get details from the image device. */ - if (root_dev == DEV_RAM) { - u32_t fsmax, probedev; - - /* If we are running from CD, see if we can find it. */ - if (igetenv("cdproberoot", 1) && (probedev=cdprobe()) != NO_DEV) { - char devnum[10]; - struct sysgetenv env; - - /* If so, this is our new RAM image device. */ - image_dev = probedev; - - /* Tell PM about it, so userland can find out about it - * with sysenv interface. - */ - env.key = "cdproberoot"; - env.keylen = strlen(env.key); - sprintf(devnum, "%d", (int) probedev); - env.val = devnum; - env.vallen = strlen(devnum); - svrctl(MMSETPARAM, &env); - } - - /* Open image device for RAM root. */ - if (dev_open(image_dev, FS_PROC_NR, R_BIT) != OK) - panic(__FILE__,"Cannot open RAM image device", NO_NUM); - - /* Get size of RAM disk image from the super block. */ - sp = &super_block[0]; - sp->s_dev = image_dev; - if (read_super(sp) != OK) - panic(__FILE__,"Bad RAM disk image FS", NO_NUM); - - lcount = sp->s_zones << sp->s_log_zone_size; /* # blks on root dev*/ - - /* Stretch the RAM disk file system to the boot parameters size, but - * no further than the last zone bit map block allows. - */ - if (ram_size_kb*1024 < lcount*sp->s_block_size) - ram_size_kb = lcount*sp->s_block_size/1024; - fsmax = (u32_t) sp->s_zmap_blocks * CHAR_BIT * sp->s_block_size; - fsmax = (fsmax + (sp->s_firstdatazone-1)) << sp->s_log_zone_size; - if (ram_size_kb*1024 > fsmax*sp->s_block_size) - ram_size_kb = fsmax*sp->s_block_size/1024; - } -#endif - - /* Tell RAM driver how big the RAM disk must be. */ - m_out.m_type = DEV_IOCTL; - m_out.PR_ENDPT = FS_PROC_NR; - m_out.DEVICE = RAM_DEV; - m_out.REQUEST = MIOCRAMSIZE; /* I/O control to use */ - m_out.POSITION = (ram_size_kb * 1024); /* request in bytes */ -#if 0 - if ((s=sendrec(MEM_PROC_NR, &m_out)) != OK) - panic("FS","sendrec from MEM failed", s); - else if (m_out.REP_STATUS != OK) { - /* Report and continue, unless RAM disk is required as root FS. */ - if (root_dev != DEV_RAM) { - report("FS","can't set RAM disk size", m_out.REP_STATUS); - return; - } else { - panic(__FILE__,"can't set RAM disk size", m_out.REP_STATUS); - } - } -#endif + root_dev = DEV_IMGRD; + if ((s=dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT)) != OK) + panic(__FILE__,"Cannot open root device", s); #if ENABLE_CACHE2 /* The RAM disk is a second level block cache while not otherwise used. */ init_cache2(ram_size); #endif - /* See if we must load the RAM disk image, otherwise return. */ - if (root_dev != DEV_RAM) - return; - -#if 0 - - /* Copy the blocks one at a time from the image to the RAM disk. */ - printf("Loading RAM disk onto /dev/ram:\33[23CLoaded: 0 KB"); - - inode[0].i_mode = I_BLOCK_SPECIAL; /* temp inode for rahead() */ - inode[0].i_size = LONG_MAX; - inode[0].i_dev = image_dev; - inode[0].i_zone[0] = image_dev; - - block_size_ram = get_block_size(DEV_RAM); - block_size_image = get_block_size(image_dev); - - /* RAM block size has to be a multiple of the root image block - * size to make copying easier. - */ - if (block_size_image % block_size_ram) { - printf("\nram block size: %d image block size: %d\n", - block_size_ram, block_size_image); - panic(__FILE__, "ram disk block size must be a multiple of " - "the image disk block size", NO_NUM); - } - - /* Loading blocks from image device. */ - for (b = 0; b < (block_t) lcount; b++) { - int rb, factor; - bp = rahead(&inode[0], b, (off_t)block_size_image * b, block_size_image); - factor = block_size_image/block_size_ram; - for(rb = 0; rb < factor; rb++) { - bp1 = get_block(root_dev, b * factor + rb, NO_READ); - memcpy(bp1->b_data, bp->b_data + rb * block_size_ram, - (size_t) block_size_ram); - bp1->b_dirt = DIRTY; - put_block(bp1, FULL_DATA_BLOCK); - } - put_block(bp, FULL_DATA_BLOCK); - if (b % 11 == 0) - printf("\b\b\b\b\b\b\b\b\b%6ld KB", ((long) b * block_size_image)/1024L); - } - - /* Commit changes to RAM so dev_io will see it. */ - do_sync(); - - printf("\rRAM disk of %u KB loaded onto /dev/ram.", (unsigned) ram_size_kb); - if (root_dev == DEV_RAM) printf(" Using RAM disk as root FS."); - printf(" \n"); - - /* Invalidate and close the image device. */ - invalidate(image_dev); - dev_close(image_dev); - - /* Resize the RAM disk root file system. */ - if (dev_io(DEV_READ, root_dev, FS_PROC_NR, - sbbuf, SUPER_BLOCK_BYTES, _MIN_BLOCK_SIZE, 0) != _MIN_BLOCK_SIZE) { - printf("WARNING: ramdisk read for resizing failed\n"); - } - dsp = (struct super_block *) sbbuf; - if (dsp->s_magic == SUPER_V3) - ramfs_block_size = dsp->s_block_size; - else - ramfs_block_size = _STATIC_BLOCK_SIZE; - zones = (ram_size_kb * 1024 / ramfs_block_size) >> sp->s_log_zone_size; - - dsp->s_nzones = conv2(sp->s_native, (u16_t) zones); - dsp->s_zones = conv4(sp->s_native, zones); - if (dev_io(DEV_WRITE, root_dev, FS_PROC_NR, - sbbuf, SUPER_BLOCK_BYTES, _MIN_BLOCK_SIZE, 0) != _MIN_BLOCK_SIZE) { - printf("WARNING: ramdisk write for resizing failed\n"); - } -#endif -} - -/*===========================================================================* - * load_super * - *===========================================================================*/ -PRIVATE void load_super(super_dev) -dev_t super_dev; /* place to get superblock from */ -{ - int bad; - register struct super_block *sp; - register struct inode *rip; - /* Initialize the super_block table. */ for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) sp->s_dev = NO_DEV; /* Read in super_block for the root file system. */ sp = &super_block[0]; - sp->s_dev = super_dev; + sp->s_dev = root_dev; /* Check super_block for consistency. */ bad = (read_super(sp) != OK); if (!bad) { - rip = get_inode(super_dev, ROOT_INODE); /* inode for root dir */ + rip = get_inode(root_dev, ROOT_INODE); /* inode for root dir */ if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++; } if (bad) panic(__FILE__,"Invalid root file system", NO_NUM); diff --git a/servers/fs/misc.c b/servers/fs/misc.c index 4b53ef8e4..eafc1c662 100644 --- a/servers/fs/misc.c +++ b/servers/fs/misc.c @@ -432,24 +432,17 @@ PUBLIC int do_exit() /* Invalidate endpoint number for error and sanity checks. */ fp->fp_endpoint = NONE; - /* If a session leader exits then revoke access to its controlling tty from - * all other processes using it. + /* If a session leader exits and it has a controlling tty, then revoke + * access to its controlling tty from all other processes using it. */ - if (!fp->fp_sesldr) { - fp->fp_pid = PID_FREE; - return(OK); /* not a session leader */ - } - fp->fp_sesldr = FALSE; - if (fp->fp_tty == 0) { - fp->fp_pid = PID_FREE; - return(OK); /* no controlling tty */ - } - dev = fp->fp_tty; + if (fp->fp_sesldr && fp->fp_tty != 0) { - for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if (rfp->fp_tty == dev) rfp->fp_tty = 0; + dev = fp->fp_tty; - for (i = 0; i < OPEN_MAX; i++) { + for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { + if (rfp->fp_tty == dev) rfp->fp_tty = 0; + + for (i = 0; i < OPEN_MAX; i++) { if ((rfilp = rfp->fp_filp[i]) == NIL_FILP) continue; if (rfilp->filp_mode == FILP_CLOSED) continue; rip = rfilp->filp_ino; @@ -457,12 +450,12 @@ PUBLIC int do_exit() if ((dev_t) rip->i_zone[0] != dev) continue; dev_close(dev); rfilp->filp_mode = FILP_CLOSED; - } + } + } } - /* Mark slot as free. */ + /* Exit done. Mark slot as free. */ fp->fp_pid = PID_FREE; - return(OK); } diff --git a/servers/fs/utility.c b/servers/fs/utility.c index 44c0279d9..afaccdfc5 100644 --- a/servers/fs/utility.c +++ b/servers/fs/utility.c @@ -106,7 +106,7 @@ int num; /* number to go with it */ printf("FS panic (%s): %s ", who, mess); if (num != NO_NUM) printf("%d",num); (void) do_sync(); /* flush everything to the disk */ - sys_exit(1); + sys_exit(SELF); } /*===========================================================================* diff --git a/servers/inet/inet.c b/servers/inet/inet.c index 9f650ba27..4d8b86985 100644 --- a/servers/inet/inet.c +++ b/servers/inet/inet.c @@ -245,7 +245,7 @@ PUBLIC void main() clck_tick(&mq->mq_mess); mq_free(mq); } - else if (mq->mq_mess.m_type == SYS_SIG) + else if (mq->mq_mess.m_type == PROC_EVENT) { /* signaled */ /* probably SIGTERM */ diff --git a/servers/is/dmp.c b/servers/is/dmp.c index bd2a256d9..483a9c51c 100644 --- a/servers/is/dmp.c +++ b/servers/is/dmp.c @@ -12,7 +12,7 @@ /* Define hooks for the debugging dumps. This table maps function keys * onto a specific dump and provides a description for it. */ -#define NHOOKS 19 +#define NHOOKS 18 struct hook_entry { int key; @@ -29,7 +29,6 @@ struct hook_entry { { F9, sched_dmp, "Scheduling queues" }, { F10, kenv_dmp, "Kernel parameters" }, { F11, timing_dmp, "Timing details (if enabled)" }, - { F12, reboot_dmp, "Reboot system after panic." }, { SF1, mproc_dmp, "Process manager process table" }, { SF2, sigaction_dmp, "Signals" }, { SF3, fproc_dmp, "Filesystem process table" }, @@ -83,14 +82,6 @@ PRIVATE char *key_name(int key) return name; } -/*===========================================================================* - * reboot_dmp * - *===========================================================================*/ -PUBLIC void reboot_dmp(void) -{ - if (sys_panic) sys_abort(RBT_HALT); -} - /*===========================================================================* * mapping_dmp * diff --git a/servers/is/main.c b/servers/is/main.c index 07ccea270..37c08a64c 100644 --- a/servers/is/main.c +++ b/servers/is/main.c @@ -18,12 +18,12 @@ message m_in; /* the input message itself */ message m_out; /* the output message used for reply */ int who_e; /* caller's proc number */ int callnr; /* system call number */ -int sys_panic; /* flag to indicate system-wide panic */ extern int errno; /* error number set by system library */ /* Declare some local functions. */ FORWARD _PROTOTYPE(void init_server, (int argc, char **argv) ); +FORWARD _PROTOTYPE(void sig_handler, (void) ); FORWARD _PROTOTYPE(void exit_server, (void) ); FORWARD _PROTOTYPE(void get_work, (void) ); FORWARD _PROTOTYPE(void reply, (int whom, int result) ); @@ -51,16 +51,16 @@ PUBLIC int main(int argc, char **argv) switch (callnr) { case SYS_SIG: - sigset = (sigset_t) m_in.NOTIFY_ARG; - if (sigismember(&sigset,SIGTERM) || sigismember(&sigset,SIGKSTOP)) { - exit_server(); - } - continue; - case PANIC_DUMPS: - printf("Oops ... panic in %d. ", who_e); - printf("Hit F-keys for debug dumps or F12 to shut down.\n"); - sys_panic = TRUE; /* set flag to allow exit */ + printf("got SYS_SIG message\n"); + sigset = m_in.NOTIFY_ARG; + for ( result=0; result< _NSIG; result++) { + if (sigismember(&sigset, result)) + printf("signal %d found\n", result); + } continue; + case PROC_EVENT: + sig_handler(); + continue; case FKEY_PRESSED: result = do_fkey_pressed(&m_in); break; @@ -105,6 +105,23 @@ PRIVATE void init_server(int argc, char **argv) report("IS", "warning, fkey_map failed:", s); } +/*===========================================================================* + * sig_handler * + *===========================================================================*/ +PRIVATE void sig_handler() +{ + sigset_t sigset; + int sig; + + /* Try to obtain signal set from PM. */ + if (getsigset(&sigset) != 0) return; + + /* Check for known signals. */ + if (sigismember(&sigset, SIGTERM)) { + exit_server(); + } +} + /*===========================================================================* * exit_server * *===========================================================================*/ diff --git a/servers/is/proto.h b/servers/is/proto.h index 42767821f..53afeb9a3 100644 --- a/servers/is/proto.h +++ b/servers/is/proto.h @@ -6,7 +6,6 @@ _PROTOTYPE( int main, (int argc, char **argv) ); /* dmp.c */ _PROTOTYPE( int do_fkey_pressed, (message *m) ); _PROTOTYPE( void mapping_dmp, (void) ); -_PROTOTYPE( void reboot_dmp, (void) ); /* dmp_kernel.c */ _PROTOTYPE( void proctab_dmp, (void) ); diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index 796e2f925..8e3cbf9f5 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "mproc.h" #include "param.h" @@ -165,9 +166,15 @@ int exit_status; /* the process' exit status (for parent) */ p_mp->mp_child_utime += t[0] + rmp->mp_child_utime; /* add user time */ p_mp->mp_child_stime += t[1] + rmp->mp_child_stime; /* add system time */ - /* Tell the kernel and FS that the process is no longer runnable. */ - tell_fs(EXIT, proc_nr_e, 0, 0); /* file system can free the proc slot */ - if((r=sys_exit(proc_nr_e)) != OK) + /* Tell the kernel the process is no longer runnable to prevent it from + * being scheduled in between the following steps. Then tell FS that it + * the process has exited and finally, clean up the process at the kernel. + * This order is important so that FS can tell drivers to cancel requests + * such as copying to/ from the exiting process, before it is gone. + */ + sys_nice(proc_nr_e, PRIO_STOP); /* stop the process */ + tell_fs(EXIT, proc_nr_e, 0, 0); /* tell FS to free the slot */ + if((r=sys_exit(proc_nr_e)) != OK) /* destroy the process */ panic(__FILE__,"pm_exit: sys_exit failed", r); /* Pending reply messages for the dead process cannot be delivered. */ diff --git a/servers/pm/glo.h b/servers/pm/glo.h index 6947b12b6..467d1a179 100644 --- a/servers/pm/glo.h +++ b/servers/pm/glo.h @@ -8,7 +8,7 @@ EXTERN struct mproc *mp; /* ptr to 'mproc' slot of current process */ EXTERN int procs_in_use; /* how many processes are marked as IN_USE */ EXTERN char monitor_params[128*sizeof(char *)]; /* boot monitor parameters */ -EXTERN struct kinfo kinfo; /* kernel information */ +EXTERN struct kinfo kinfo; /* kernel information */ /* The parameters of the call are kept here. */ EXTERN message m_in; /* the incoming message itself is kept here. */ diff --git a/servers/pm/main.c b/servers/pm/main.c index ec31baa50..1e01a013d 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -236,12 +236,10 @@ PRIVATE void pm_init() else { /* system process */ rmp->mp_pid = get_free_pid(); rmp->mp_flags |= IN_USE | DONT_SWAP | PRIV_PROC; -#if DEAD_CODE for (sig_ptr = mess_sigs; sig_ptr < mess_sigs+sizeof(mess_sigs); sig_ptr++) sigaddset(&rmp->mp_sig2mess, *sig_ptr); -#endif } /* Get kernel endpoint identifier. */ @@ -270,8 +268,6 @@ PRIVATE void pm_init() mproc[PM_PROC_NR].mp_pid = PM_PID; /* PM has magic pid */ mproc[RS_PROC_NR].mp_parent = INIT_PROC_NR; /* INIT is root */ sigfillset(&mproc[PM_PROC_NR].mp_ignore); /* guard against signals */ - sigfillset(&mproc[FS_PROC_NR].mp_sig2mess); /* forward signals */ - sigfillset(&mproc[TTY_PROC_NR].mp_sig2mess); /* forward signals */ /* Tell FS that no more system processes follow and synchronize. */ mess.PR_ENDPT = NONE; diff --git a/servers/pm/misc.c b/servers/pm/misc.c index 03684b065..b71adfa95 100644 --- a/servers/pm/misc.c +++ b/servers/pm/misc.c @@ -2,12 +2,13 @@ * 31 Mar 2000 * The entry points into this file are: * do_reboot: kill all processes, then reboot system - * do_svrctl: process manager control + * do_procstat: request process status (Jorrit N. Herder) * do_getsysinfo: request copy of PM data structure (Jorrit N. Herder) * do_getprocnr: lookup process slot number (Jorrit N. Herder) * do_allocmem: allocate a chunk of memory (Jorrit N. Herder) * do_freemem: deallocate a chunk of memory (Jorrit N. Herder) * do_getsetpriority: get/set process priority + * do_svrctl: process manager control */ #include "pm.h" @@ -52,6 +53,27 @@ PUBLIC int do_freemem() return(OK); } +/*===========================================================================* + * do_procstat * + *===========================================================================*/ +PUBLIC int do_procstat() +{ + /* For the moment, this is only used to return pending signals to + * system processes that request the PM for their own status. + * + * Future use might include the FS requesting for process status of + * any user process. + */ + if (m_in.stat_nr == SELF) { + mp->mp_reply.sig_set = mp->mp_sigpending; + sigemptyset(&mp->mp_sigpending); + } + else { + return(ENOSYS); + } + return(OK); +} + /*===========================================================================* * do_getsysinfo * *===========================================================================*/ @@ -147,52 +169,42 @@ PUBLIC int do_getprocnr() /*===========================================================================* * do_reboot * *===========================================================================*/ -#define REBOOT_CODE "delay; boot" PUBLIC int do_reboot() { char monitor_code[32*sizeof(char *)]; - int code_len; + vir_bytes code_addr; + int code_size; int abort_flag; + /* Check permission to abort the system. */ if (mp->mp_effuid != SUPER_USER) return(EPERM); - switch (m_in.reboot_flag) { - case RBT_HALT: - case RBT_PANIC: - case RBT_RESET: - abort_flag = m_in.reboot_flag; - break; - case RBT_REBOOT: - code_len = strlen(REBOOT_CODE) + 1; - strncpy(monitor_code, REBOOT_CODE, code_len); - abort_flag = RBT_MONITOR; - break; - case RBT_MONITOR: - code_len = m_in.reboot_strlen + 1; - if (code_len > sizeof(monitor_code)) return(EINVAL); - if (sys_datacopy(who_e, (vir_bytes) m_in.reboot_code, - PM_PROC_NR, (vir_bytes) monitor_code, - (phys_bytes) (code_len)) != OK) return(EFAULT); - if (monitor_code[code_len-1] != 0) return(EINVAL); - abort_flag = RBT_MONITOR; - break; - default: - return(EINVAL); + /* See how the system should be aborted. */ + abort_flag = (unsigned) m_in.reboot_flag; + if (abort_flag >= RBT_INVALID) return(EINVAL); + if (RBT_MONITOR == abort_flag) { + code_addr = (vir_bytes) m_in.reboot_code; + code_size = m_in.reboot_strlen + 1; } /* Order matters here. When FS is told to reboot, it exits all its * processes, and then would be confused if they're exited again by - * SIGKILL. So first kill, then reboot. + * SIGKILL. So first kill, then reboot. */ - check_sig(-1, SIGKILL); /* kill all processes except init */ + printf("check_sig(-1, SIGKILL) ...\n"); + check_sig(-1, SIGKILL); /* kill all users except init */ + printf("stopping init with PRIO_STOP ...\n"); + sys_nice(INIT_PROC_NR, PRIO_STOP); /* stop init, but keep it around */ + printf("tell_fs to sync() ...\n"); tell_fs(REBOOT, 0, 0, 0); /* tell FS to synchronize */ + printf("sys_abort ...\n"); /* Ask the kernel to abort. All system services, including the PM, will * get a HARD_STOP notification. Await the notification in the main loop. */ - sys_abort(abort_flag, PM_PROC_NR, monitor_code, code_len); - return(SUSPEND); /* don't reply to killed process */ + sys_abort(abort_flag, who_e, code_addr, code_size); + return(SUSPEND); /* don't reply to caller */ } /*===========================================================================* diff --git a/servers/pm/param.h b/servers/pm/param.h index 68a9b940b..08e902f82 100644 --- a/servers/pm/param.h +++ b/servers/pm/param.h @@ -21,6 +21,7 @@ #define sig_nsa m1_p1 #define sig_osa m1_p2 #define sig_ret m1_p3 +#define stat_nr m2_i1 #define sig_set m2_l1 #define sig_how m2_i1 #define sig_flags m2_i2 diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 6913e9d89..7a93dbf41 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -57,6 +57,7 @@ _PROTOTYPE( int main, (void) ); /* misc.c */ _PROTOTYPE( int do_reboot, (void) ); +_PROTOTYPE( int do_procstat, (void) ); _PROTOTYPE( int do_getsysinfo, (void) ); _PROTOTYPE( int do_getprocnr, (void) ); _PROTOTYPE( int do_svrctl, (void) ); diff --git a/servers/pm/signal.c b/servers/pm/signal.c index fb4342b4f..fe971f135 100644 --- a/servers/pm/signal.c +++ b/servers/pm/signal.c @@ -37,7 +37,7 @@ FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp) ); FORWARD _PROTOTYPE( void unpause, (int pro) ); -FORWARD _PROTOTYPE( void handle_sig, (int proc_nr, sigset_t sig_map) ); +FORWARD _PROTOTYPE( void handle_ksig, (int proc_nr, sigset_t sig_map) ); FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp) ); /*===========================================================================* @@ -228,7 +228,7 @@ PUBLIC int ksig_pending() int proc_nr_p; if(pm_isokendpt(proc_nr_e, &proc_nr_p) != OK) panic(__FILE__,"sys_getksig strange process", proc_nr_e); - handle_sig(proc_nr_e, sig_map); /* handle the received signal */ + handle_ksig(proc_nr_e, sig_map); /* handle the received signal */ /* If the process still exists to the kernel after the signal * has been handled ... */ @@ -241,9 +241,9 @@ PUBLIC int ksig_pending() } /*===========================================================================* - * handle_sig * + * handle_ksig * *===========================================================================*/ -PRIVATE void handle_sig(proc_nr_e, sig_map) +PRIVATE void handle_ksig(proc_nr_e, sig_map) int proc_nr_e; sigset_t sig_map; { @@ -489,8 +489,10 @@ int signo; /* signal to send to process (1 to _NSIG) */ panic(__FILE__, "sys_sigsend failed", s); } else if (sigismember(&rmp->mp_sig2mess, signo)) { - if (OK != (s=sys_kill(rmp->mp_endpoint,signo))) - panic(__FILE__, "warning, sys_kill failed", s); + + /* Mark event pending in process slot and send notification. */ + sigaddset(&rmp->mp_sigpending, signo); + notify(rmp->mp_endpoint); return; } @@ -536,8 +538,8 @@ int signo; /* signal to send to process (0 to _NSIG) */ /* Return EINVAL for attempts to send SIGKILL to INIT alone. */ if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL); - /* Search the proc table for processes to signal. (See forkexit.c about - * pid magic.) + /* Search the proc table for processes to signal. + * (See forkexit.c aboutpid magic.) */ count = 0; error_code = ESRCH; @@ -551,6 +553,10 @@ int signo; /* signal to send to process (0 to _NSIG) */ if (proc_id == -1 && rmp->mp_pid <= INIT_PID) continue; if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue; + /* Do not kill servers and drivers when broadcasting SIGKILL. */ + if (proc_id == -1 && signo == SIGKILL && + (rmp->mp_flags & PRIV_PROC)) continue; + /* Check for permission. */ if (mp->mp_effuid != SUPER_USER && mp->mp_realuid != rmp->mp_realuid diff --git a/servers/pm/table.c b/servers/pm/table.c index fb053a932..d494f2bc4 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -93,8 +93,7 @@ _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = { do_sigreturn, /* 75 = sigreturn */ do_reboot, /* 76 = reboot */ do_svrctl, /* 77 = svrctl */ - - no_sys, /* 78 = unused */ + do_procstat, /* 78 = procstat */ do_getsysinfo, /* 79 = getsysinfo */ do_getprocnr, /* 80 = getprocnr */ no_sys, /* 81 = unused */ diff --git a/servers/pm/utility.c b/servers/pm/utility.c index c12425128..3e03f861e 100644 --- a/servers/pm/utility.c +++ b/servers/pm/utility.c @@ -111,8 +111,7 @@ int num; /* number to go with it */ { /* An unrecoverable error has occurred. Panics are caused when an internal * inconsistency is detected, e.g., a programming error or illegal value of a - * defined constant. The process manager decides to shut down. This results - * in a HARD_STOP notification to all system processes to allow local cleanup. + * defined constant. The process manager decides to exit. */ message m; int s; @@ -122,16 +121,8 @@ int num; /* number to go with it */ printf("PM panic (%s): %s", who, mess); if (num != NO_NUM) printf(": %d",num); printf("\n"); - -#if 0 - /* Allow for debug dumps if the IS server is available. */ - m.m_type = PANIC_DUMPS; - if (OK == (s= nb_send(11, &m))) { - return; /* IS responsible for exit */ - } - printf("Shutting down: IS is not answering: %d\n", s); - sys_abort(RBT_PANIC); -#endif + + /* Exit PM. */ sys_exit(SELF); } diff --git a/servers/rs/main.c b/servers/rs/main.c index fd1822652..4ca580dfa 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -15,6 +15,7 @@ /* Declare some local functions. */ FORWARD _PROTOTYPE(void init_server, (void) ); +FORWARD _PROTOTYPE(void sig_handler, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m) ); FORWARD _PROTOTYPE(void reply, (int whom, int result) ); @@ -66,11 +67,8 @@ PUBLIC int main(void) case SYN_ALARM: do_period(&m); /* check drivers status */ continue; - case SYS_SIG: - sigset = (sigset_t) m.NOTIFY_ARG; /* check signals passed */ - if (sigismember(&sigset, SIGCHLD)) do_exit(&m); - if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL); - if (sigismember(&sigset, SIGKSTOP)) do_shutdown(NULL); + case PROC_EVENT: + sig_handler(); continue; default: /* heartbeat notification */ if (rproc_ptr[who_p] != NULL) /* mark heartbeat time */ @@ -120,8 +118,6 @@ PRIVATE void init_server(void) sa.sa_flags = 0; if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno); if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno); - if (sigaction(SIGABRT,&sa,NULL)<0) panic("RS","sigaction failed", errno); - if (sigaction(SIGHUP, &sa,NULL)<0) panic("RS","sigaction failed", errno); /* Initialize the system process table. Use the boot image from the kernel * and the device map from the FS to gather all needed information. @@ -158,6 +154,21 @@ PRIVATE void init_server(void) } +/*===========================================================================* + * sig_handler * + *===========================================================================*/ +PRIVATE void sig_handler() +{ + sigset_t sigset; + int sig; + + /* Try to obtain signal set from PM. */ + if (getsigset(&sigset) != 0) return; + + /* Check for known signals. */ + if (sigismember(&sigset, SIGCHLD)) do_exit(NULL); + if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL); +} /*===========================================================================* * get_work *