Jorrit's ... "progress?"

This commit is contained in:
Jorrit Herder 2006-03-10 16:10:05 +00:00
parent 498e232a5c
commit 021e3234d8
35 changed files with 352 additions and 436 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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) );

View file

@ -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);

View file

@ -7,24 +7,28 @@
#include <minix/com.h>
/* 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 */

View file

@ -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; rp<END_PROC_ADDR; rp++) {
if (!isemptyp(rp) && (priv(rp)->s_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

View file

@ -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

View file

@ -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])

View file

@ -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; rp<END_PROC_ADDR; rp++) {
if (! isemptyp(rp)) { /* check slot use */
lock(5,"balance_queues");
if (rp->p_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);

View file

@ -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

View file

@ -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))

View file

@ -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);
}

View file

@ -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 */

View file

@ -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" },
};

View file

@ -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 *
*===========================================================================*/

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}
/*===========================================================================*

View file

@ -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 */

View file

@ -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 *

View file

@ -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 *
*===========================================================================*/

View file

@ -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) );

View file

@ -17,6 +17,7 @@
#include <sys/wait.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <sys/resource.h>
#include <signal.h>
#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. */

View file

@ -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. */

View file

@ -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;

View file

@ -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 */
}
/*===========================================================================*

View file

@ -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

View file

@ -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) );

View file

@ -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

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 *