Jorrit's ... "progress?"
This commit is contained in:
parent
498e232a5c
commit
021e3234d8
35 changed files with 352 additions and 436 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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);
|
||||
|
|
28
kernel/ipc.h
28
kernel/ipc.h
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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" },
|
||||
};
|
||||
|
||||
|
|
|
@ -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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
Loading…
Reference in a new issue