System processes can be signaled; signals are transformed in SYS_EVENT message

that passes signal map along. This mechanisms is also used for nonuser signals
like SIGKMESS, SIGKSTOP, SIGKSIG.

Revised comments of many system call handlers. Renamed setpriority to nice.
This commit is contained in:
Jorrit Herder 2005-07-19 12:21:36 +00:00
parent f8c380c195
commit 198c976f7e
33 changed files with 289 additions and 395 deletions

View file

@ -7,10 +7,8 @@
* *
* Changes: * Changes:
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder) * Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
* Oct 10, 2004 call vector + return values allowed (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder) * Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
* Sep 24, 2004 redesigned timers and alarms (Jorrit N. Herder) * Sep 24, 2004 redesigned timers and alarms (Jorrit N. Herder)
* Jun 04, 2004 new timeout flag alarm functionality (Jorrit N. Herder)
* *
* The function do_clocktick() is not triggered from the clock library, but * The function do_clocktick() is not triggered from the clock library, but
* by the clock's interrupt handler when a watchdog timer has expired or * by the clock's interrupt handler when a watchdog timer has expired or
@ -60,25 +58,18 @@ FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
#endif #endif
/* The CLOCK's timers queue. The functions in <timers.h> operate on this. /* The CLOCK's timers queue. The functions in <timers.h> operate on this.
* The process structure contains one timer per type of alarm (SIGNALRM, * All system processes possess a single synchronous alarm timer. If other
* SYNCALRM, and FLAGALRM), which means that a process can have a single * kernel parts want to use additional timers, they must declare their own
* outstanding timer for each alarm type. * persistent (static) timer structure, which can be passed to the clock
* If other kernel parts want to use additional timers, they must declare
* their own persistent timer structure, which can be passed to the clock
* via (re)set_timer(). * via (re)set_timer().
* When a timer expires its watchdog function is run by the CLOCK task. * When a timer expires its watchdog function is run by the CLOCK task.
*/ */
PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */ PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */
PRIVATE clock_t next_timeout; /* realtime that next timer expires */ PRIVATE clock_t next_timeout; /* realtime that next timer expires */
/* The boot time and the current real time. The real time is incremented by /* The time is incremented by the interrupt handler on each clock tick. */
* the clock on each clock tick. The boot time is set by a utility program
* after system startup to prevent troubles reading the CMOS.
*/
PRIVATE clock_t realtime; /* real time clock */ PRIVATE clock_t realtime; /* real time clock */
PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */
/* Variables for and changed by the CLOCK's interrupt handler. */
PRIVATE irq_hook_t clock_hook;
/*===========================================================================* /*===========================================================================*
@ -86,12 +77,12 @@ PRIVATE irq_hook_t clock_hook;
*===========================================================================*/ *===========================================================================*/
PUBLIC void clock_task() PUBLIC void clock_task()
{ {
/* Main program of clock task. It corrects realtime by adding pending ticks /* Main program of clock task. It determines which call this is by looking at
* seen only by the interrupt service, then it determines which call this is * the message type and dispatches.
* by looking at the message type and dispatches.
*/ */
message m; /* message buffer for both input and output */ message m; /* message buffer for both input and output */
int result; int result; /* result returned by the handler */
init_clock(); /* initialize clock task */ init_clock(); /* initialize clock task */
/* Main loop of the clock task. Get work, process it, sometimes reply. */ /* Main loop of the clock task. Get work, process it, sometimes reply. */
@ -297,11 +288,9 @@ PUBLIC unsigned long read_clock()
*/ */
unsigned count; unsigned count;
/* lock(10, "read_clock"); */
outb(TIMER_MODE, LATCH_COUNT); outb(TIMER_MODE, LATCH_COUNT);
count = inb(TIMER0); count = inb(TIMER0);
count |= (inb(TIMER0) << 8); count |= (inb(TIMER0) << 8);
/* unlock(10); */
return count; return count;
} }

View file

@ -34,7 +34,7 @@
#define USE_IRQCTL 1 /* set an interrupt policy */ #define USE_IRQCTL 1 /* set an interrupt policy */
#define USE_SEGCTL 1 /* set up a remote segment */ #define USE_SEGCTL 1 /* set up a remote segment */
#define USE_SVRCTL 1 /* system server control */ #define USE_SVRCTL 1 /* system server control */
#define USE_SCHEDCTL 1 /* change scheduling priority (nice) */ #define USE_NICE 1 /* change scheduling priority */
#define USE_UMAP 1 /* map virtual to physical address */ #define USE_UMAP 1 /* map virtual to physical address */
#define USE_VIRCOPY 1 /* copy using virtual addressing */ #define USE_VIRCOPY 1 /* copy using virtual addressing */
#define USE_VIRVCOPY 1 /* vector with virtual copy requests */ #define USE_VIRVCOPY 1 /* vector with virtual copy requests */
@ -70,8 +70,13 @@
#define VDEVIO_BUF_SIZE 64 /* max elements per VDEVIO request */ #define VDEVIO_BUF_SIZE 64 /* max elements per VDEVIO request */
#define VCOPY_VEC_SIZE 16 /* max elements per VCOPY request */ #define VCOPY_VEC_SIZE 16 /* max elements per VCOPY request */
#if TEMP_CODE
/* How many buffers for notification messages should there be? */ /* How many buffers for notification messages should there be? */
#define NR_NOTIFY_BUFS 32 #define NR_NOTIFY_BUFS 32
#endif
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
#define K_STACK_BYTES 1024
/* This section allows to enable kernel debugging and timing functionality. /* This section allows to enable kernel debugging and timing functionality.

View file

@ -20,9 +20,6 @@
#define structof(type, field, ptr) \ #define structof(type, field, ptr) \
((type *) (((char *) (ptr)) - offsetof(type, field))) ((type *) (((char *) (ptr)) - offsetof(type, field)))
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
#define K_STACK_BYTES 1024
/* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */ /* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */
#define _SRC_ 0 #define _SRC_ 0
#define _DST_ 1 #define _DST_ 1

View file

@ -33,9 +33,11 @@ EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */
EXTERN int sched_ticks; /* keep track of quantum usage */ EXTERN int sched_ticks; /* keep track of quantum usage */
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */ EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
#if TEMP_CODE
/* Declare buffer space and a bit map for notification messages. */ /* Declare buffer space and a bit map for notification messages. */
EXTERN struct notification notify_buffer[NR_NOTIFY_BUFS]; EXTERN struct notification notify_buffer[NR_NOTIFY_BUFS];
EXTERN bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)]; EXTERN bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)];
#endif
#if (CHIP == INTEL) #if (CHIP == INTEL)

View file

@ -51,39 +51,39 @@ int mine;
intr_disable(); intr_disable();
if (machine.protected) { if (machine.protected) {
/* The AT and newer PS/2 have two interrupt controllers, one master, /* The AT and newer PS/2 have two interrupt controllers, one master,
* one slaved at IRQ 2. (We don't have to deal with the PC that * one slaved at IRQ 2. (We don't have to deal with the PC that
* has just one controller, because it must run in real mode.) * has just one controller, because it must run in real mode.)
*/ */
outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC); outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
/* ICW2 for master */ /* ICW2 for master */
outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */ outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
outb(INT_CTLMASK, ICW4_AT_MASTER); outb(INT_CTLMASK, ICW4_AT_MASTER);
outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC); outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
/* ICW2 for slave */ /* ICW2 for slave */
outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
outb(INT2_CTLMASK, ICW4_AT_SLAVE); outb(INT2_CTLMASK, ICW4_AT_SLAVE);
outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
/* Copy the BIOS vectors from the BIOS to the Minix location, so we /* Copy the BIOS vectors from the BIOS to the Minix location, so we
* can still make BIOS calls without reprogramming the i8259s. * can still make BIOS calls without reprogramming the i8259s.
*/ */
#if IRQ0_VECTOR != BIOS_IRQ0_VEC #if IRQ0_VECTOR != BIOS_IRQ0_VEC
phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L); phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
#endif #endif
#if IRQ8_VECTOR != BIOS_IRQ8_VEC #if IRQ8_VECTOR != BIOS_IRQ8_VEC
phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L); phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
#endif #endif
} else { } else {
/* Use the BIOS interrupt vectors in real mode. We only reprogram the /* Use the BIOS interrupt vectors in real mode. We only reprogram the
* exceptions here, the interrupt vectors are reprogrammed on demand. * exceptions here, the interrupt vectors are reprogrammed on demand.
* SYS_VECTOR is the Minix system call for message passing. * SYS_VECTOR is the Minix system call for message passing.
*/ */
for (i = 0; i < 8; i++) set_vec(i, int_vec[i]); for (i = 0; i < 8; i++) set_vec(i, int_vec[i]);
set_vec(SYS_VECTOR, s_call); set_vec(SYS_VECTOR, s_call);
} }
} }
@ -100,14 +100,14 @@ irq_handler_t handler;
irq_hook_t **line; irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS) if (irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to put_irq_handler", irq); panic("invalid call to put_irq_handler", irq);
line = &irq_handlers[irq]; line = &irq_handlers[irq];
id = 1; id = 1;
while (*line != NULL) { while (*line != NULL) {
if (hook == *line) return; /* extra initialization */ if (hook == *line) return; /* extra initialization */
line = &(*line)->next; line = &(*line)->next;
id <<= 1; id <<= 1;
} }
if (id == 0) panic("Too many handlers for irq", irq); if (id == 0) panic("Too many handlers for irq", irq);
@ -130,22 +130,20 @@ int id;
/* Unregister an interrupt handler. */ /* Unregister an interrupt handler. */
irq_hook_t **line; irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS) { if (irq < 0 || irq >= NR_IRQ_VECTORS) return(EINVAL);
return EINVAL;
}
line = &irq_handlers[irq]; line = &irq_handlers[irq];
while (*line != NULL) { while (*line != NULL) {
if((*line)->id == id) { if((*line)->id == id) {
(*line) = (*line)->next; (*line) = (*line)->next;
if(!irq_handlers[irq]) if(! irq_handlers[irq])
irq_use &= ~(1 << irq); irq_use &= ~(1 << irq);
return OK; return(OK);
} }
line = &(*line)->next; line = &(*line)->next;
} }
return ENOENT; return(ENOENT);
} }
/*==========================================================================* /*==========================================================================*
@ -161,12 +159,12 @@ irq_hook_t *hook;
/* Call list of handlers for an IRQ. */ /* Call list of handlers for an IRQ. */
while (hook != NULL) { while (hook != NULL) {
/* For each handler in the list, mark it active by setting its ID bit, /* For each handler in the list, mark it active by setting its ID bit,
* call the function, and unmark it if the function returns true. * call the function, and unmark it if the function returns true.
*/ */
irq_actids[hook->irq] |= hook->id; irq_actids[hook->irq] |= hook->id;
if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id; if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id;
hook = hook->next; hook = hook->next;
} }
/* The assembly code will now disable interrupts, unmask the IRQ if and only /* The assembly code will now disable interrupts, unmask the IRQ if and only

View file

@ -18,9 +18,8 @@
/* Call masks indicating which system calls a process can make. */ /* Call masks indicating which system calls a process can make. */
#define EMPTY_CALL_MASK (0) #define EMPTY_CALL_MASK (0)
#define _USER_CALL_MASK ((1 << SENDREC) | (1 << ALERT)) #define USER_CALL_MASK (1 << SENDREC)
#define SYSTEM_CALL_MASK (~0) #define SYSTEM_CALL_MASK (~0)
#define USER_CALL_MASK (~0)
#endif /* IPC_H */ #endif /* IPC_H */

View file

@ -20,6 +20,7 @@
#include "kernel.h" #include "kernel.h"
#include <signal.h>
#include <minix/com.h> #include <minix/com.h>
#define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10) #define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10)
@ -159,7 +160,7 @@ int c; /* character to append */
kmess.km_size += 1; kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE; kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
} else { } else {
lock_alert(SYSTEM, PRINTF_PROC); send_sig(PRINTF_PROC, SIGKMESS);
} }
} }

View file

@ -201,6 +201,9 @@ int how; /* reason to shut down */
return; /* await sys_abort() from TTY */ return; /* await sys_abort() from TTY */
} }
/* Send signal to TTY so that it can switch to the primary console. */
send_sig(TTY, SIGKSTOP);
/* Allow processes to be scheduled to clean up, unless a CPU exception /* Allow processes to be scheduled to clean up, unless a CPU exception
* occurred. This is done by setting a timer. The timer argument passes * occurred. This is done by setting a timer. The timer argument passes
* the shutdown status. * the shutdown status.

View file

@ -26,6 +26,7 @@ struct priv {
sys_map_t s_notify_pending; /* bit map with pending notifications */ sys_map_t s_notify_pending; /* bit map with pending notifications */
short s_int_pending; /* pending hardware interrupts */ short s_int_pending; /* pending hardware interrupts */
sigset_t s_sig_pending; /* pending signals */
timer_t s_alarm_timer; /* synchronous alarm timer */ timer_t s_alarm_timer; /* synchronous alarm timer */
struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */ struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */
@ -60,6 +61,9 @@ struct priv {
EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */ EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */
EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
/* Unprivileged user processes all share the same privilege structure. */
#define USER_PRIV_ID 0
/* Make sure the system can boot. The following sanity check verifies that /* Make sure the system can boot. The following sanity check verifies that
* the system privileges table is large enough for the number of processes * the system privileges table is large enough for the number of processes
* in the boot image. * in the boot image.

View file

@ -62,19 +62,27 @@ FORWARD _PROTOTYPE( void sched, (struct proc *rp) );
FORWARD _PROTOTYPE( void pick_proc, (void) ); FORWARD _PROTOTYPE( void pick_proc, (void) );
#if TEMP_CODE
#define BuildOldMess(m,n) \ #define BuildOldMess(m,n) \
(m).NOTIFY_SOURCE = (n)->n_source, \ (m).NOTIFY_SOURCE = (n)->n_source, \
(m).NOTIFY_TYPE = (n)->n_type, \ (m).NOTIFY_TYPE = (n)->n_type, \
(m).NOTIFY_FLAGS = (n)->n_flags, \ (m).NOTIFY_FLAGS = (n)->n_flags, \
(m).NOTIFY_ARG = (n)->n_arg; (m).NOTIFY_ARG = (n)->n_arg;
#endif
#define BuildMess(m_ptr, src, dst_ptr) \ #define BuildMess(m_ptr, src, dst_ptr) \
(m_ptr)->m_source = (src); \ (m_ptr)->m_source = (src); \
(m_ptr)->m_type = NOTIFY_FROM(src); \ (m_ptr)->m_type = NOTIFY_FROM(src); \
(m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \
if ((src) == HARDWARE) { \ switch (src) { \
case HARDWARE: \
(m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \ (m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \
priv(dst_ptr)->s_int_pending = 0; \ priv(dst_ptr)->s_int_pending = 0; \
break; \
case SYSTEM: \
(m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_sig_pending; \
priv(dst_ptr)->s_sig_pending = 0; \
break; \
} }
#if (CHIP == INTEL) #if (CHIP == INTEL)
@ -123,24 +131,16 @@ message *m_ptr; /* pointer to message in the caller's space */
return(EBADSRCDST); return(EBADSRCDST);
#if DEAD_CODE /* temporarily disabled for testing ALERT */ #if DEAD_CODE /* temporarily disabled for testing ALERT */
/* Check validity of message pointer. */
vb = (vir_bytes) m_ptr;
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
#if ALLOW_GAP_MESSAGES
/* This check allows a message to be anywhere in data or stack or gap. /* This check allows a message to be anywhere in data or stack or gap.
* It will have to be made more elaborate later for machines which * It will have to be made more elaborate later for machines which
* don't have the gap mapped. * don't have the gap mapped.
*/ */
vb = (vir_bytes) m_ptr;
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi || if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
vhi >= caller_ptr->p_memmap[S].mem_vir + caller_ptr->p_memmap[S].mem_len) vhi >= caller_ptr->p_memmap[S].mem_vir + caller_ptr->p_memmap[S].mem_len)
return(EFAULT); return(EFAULT);
#else
/* Check for messages wrapping around top of memory or outside data seg. */
if (vhi < vlo ||
vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len)
return(EFAULT);
#endif
#endif #endif
/* Now check if the call is known and try to perform the request. The only /* Now check if the call is known and try to perform the request. The only
@ -183,9 +183,11 @@ message *m_ptr; /* pointer to message in the caller's space */
break; break;
case NOTIFY: case NOTIFY:
result = mini_notify(caller_ptr, src_dst, m_ptr); result = mini_notify(caller_ptr, src_dst, m_ptr);
#if TEMP_CODE
break; break;
case ECHO: case ECHO:
kprintf("Echo message from process %s\n", proc_nr(caller_ptr)); kprintf("Echo message from process %s\n", proc_nr(caller_ptr));
#endif
CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr); CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr);
result = OK; result = OK;
break; break;
@ -197,7 +199,7 @@ message *m_ptr; /* pointer to message in the caller's space */
* be raised. The priority may have been lowered if a process consumed too * be raised. The priority may have been lowered if a process consumed too
* many full quantums in a row to prevent damage from infinite loops * many full quantums in a row to prevent damage from infinite loops
*/ */
#if DEAD_CODE /* temporarily disabled for testing ALERT */ #if DEAD_CODE /* buggy ... do unready() first! */
if ((caller_ptr->p_priority > caller_ptr->p_max_priority) && if ((caller_ptr->p_priority > caller_ptr->p_max_priority) &&
! (flags & NON_BLOCKING) && (result == OK)) { ! (flags & NON_BLOCKING) && (result == OK)) {
caller_ptr->p_priority = caller_ptr->p_max_priority; caller_ptr->p_priority = caller_ptr->p_max_priority;

View file

@ -87,7 +87,7 @@ struct proc {
#define BEG_USER_ADDR (&proc[NR_TASKS]) #define BEG_USER_ADDR (&proc[NR_TASKS])
#define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS]) #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
#define NIL_PROC ((struct proc *) 0) #define NIL_PROC ((struct proc *) 0)
#define cproc_addr(n) (&(proc + NR_TASKS)[(n)]) #define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
#define proc_addr(n) (pproc_addr + NR_TASKS)[(n)] #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
#define proc_nr(p) ((p)->p_nr) #define proc_nr(p) ((p)->p_nr)

View file

@ -50,6 +50,7 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
U16_t parmoff, U16_t parmsize) ); U16_t parmoff, U16_t parmsize) );
/* system.c */ /* system.c */
_PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) ); _PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) );
_PROTOTYPE( void clear_proc, (int proc_nr) ); _PROTOTYPE( void clear_proc, (int proc_nr) );

View file

@ -1,44 +0,0 @@
/* Definition of the 'p_sendmask' bit mask used in the process table. The bit
* mask of process is checked in mini_send() to see if the caller is allowed
* to send to the destination.
*
* PLEASE NOTE: the send masks definitions are a mess and must be updated!!!
* this will be done when dynamic driver loading is implemented
*
* Changes:
* May 01, 2004 created and sendmask definitions (Jorrit N. Herder)
*/
#ifndef SENDMASK_H
#define SENDMASK_H
/* Define type for sendmask, if not already done. */
#include "type.h"
/* Constants to support the bitmask operations. */
#define BIT_0 (send_mask_t) 1
#define MASK_ENTRIES NR_TASKS + (INIT_PROC_NR+1) + 1
#define USER_PROC_NR INIT_PROC_NR+1 /* used to set bit for user procs */
#define ALLOW_ALL_MASK (send_mask_t) -1
#define DENY_ALL_MASK (send_mask_t) 0
/* Check if given process number is in range. */
#define isvalid(n) ((unsigned) ((n)+NR_TASKS) <= MASK_ENTRIES -1)
/* Default masks and bit operations that easily allow to construct bit masks.
* Note the one always must start with a default mask like allow_all_mask.
* From that point, one can, for example, deny several processes.
*/
#define allow(enabled,n) | (enabled << ((n) + NR_TASKS))
#define deny(enabled,n) & ~(enabled << ((n) + NR_TASKS))
#define send_mask_allow(mask,n) ((mask) |= (1 << ((n) + NR_TASKS)))
#define send_mask_deny(mask,n) ((mask) &= ~(1 << ((n) + NR_TASKS)))
/* Check if the bit for the given process number is set. */
#define isallowed(mask,n) ((mask) & (BIT_0 << ((n) + NR_TASKS)))
#define USER_PROC_SENDMASK \
DENY_ALL_MASK allow(1, PM_PROC_NR) allow(1, FS_PROC_NR)
#endif /* SENDMASK_H */

View file

@ -11,7 +11,8 @@
* *
* In addition to the main sys_task() entry point, which starts the main loop, * In addition to the main sys_task() entry point, which starts the main loop,
* there are several other minor entry points: * there are several other minor entry points:
* cause_sig: take action to cause a signal to occur * send_sig: send signal directly to a system process
* cause_sig: take action to cause a signal to occur via PM
* clear_proc: clean up a process in the process table, e.g. on exit * clear_proc: clean up a process in the process table, e.g. on exit
* umap_local: map virtual address in LOCAL_SEG to physical * umap_local: map virtual address in LOCAL_SEG to physical
* umap_remote: map virtual address in REMOTE_SEG to physical * umap_remote: map virtual address in REMOTE_SEG to physical
@ -78,9 +79,6 @@ PUBLIC void sys_task()
/* Handle the request. */ /* Handle the request. */
if ((unsigned) m.m_type < NR_SYS_CALLS) { if ((unsigned) m.m_type < NR_SYS_CALLS) {
result = (*call_vec[m.m_type])(&m); /* handle the kernel call */ result = (*call_vec[m.m_type])(&m); /* handle the kernel call */
} else if (m.m_type == NEW_KSIG) {
lock_alert(SYSTEM, PM_PROC_NR); /* tell PM about signal */
continue;
} else { } else {
kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source); kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source);
result = EBADREQUEST; /* illegal message type */ result = EBADREQUEST; /* illegal message type */
@ -133,6 +131,7 @@ PRIVATE void initialize(void)
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
map(SYS_EXEC, do_exec); /* update process after execute */ map(SYS_EXEC, do_exec); /* update process after execute */
map(SYS_EXIT, do_exit); /* clean up after process exit */ map(SYS_EXIT, do_exit); /* clean up after process exit */
map(SYS_NICE, do_nice); /* set scheduling priority */
map(SYS_TRACE, do_trace); /* request a trace operation */ map(SYS_TRACE, do_trace); /* request a trace operation */
/* Signal handling. */ /* Signal handling. */
@ -153,7 +152,8 @@ PRIVATE void initialize(void)
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */ map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
/* System control. */ /* System control. */
map(SYS_SETPRIORITY, do_schedctl); /* set scheduling priority */ map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
map(SYS_SVRCTL, do_svrctl); /* kernel control functions */ map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
@ -164,10 +164,6 @@ PRIVATE void initialize(void)
map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */ map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */ map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */
map(SYS_MEMSET, do_memset); /* write char to memory area */ map(SYS_MEMSET, do_memset); /* write char to memory area */
/* Miscellaneous. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
} }
@ -256,17 +252,18 @@ int proc_nr; /* slot of process to clean up */
while (rc->p_ntf_q != NULL) { while (rc->p_ntf_q != NULL) {
i = (int) (rc->p_ntf_q - &notify_buffer[0]); i = (int) (rc->p_ntf_q - &notify_buffer[0]);
free_bit(i, notify_bitmap, NR_NOTIFY_BUFS); free_bit(i, notify_bitmap, NR_NOTIFY_BUFS);
#if TEMP_CODE
rc->p_ntf_q = rc->p_ntf_q->n_next; rc->p_ntf_q = rc->p_ntf_q->n_next;
} }
/* Now clean up the process table entry. Reset to defaults. */
kstrncpy(rc->p_name, "<none>", P_NAME_LEN); /* unset name */
sigemptyset(&rc->p_pending); /* remove pending signals */
rc->p_rts_flags = SLOT_FREE; /* announce slot empty */
#if (CHIP == M68000)
pmmu_delete(rc); /* we're done, remove tables */
#endif #endif
/* Now it is safe to release the process table slot. If this is a system
* process, also release its privilege structure. Further cleanup is not
* needed at this point. All important fields are reinitialized when the
* slots are assigned to another, new process.
*/
rc->p_rts_flags = SLOT_FREE;
if (priv(rp)->s_flags & SYS_PROC) priv(rp)->s_proc_nr = NONE;
} }
@ -331,6 +328,25 @@ irq_hook_t *hook;
} }
/*===========================================================================*
* send_sig *
*===========================================================================*/
PUBLIC void send_sig(proc_nr, sig_nr)
int proc_nr; /* system process to be signalled */
int sig_nr; /* signal to be sent, 1 to _NSIG */
{
/* Notify a system process about a signal. This is straightforward. Simply
* set the signal that is to be delivered in the pending signals map and
* send a notification with source SYSTEM.
*/
register struct proc *rp;
rp = proc_addr(proc_nr);
sigaddset(&priv(rp)->s_sig_pending, sig_nr);
lock_alert(SYSTEM, proc_nr);
}
/*===========================================================================* /*===========================================================================*
* cause_sig * * cause_sig *
*===========================================================================*/ *===========================================================================*/
@ -346,8 +362,10 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
* signals and makes sure the PM gets them by sending a notification. The * signals and makes sure the PM gets them by sending a notification. The
* process being signaled is blocked while PM has not finished all signals * process being signaled is blocked while PM has not finished all signals
* for it. * for it.
* It is not sufficient to ready the process when PM is informed, because * Race conditions between calls to this function and the system calls that
* PM can block waiting for FS to do a core dump. * process pending kernel signals cannot exist. Signal related functions are
* only called when a user process causes a CPU exception and from the kernel
* process level, which runs to completion.
*/ */
register struct proc *rp; register struct proc *rp;
@ -358,7 +376,7 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */ if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */
if (rp->p_rts_flags == 0) lock_unready(rp); /* make not ready */ if (rp->p_rts_flags == 0) lock_unready(rp); /* make not ready */
rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */ rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */
lock_alert(HARDWARE, SYSTEM); send_sig(PM_PROC_NR, SIGKSIG);
} }
} }
} }
@ -509,10 +527,7 @@ vir_bytes bytes; /* # of bytes to copy */
int i; int i;
/* Check copy count. */ /* Check copy count. */
if (bytes <= 0) { if (bytes <= 0) return(EDOM);
kprintf("v_cp: copy count problem <= 0\n", NO_NUM);
return(EDOM);
}
/* Do some more checks and map virtual addresses to physical addresses. */ /* Do some more checks and map virtual addresses to physical addresses. */
vir_addr[_SRC_] = src_addr; vir_addr[_SRC_] = src_addr;
@ -539,16 +554,12 @@ vir_bytes bytes; /* # of bytes to copy */
phys_addr[i] = vir_addr[i]->offset; phys_addr[i] = vir_addr[i]->offset;
break; break;
default: default:
kprintf("v_cp: Unknown segment type: %d\n",
vir_addr[i]->segment & SEGMENT_TYPE);
return(EINVAL); return(EINVAL);
} }
/* Check if mapping succeeded. */ /* Check if mapping succeeded. */
if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) { if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG)
kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_NUM);
return(EFAULT); return(EFAULT);
}
} }
/* Now copy bytes between physical addresseses. */ /* Now copy bytes between physical addresseses. */

View file

@ -43,9 +43,9 @@ _PROTOTYPE( int do_trace, (message *m_ptr) );
#define do_trace do_unused #define do_trace do_unused
#endif #endif
_PROTOTYPE( int do_schedctl, (message *m_ptr) ); _PROTOTYPE( int do_nice, (message *m_ptr) );
#if ! USE_SCHEDCTL #if ! USE_NICE
#define do_schedctl do_unused #define do_nice do_unused
#endif #endif
_PROTOTYPE( int do_copy, (message *m_ptr) ); _PROTOTYPE( int do_copy, (message *m_ptr) );

View file

@ -23,7 +23,7 @@ OBJECTS = \
$(SYSTEM)(do_newmap.o) \ $(SYSTEM)(do_newmap.o) \
$(SYSTEM)(do_exit.o) \ $(SYSTEM)(do_exit.o) \
$(SYSTEM)(do_trace.o) \ $(SYSTEM)(do_trace.o) \
$(SYSTEM)(do_schedctl.o) \ $(SYSTEM)(do_nice.o) \
$(SYSTEM)(do_times.o) \ $(SYSTEM)(do_times.o) \
$(SYSTEM)(do_alarm.o) \ $(SYSTEM)(do_alarm.o) \
$(SYSTEM)(do_irqctl.o) \ $(SYSTEM)(do_irqctl.o) \
@ -75,8 +75,8 @@ $(SYSTEM)(do_exit.o): do_exit.c
$(SYSTEM)(do_trace.o): do_trace.c $(SYSTEM)(do_trace.o): do_trace.c
$(CC) do_trace.c $(CC) do_trace.c
$(SYSTEM)(do_schedctl.o): do_schedctl.c $(SYSTEM)(do_nice.o): do_nice.c
$(CC) do_schedctl.c $(CC) do_nice.c
$(SYSTEM)(do_times.o): do_times.c $(SYSTEM)(do_times.o): do_times.c
$(CC) do_times.c $(CC) do_times.c

View file

@ -1,7 +1,3 @@
#include "../system.h"
#include <unistd.h>
/* The system call implemented in this file: /* The system call implemented in this file:
* m_type: SYS_ABORT * m_type: SYS_ABORT
* *
@ -11,6 +7,10 @@
* m1_i3: ABRT_MON_LEN (length of monitor params) * m1_i3: ABRT_MON_LEN (length of monitor params)
* m1_p1: ABRT_MON_ADDR (virtual address of params) * m1_p1: ABRT_MON_ADDR (virtual address of params)
*/ */
#include "../system.h"
#include <unistd.h>
#if USE_ABORT #if USE_ABORT
/*===========================================================================* /*===========================================================================*
@ -24,7 +24,7 @@ message *m_ptr; /* pointer to request message */
* or ESC after debugging dumps). * or ESC after debugging dumps).
*/ */
int how = m_ptr->ABRT_HOW; int how = m_ptr->ABRT_HOW;
if (how == RBT_MONITOR) { if (how == RBT_MONITOR) {
/* The monitor is to run the specified instructions. */ /* The monitor is to run the specified instructions. */
int proc_nr = m_ptr->ABRT_MON_PROC; int proc_nr = m_ptr->ABRT_MON_PROC;
@ -33,8 +33,8 @@ message *m_ptr; /* pointer to request message */
phys_bytes src_phys = numap_local(proc_nr, src_vir, length); phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
/* Validate length and address of shutdown code before copying. */ /* Validate length and address of shutdown code before copying. */
if (length > kinfo.params_size || src_phys == 0) if (length > kinfo.params_size || src_phys == 0)
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11); phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
else else
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length); phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
} }

View file

@ -5,10 +5,10 @@
* m2_i1: ALRM_PROC_NR (set alarm for this process) * m2_i1: ALRM_PROC_NR (set alarm for this process)
* m2_l1: ALRM_EXP_TIME (alarm's expiration time) * m2_l1: ALRM_EXP_TIME (alarm's expiration time)
* m2_i2: ALRM_ABS_TIME (expiration time is absolute?) * m2_i2: ALRM_ABS_TIME (expiration time is absolute?)
* m2_l1: ALRM_SEC_LEFT (return seconds left of previous) * m2_l1: ALRM_TIME_LEFT (return seconds left of previous)
* *
* Changes: * Changes:
* Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder) * Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder)
*/ */
#include "../system.h" #include "../system.h"
@ -40,10 +40,10 @@ message *m_ptr; /* pointer to request message */
/* Get the timer structure and set the parameters for this alarm. */ /* Get the timer structure and set the parameters for this alarm. */
tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer); tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);
tmr_arg(tp)->ta_int = proc_nr; tmr_arg(tp)->ta_int = proc_nr;
tp->tmr_func = cause_alarm; tp->tmr_func = cause_alarm;
/* Return the ticks left on the previous alarm. */ /* Return the ticks left on the previous alarm. */
uptime = get_uptime(); uptime = get_uptime();
if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) { if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) {
m_ptr->ALRM_TIME_LEFT = 0; m_ptr->ALRM_TIME_LEFT = 0;
} else { } else {
@ -69,7 +69,7 @@ timer_t *tp;
{ {
/* Routine called if a timer goes off and the process requested a synchronous /* Routine called if a timer goes off and the process requested a synchronous
* alarm. The process number is stored in timer argument 'ta_int'. Notify that * alarm. The process number is stored in timer argument 'ta_int'. Notify that
* process given with a SYN_ALARM message. * process with a notification message from CLOCK.
*/ */
lock_alert(CLOCK, tmr_arg(tp)->ta_int); lock_alert(CLOCK, tmr_arg(tp)->ta_int);
} }

View file

@ -45,10 +45,8 @@ register message *m_ptr; /* pointer to request message */
/* Check if process number was given implictly with SELF and is valid. */ /* Check if process number was given implictly with SELF and is valid. */
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source; if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) { if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG)
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
return(EINVAL); return(EINVAL);
}
/* Check if physical addressing is used without SYS_PHYSCOPY. */ /* Check if physical addressing is used without SYS_PHYSCOPY. */
if ((vir_addr[i].segment & PHYS_SEG) && if ((vir_addr[i].segment & PHYS_SEG) &&
@ -58,10 +56,7 @@ register message *m_ptr; /* pointer to request message */
/* Check for overflow. This would happen for 64K segments and 16-bit /* Check for overflow. This would happen for 64K segments and 16-bit
* vir_bytes. Especially copying by the PM on do_fork() is affected. * vir_bytes. Especially copying by the PM on do_fork() is affected.
*/ */
if (bytes != (vir_bytes) bytes) { if (bytes != (vir_bytes) bytes) return(E2BIG);
kprintf("do_vircopy: overflow\n", NO_NUM);
return(E2BIG);
}
/* Now try to make the actual virtual copy. */ /* Now try to make the actual virtual copy. */
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) ); return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );

View file

@ -1,20 +1,8 @@
/* The system call that is implemented in this file: /* The system call that is implemented in this file:
* SYS_SIGCTL # signal handling functionality * m_type: SYS_ENDKSIG
* *
* The parameters and types for this system call are: * The parameters for this system call are:
* SIG_REQUEST # request to perform (long) * m2_i1: SIG_PROC # process for which PM is done
* SIG_PROC # process to signal/ pending (int)
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
* SIG_FLAGS # flags for S_SIGRETURN call (int)
* SIG_MAP # bit map with pending signals (long)
* SIG_NUMBER # signal number to send to process (int)
*
* Supported request types are in the parameter SIG_REQUEST:
* S_GETSIG # get a pending kernel signal
* S_ENDSIG # signal has been processed
* S_SENDSIG # deliver a POSIX-style signal
* S_SIGRETURN # return from a POSIX-style signal
* S_KILL # send a signal to a process
*/ */
#include "../system.h" #include "../system.h"

View file

@ -3,7 +3,9 @@
* *
* The parameters for this system call are: * The parameters for this system call are:
* m1_i1: PR_PROC_NR (process that did exec call) * m1_i1: PR_PROC_NR (process that did exec call)
#if DEAD_CODE
* m1_i3: PR_TRACING (flag to indicate tracing is on/ off) * m1_i3: PR_TRACING (flag to indicate tracing is on/ off)
#endif
* m1_p1: PR_STACK_PTR (new stack pointer) * m1_p1: PR_STACK_PTR (new stack pointer)
* m1_p2: PR_NAME_PTR (pointer to program name) * m1_p2: PR_NAME_PTR (pointer to program name)
* m1_p3: PR_IP_PTR (new instruction pointer) * m1_p3: PR_IP_PTR (new instruction pointer)
@ -20,14 +22,15 @@ PUBLIC int do_exec(m_ptr)
register message *m_ptr; /* pointer to request message */ register message *m_ptr; /* pointer to request message */
{ {
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
register struct proc *rp; register struct proc *rp;
reg_t sp; /* new sp */ reg_t sp; /* new sp */
phys_bytes phys_name; phys_bytes phys_name;
char *np; char *np;
rp = proc_addr(m_ptr->PR_PROC_NR); rp = proc_addr(m_ptr->PR_PROC_NR);
#if DEAD_CODE
if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP); if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP);
#endif
sp = (reg_t) m_ptr->PR_STACK_PTR; sp = (reg_t) m_ptr->PR_STACK_PTR;
rp->p_reg.sp = sp; /* set the stack pointer */ rp->p_reg.sp = sp; /* set the stack pointer */
#if (CHIP == M68000) #if (CHIP == M68000)

View file

@ -26,25 +26,26 @@ register message *m_ptr; /* pointer to request message */
#if (CHIP == INTEL) #if (CHIP == INTEL)
reg_t old_ldt_sel; reg_t old_ldt_sel;
#endif #endif
register struct proc *rpc; register struct proc *rpc; /* child process pointer */
struct proc *rpp; struct proc *rpp; /* parent process pointer */
rpp = proc_addr(m_ptr->PR_PPROC_NR); rpp = proc_addr(m_ptr->PR_PPROC_NR);
rpc = proc_addr(m_ptr->PR_PROC_NR); rpc = proc_addr(m_ptr->PR_PROC_NR);
if (! isemptyp(rpc)) return(EINVAL); if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);
/* Copy parent 'proc' struct to child. */ /* Copy parent 'proc' struct to child. And reinitialize some fields. */
#if (CHIP == INTEL) #if (CHIP == INTEL)
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */ old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
#endif *rpc = *rpp; /* copy 'proc' struct */
rpc->p_ldt_sel = old_ldt_sel; /* restore descriptors */
*rpc = *rpp; /* copy 'proc' struct */ #else
*rpc = *rpp; /* copy 'proc' struct */
#if (CHIP == INTEL)
rpc->p_ldt_sel = old_ldt_sel;
#endif #endif
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
#if TEMP_CODE
rpc->p_ntf_q = NULL; /* remove pending notifications */ rpc->p_ntf_q = NULL; /* remove pending notifications */
#endif
/* Only one in group should have SIGNALED, child doesn't inherit tracing. */ /* Only one in group should have SIGNALED, child doesn't inherit tracing. */
rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */

View file

@ -6,8 +6,8 @@
* m1_i4: I_PROC_NR (process to store value at) * m1_i4: I_PROC_NR (process to store value at)
* m1_p1: I_VAL_PTR (where to put it) * m1_p1: I_VAL_PTR (where to put it)
* m1_i1: I_VAL_LEN (maximum length expected, optional) * m1_i1: I_VAL_LEN (maximum length expected, optional)
* m1_p2: I_KEY_PTR (environment variable key) * m1_p2: I_VAL_PTR2 (second, optional pointer)
* m1_i2: I_KEY_LEN (lenght of environment variable key) * m1_i2: I_VAL_LEN2 (second length or process nr)
* *
* Author: * Author:
* Jorrit N. Herder <jnherder@cs.vu.nl> * Jorrit N. Herder <jnherder@cs.vu.nl>
@ -29,26 +29,26 @@ register message *m_ptr; /* pointer to request message */
phys_bytes dst_phys; phys_bytes dst_phys;
int proc_nr, nr; int proc_nr, nr;
/* Set source address and length based on request type. */ /* Set source address and length based on request type. */
switch (m_ptr->I_REQUEST) { switch (m_ptr->I_REQUEST) {
case GET_MACHINE: { case GET_MACHINE: {
length = sizeof(struct machine); length = sizeof(struct machine);
src_phys = vir2phys(&machine); src_phys = vir2phys(&machine);
break; break;
} }
case GET_KINFO: { case GET_KINFO: {
length = sizeof(struct kinfo); length = sizeof(struct kinfo);
src_phys = vir2phys(&kinfo); src_phys = vir2phys(&kinfo);
break; break;
} }
case GET_IMAGE: { case GET_IMAGE: {
length = sizeof(struct system_image) * NR_BOOT_PROCS; length = sizeof(struct system_image) * NR_BOOT_PROCS;
src_phys = vir2phys(image); src_phys = vir2phys(image);
break; break;
} }
case GET_IRQHOOKS: { case GET_IRQHOOKS: {
length = sizeof(struct irq_hook) * NR_IRQ_HOOKS; length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
src_phys = vir2phys(irq_hooks); src_phys = vir2phys(irq_hooks);
break; break;
} }
case GET_SCHEDINFO: { case GET_SCHEDINFO: {
@ -58,37 +58,36 @@ register message *m_ptr; /* pointer to request message */
*/ */
length = sizeof(struct proc *) * NR_SCHED_QUEUES; length = sizeof(struct proc *) * NR_SCHED_QUEUES;
src_phys = vir2phys(rdy_head); src_phys = vir2phys(rdy_head);
dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_KEY_PTR, dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_VAL_PTR2,
length); length);
if (src_phys == 0 || dst_phys == 0) return(EFAULT); if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, length); phys_copy(src_phys, dst_phys, length);
/* fall through */ /* fall through */
} }
case GET_PROCTAB: { case GET_PROCTAB: {
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS); length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
src_phys = vir2phys(proc); src_phys = vir2phys(proc);
break; break;
} }
case GET_PRIVTAB: { case GET_PRIVTAB: {
length = sizeof(struct priv) * (NR_SYS_PROCS); length = sizeof(struct priv) * (NR_SYS_PROCS);
src_phys = vir2phys(priv); src_phys = vir2phys(priv);
break; break;
} }
case GET_PROC: { case GET_PROC: {
nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN; nr = (m_ptr->I_VAL_LEN2 == SELF) ? m_ptr->m_source : m_ptr->I_VAL_LEN2;
if (! isokprocn(nr)) return(EINVAL); /* validate request */ if (! isokprocn(nr)) return(EINVAL); /* validate request */
length = sizeof(struct proc); length = sizeof(struct proc);
src_phys = vir2phys(proc_addr(nr)); src_phys = vir2phys(proc_addr(nr));
break; break;
} }
case GET_MONPARAMS: { case GET_MONPARAMS: {
src_phys = kinfo.params_base; /* already is a physical */ src_phys = kinfo.params_base; /* already is a physical */
length = kinfo.params_size; length = kinfo.params_size;
break; break;
} }
case GET_RANDOMNESS: { case GET_RANDOMNESS: {
static struct randomness copy; /* copy to keep counters */ static struct randomness copy; /* copy to keep counters */
int i; int i;
copy = krandom; copy = krandom;
@ -107,9 +106,9 @@ register message *m_ptr; /* pointer to request message */
} }
#if DEBUG_TIME_LOCKS #if DEBUG_TIME_LOCKS
case GET_LOCKTIMING: { case GET_LOCKTIMING: {
length = sizeof(timingdata); length = sizeof(timingdata);
src_phys = vir2phys(timingdata); src_phys = vir2phys(timingdata);
break; break;
} }
#endif #endif
default: default:

View file

@ -1,20 +1,10 @@
/* The system call that is implemented in this file: /* The system call that is implemented in this file:
* SYS_SIGCTL # signal handling functionality * m_type: SYS_GETKSIG
* *
* The parameters and types for this system call are: * The parameters for this system call are:
* SIG_REQUEST # request to perform (long) * m2_i1: SIG_PROC # process with pending signals
* SIG_PROC # process to signal/ pending (int) * m2_l1: SIG_MAP # bit map with pending signals
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
* SIG_FLAGS # flags for S_SIGRETURN call (int)
* SIG_MAP # bit map with pending signals (long)
* SIG_NUMBER # signal number to send to process (int)
* *
* Supported request types are in the parameter SIG_REQUEST:
* S_GETSIG # get a pending kernel signal
* S_ENDSIG # signal has been processed
* S_SENDSIG # deliver a POSIX-style signal
* S_SIGRETURN # return from a POSIX-style signal
* S_KILL # send a signal to a process
*/ */
#include "../system.h" #include "../system.h"
@ -32,16 +22,18 @@ message *m_ptr; /* pointer to request message */
/* PM is ready to accept signals and repeatedly does a system call to get /* PM is ready to accept signals and repeatedly does a system call to get
* one. Find a process with pending signals. If no signals are available, * one. Find a process with pending signals. If no signals are available,
* return NONE in the process number field. * return NONE in the process number field.
* It is not sufficient to ready the process when PM is informed, because
* PM can block waiting for FS to do a core dump.
*/ */
register struct proc *rp; register struct proc *rp;
/* Find the next process with pending signals. */ /* Find the next process with pending signals. */
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
if (rp->p_rts_flags & SIGNALED) { if (rp->p_rts_flags & SIGNALED) {
m_ptr->SIG_PROC = rp->p_nr; m_ptr->SIG_PROC = rp->p_nr; /* store signaled process */
m_ptr->SIG_MAP = rp->p_pending; m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */
sigemptyset(&rp->p_pending); /* ball is in PM's court */ sigemptyset(&rp->p_pending); /* ball is in PM's court */
rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
return(OK); return(OK);
} }
} }

View file

@ -37,15 +37,15 @@ register message *m_ptr; /* pointer to request message */
/* Enable or disable IRQs. This is straightforward. */ /* Enable or disable IRQs. This is straightforward. */
case IRQ_ENABLE: case IRQ_ENABLE:
case IRQ_DISABLE: case IRQ_DISABLE:
if (irq_hook_id >= NR_IRQ_HOOKS || if (irq_hook_id >= NR_IRQ_HOOKS ||
irq_hooks[irq_hook_id].proc_nr == NONE) return(EINVAL); irq_hooks[irq_hook_id].proc_nr == NONE) return(EINVAL);
if (irq_hooks[irq_hook_id].proc_nr != m_ptr->m_source) return(EPERM); if (irq_hooks[irq_hook_id].proc_nr != m_ptr->m_source) return(EPERM);
if (m_ptr->IRQ_REQUEST == IRQ_ENABLE) if (m_ptr->IRQ_REQUEST == IRQ_ENABLE)
enable_irq(&irq_hooks[irq_hook_id]); enable_irq(&irq_hooks[irq_hook_id]);
else else
disable_irq(&irq_hooks[irq_hook_id]); disable_irq(&irq_hooks[irq_hook_id]);
break; break;
/* Control IRQ policies. Set a policy and needed details in the IRQ table. /* Control IRQ policies. Set a policy and needed details in the IRQ table.
* This policy is used by a generic function to handle hardware interrupts. * This policy is used by a generic function to handle hardware interrupts.
@ -53,10 +53,7 @@ register message *m_ptr; /* pointer to request message */
case IRQ_SETPOLICY: case IRQ_SETPOLICY:
/* Check if IRQ line is acceptable. */ /* Check if IRQ line is acceptable. */
if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) { if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL);
kprintf("ST: irq line %d is not acceptable!\n", irq_vec);
return(EINVAL);
}
/* Find a free IRQ hook for this mapping. */ /* Find a free IRQ hook for this mapping. */
hook_ptr = NULL; hook_ptr = NULL;
@ -77,18 +74,16 @@ register message *m_ptr; /* pointer to request message */
m_ptr->IRQ_HOOK_ID = irq_hook_id + 1; m_ptr->IRQ_HOOK_ID = irq_hook_id + 1;
break; break;
case IRQ_RMPOLICY: case IRQ_RMPOLICY:
if (irq_hook_id >= NR_IRQ_HOOKS || if (irq_hook_id >= NR_IRQ_HOOKS ||
irq_hooks[irq_hook_id].proc_nr == NONE) { irq_hooks[irq_hook_id].proc_nr == NONE) {
r = EINVAL; return(EINVAL);
} else { } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { return(EPERM);
r = EPERM; } else {
} else { r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id);
r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id); }
} break;
}
break;
default: default:
r = EINVAL; /* invalid IRQ_REQUEST */ r = EINVAL; /* invalid IRQ_REQUEST */

View file

@ -1,20 +1,9 @@
/* The system call that is implemented in this file: /* The system call that is implemented in this file:
* SYS_SIGCTL # signal handling functionality * m_type: SYS_KILL
* *
* The parameters and types for this system call are: * The parameters for this system call are:
* SIG_REQUEST # request to perform (long) * m2_i1: SIG_PROC # process to signal/ pending
* SIG_PROC # process to signal/ pending (int) * m2_i2: SIG_NUMBER # signal number to send to process
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
* SIG_FLAGS # flags for S_SIGRETURN call (int)
* SIG_MAP # bit map with pending signals (long)
* SIG_NUMBER # signal number to send to process (int)
*
* Supported request types are in the parameter SIG_REQUEST:
* S_GETSIG # get a pending kernel signal
* S_ENDSIG # signal has been processed
* S_SENDSIG # deliver a POSIX-style signal
* S_SIGRETURN # return from a POSIX-style signal
* S_KILL # send a signal to a process
*/ */
#include "../system.h" #include "../system.h"
@ -29,11 +18,27 @@
PUBLIC int do_kill(m_ptr) PUBLIC int do_kill(m_ptr)
message *m_ptr; /* pointer to request message */ message *m_ptr; /* pointer to request message */
{ {
/* Handle sys_kill(). Cause a signal to be sent to a process via PM. /* Handle sys_kill(). Cause a signal to be sent to a process. The PM is the
* Note that this has nothing to do with the kill (2) system call, this * central server where all signals are processed and handler policies can
* is how the FS (and possibly other servers) get access to cause_sig. * be registered. Any request, except for PM requests, is added to the map
* of pending signals and the PM is informed about the new signal.
* Since system servers cannot use normal POSIX signal handlers (because they
* are usually blocked on a RECEIVE), they can request the PM to transform
* signals into messages. This is done by the PM with a call to sys_kill().
*/ */
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER); proc_nr_t proc_nr = m_ptr->SIG_PROC;
int sig_nr = m_ptr->SIG_NUMBER;
if (! isokprocn(proc_nr) || sig_nr > _NSIG) return(EINVAL);
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);
}
return(OK); return(OK);
} }

View file

@ -3,7 +3,7 @@
* *
* The parameters for this system call are: * The parameters for this system call are:
* m1_i1: PR_PROC_NR (install new map for this process) * m1_i1: PR_PROC_NR (install new map for this process)
* m1_p1: PR_MEM_PTR (pointer to memory map) * m1_p1: PR_MEM_PTR (pointer to the new memory map)
*/ */
#include "../system.h" #include "../system.h"
@ -16,24 +16,21 @@ PUBLIC int do_newmap(m_ptr)
message *m_ptr; /* pointer to request message */ message *m_ptr; /* pointer to request message */
{ {
/* Handle sys_newmap(). Fetch the memory map from PM. */ /* Handle sys_newmap(). Fetch the memory map from PM. */
register struct proc *rp; /* process whose map is to be loaded */
register struct proc *rp;
phys_bytes src_phys;
int caller; /* whose space has the new map (usually PM) */ int caller; /* whose space has the new map (usually PM) */
int k; /* process whose map is to be loaded */
int old_flags; /* value of flags before modification */
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
phys_bytes src_phys; /* physical address of map at the PM */
int old_flags; /* value of flags before modification */
/* Extract message parameters and copy new memory map from PM. */ /* Extract message parameters and copy new memory map from PM. */
caller = m_ptr->m_source; caller = m_ptr->m_source;
k = m_ptr->PR_PROC_NR;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
if (!isokprocn(k)) return(EINVAL); if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL);
rp = proc_addr(k); /* ptr to entry of user getting new map */ rp = proc_addr(m_ptr->PR_PROC_NR);
/* Copy the map from PM. */ /* Copy the map from PM. */
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
sizeof(rp->p_memmap)); sizeof(rp->p_memmap));
if (src_phys == 0) return(EFAULT); if (src_phys == 0) return(EFAULT);
phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));

View file

@ -44,8 +44,8 @@ register message *m_ptr; /* pointer to request message */
} }
} else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) { } else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) {
switch (m_ptr->DIO_TYPE) { switch (m_ptr->DIO_TYPE) {
case DIO_BYTE: phys_outsb(port, phys_buf, count); break; case DIO_BYTE: phys_outsb(port, phys_buf, count); break;
case DIO_WORD: phys_outsw(port, phys_buf, count); break; case DIO_WORD: phys_outsw(port, phys_buf, count); break;
default: return(EINVAL); default: return(EINVAL);
} }
} }

View file

@ -37,13 +37,13 @@ register message *m_ptr; /* pointer to request message */
rp = proc_addr(m_ptr->m_source); rp = proc_addr(m_ptr->m_source);
index = -1; index = -1;
for (i=0; i < NR_REMOTE_SEGS; i++) { for (i=0; i < NR_REMOTE_SEGS; i++) {
if (! rp->p_priv->s_farmem[i].in_use) { if (! rp->p_priv->s_farmem[i].in_use) {
index = i; index = i;
rp->p_priv->s_farmem[i].in_use = TRUE; rp->p_priv->s_farmem[i].in_use = TRUE;
rp->p_priv->s_farmem[i].mem_phys = phys; rp->p_priv->s_farmem[i].mem_phys = phys;
rp->p_priv->s_farmem[i].mem_len = size; rp->p_priv->s_farmem[i].mem_len = size;
break; break;
} }
} }
if (index < 0) return(ENOSPC); if (index < 0) return(ENOSPC);
@ -63,7 +63,7 @@ register message *m_ptr; /* pointer to request message */
USER_PRIVILEGE); USER_PRIVILEGE);
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
offset = 0; offset = 0;
result = OK; result = OK;
} else { } else {
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0, init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
USER_PRIVILEGE); USER_PRIVILEGE);

View file

@ -1,20 +1,10 @@
/* The system call that is implemented in this file: /* The system call that is implemented in this file:
* SYS_SIGCTL # signal handling functionality * m_type: SYS_SIGRETURN
* *
* The parameters and types for this system call are: * The parameters for this system call are:
* SIG_REQUEST # request to perform (long) * m2_i1: SIG_PROC # process returning from handler
* SIG_PROC # process to signal/ pending (int) * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
* SIG_FLAGS # flags for S_SIGRETURN call (int)
* SIG_MAP # bit map with pending signals (long)
* SIG_NUMBER # signal number to send to process (int)
* *
* Supported request types are in the parameter SIG_REQUEST:
* S_GETSIG # get a pending kernel signal
* S_ENDSIG # signal has been processed
* S_SENDSIG # deliver a POSIX-style signal
* S_SIGRETURN # return from a POSIX-style signal
* S_KILL # send a signal to a process
*/ */
#include "../system.h" #include "../system.h"

View file

@ -1,20 +1,11 @@
/* The system call that is implemented in this file: /* The system call that is implemented in this file:
* SYS_SIGCTL # signal handling functionality * m_type: SYS_SIGSEND
* *
* The parameters and types for this system call are: * The parameters for this system call are:
* SIG_REQUEST # request to perform (long) * m2_i1: SIG_PROC # process to call signal handler
* SIG_PROC # process to signal/ pending (int) * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer) * m2_i3: SIG_FLAGS # flags for S_SIGRETURN call
* SIG_FLAGS # flags for S_SIGRETURN call (int)
* SIG_MAP # bit map with pending signals (long)
* SIG_NUMBER # signal number to send to process (int)
* *
* Supported request types are in the parameter SIG_REQUEST:
* S_GETSIG # get a pending kernel signal
* S_ENDSIG # signal has been processed
* S_SENDSIG # deliver a POSIX-style signal
* S_SIGRETURN # return from a POSIX-style signal
* S_KILL # send a signal to a process
*/ */
#include "../system.h" #include "../system.h"

View file

@ -48,24 +48,24 @@ register message *m_ptr; /* pointer to request message */
phys_bytes caller_phys; /* physical address at caller */ phys_bytes caller_phys; /* physical address at caller */
phys_bytes kernel_phys; /* physical address in kernel */ phys_bytes kernel_phys; /* physical address in kernel */
/* Check if nr of ports is ok and get size of (port,value) data. */ /* Check if nr of ports is ok and get size of (port,value) data. */
if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL); if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL);
switch(m_ptr->DIO_TYPE) { switch(m_ptr->DIO_TYPE) {
case DIO_BYTE: case DIO_BYTE:
if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL); if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL);
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t)); bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t));
break; break;
case DIO_WORD: case DIO_WORD:
if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL); if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL);
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t)); bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t));
break; break;
case DIO_LONG: case DIO_LONG:
if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL); if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL);
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t)); bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t));
break; break;
default: /* this once and for all checks for a correct type */ default: /* this once and for all checks for a correct type */
return(EINVAL); return(EINVAL);
} }
/* Calculate physical addresses and copy (port,value)-pairs from user. */ /* Calculate physical addresses and copy (port,value)-pairs from user. */

View file

@ -1,9 +1,5 @@
/* This file contains a collection of miscellaneous procedures: /* This file contains a collection of miscellaneous procedures:
* panic abort MINIX due to a fatal error * panic abort MINIX due to a fatal error
* safe_lock lock the kernel, use in combination with safe_unlock
* safe_unlock unlock the kernel, but prevent breaking nested locks
* alloc_bit bit map manipulation
* free_bit bit map manipulation
*/ */
#include "kernel.h" #include "kernel.h"
@ -12,33 +8,6 @@
#include <minix/com.h> #include <minix/com.h>
PRIVATE int relock_count = 0;
/*===========================================================================*
* safe_lock *
*===========================================================================*/
PUBLIC void safe_lock(c,v)
int c;
char *v;
{
if(!(read_cpu_flags() & X86_FLAG_I)) {
relock_count++;
} else {
intr_disable();
}
}
/*===========================================================================*
* safe_unlock *
*===========================================================================*/
PUBLIC void safe_unlock(void)
{
if(! relock_count) {
intr_enable();
} else {
relock_count--;
}
}
/*===========================================================================* /*===========================================================================*
* panic * * panic *
@ -49,8 +18,7 @@ int n;
{ {
/* The system has run aground of a fatal kernel error. Terminate execution. */ /* The system has run aground of a fatal kernel error. Terminate execution. */
static int panicking = 0; static int panicking = 0;
if (panicking ++) /* prevent recursive panics */ if (panicking ++) return; /* prevent recursive panics */
return;
if (s != NULL) { if (s != NULL) {
kprintf("\nKernel panic: %s", karg(s)); kprintf("\nKernel panic: %s", karg(s));
@ -62,6 +30,7 @@ int n;
#if TEMP_CODE
/*===========================================================================* /*===========================================================================*
* free_bit * * free_bit *
@ -113,3 +82,4 @@ bit_t nr_bits;
return(-1); return(-1);
} }
#endif