From 198c976f7e723e4af706d7786e1546ab7ad7ffb9 Mon Sep 17 00:00:00 2001 From: Jorrit Herder Date: Tue, 19 Jul 2005 12:21:36 +0000 Subject: [PATCH] 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. --- kernel/clock.c | 29 ++++-------- kernel/config.h | 7 ++- kernel/const.h | 3 -- kernel/glo.h | 2 + kernel/i8259.c | 90 ++++++++++++++++++------------------ kernel/ipc.h | 3 +- kernel/klibc.c | 3 +- kernel/main.c | 3 ++ kernel/priv.h | 4 ++ kernel/proc.c | 28 +++++------ kernel/proc.h | 2 +- kernel/proto.h | 1 + kernel/sendmask.h | 44 ------------------ kernel/system.c | 69 +++++++++++++++------------ kernel/system.h | 6 +-- kernel/system/Makefile | 6 +-- kernel/system/do_abort.c | 14 +++--- kernel/system/do_alarm.c | 10 ++-- kernel/system/do_copy.c | 9 +--- kernel/system/do_endksig.c | 18 ++------ kernel/system/do_exec.c | 5 +- kernel/system/do_fork.c | 23 ++++----- kernel/system/do_getinfo.c | 61 ++++++++++++------------ kernel/system/do_getksig.c | 28 ++++------- kernel/system/do_irqctl.c | 33 ++++++------- kernel/system/do_kill.c | 43 +++++++++-------- kernel/system/do_newmap.c | 17 +++---- kernel/system/do_sdevio.c | 4 +- kernel/system/do_segctl.c | 16 +++---- kernel/system/do_sigreturn.c | 18 ++------ kernel/system/do_sigsend.c | 19 ++------ kernel/system/do_vdevio.c | 30 ++++++------ kernel/utility.c | 36 ++------------- 33 files changed, 289 insertions(+), 395 deletions(-) delete mode 100644 kernel/sendmask.h diff --git a/kernel/clock.c b/kernel/clock.c index e744e6742..d6039e4ac 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -7,10 +7,8 @@ * * Changes: * 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 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 * 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 /* The CLOCK's timers queue. The functions in operate on this. - * The process structure contains one timer per type of alarm (SIGNALRM, - * SYNCALRM, and FLAGALRM), which means that a process can have a single - * outstanding timer for each alarm type. - * If other kernel parts want to use additional timers, they must declare - * their own persistent timer structure, which can be passed to the clock + * All system processes possess a single synchronous alarm timer. If other + * kernel parts want to use additional timers, they must declare their own + * persistent (static) timer structure, which can be passed to the clock * via (re)set_timer(). * When a timer expires its watchdog function is run by the CLOCK task. */ PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */ 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 clock on each clock tick. The boot time is set by a utility program - * after system startup to prevent troubles reading the CMOS. - */ +/* The time is incremented by the interrupt handler on each clock tick. */ PRIVATE clock_t realtime; /* real time clock */ - -/* Variables for and changed by the CLOCK's interrupt handler. */ -PRIVATE irq_hook_t clock_hook; +PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */ /*===========================================================================* @@ -86,12 +77,12 @@ PRIVATE irq_hook_t clock_hook; *===========================================================================*/ PUBLIC void clock_task() { -/* Main program of clock task. It corrects realtime by adding pending ticks - * seen only by the interrupt service, then it determines which call this is - * by looking at the message type and dispatches. +/* Main program of clock task. It determines which call this is by looking at + * the message type and dispatches. */ message m; /* message buffer for both input and output */ - int result; + int result; /* result returned by the handler */ + init_clock(); /* initialize clock task */ /* Main loop of the clock task. Get work, process it, sometimes reply. */ @@ -297,11 +288,9 @@ PUBLIC unsigned long read_clock() */ unsigned count; - /* lock(10, "read_clock"); */ outb(TIMER_MODE, LATCH_COUNT); count = inb(TIMER0); count |= (inb(TIMER0) << 8); - /* unlock(10); */ return count; } diff --git a/kernel/config.h b/kernel/config.h index a15ed0313..31e7e6bc6 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -34,7 +34,7 @@ #define USE_IRQCTL 1 /* set an interrupt policy */ #define USE_SEGCTL 1 /* set up a remote segment */ #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_VIRCOPY 1 /* copy using virtual addressing */ #define USE_VIRVCOPY 1 /* vector with virtual copy requests */ @@ -70,8 +70,13 @@ #define VDEVIO_BUF_SIZE 64 /* max elements per VDEVIO request */ #define VCOPY_VEC_SIZE 16 /* max elements per VCOPY request */ +#if TEMP_CODE /* How many buffers for notification messages should there be? */ #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. diff --git a/kernel/const.h b/kernel/const.h index b5be5cc83..477491fca 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -20,9 +20,6 @@ #define structof(type, field, ptr) \ ((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. */ #define _SRC_ 0 #define _DST_ 1 diff --git a/kernel/glo.h b/kernel/glo.h index a8711d0f5..94fb59432 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -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 unsigned lost_ticks; /* clock ticks counted outside clock task */ +#if TEMP_CODE /* Declare buffer space and a bit map for notification messages. */ EXTERN struct notification notify_buffer[NR_NOTIFY_BUFS]; EXTERN bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)]; +#endif #if (CHIP == INTEL) diff --git a/kernel/i8259.c b/kernel/i8259.c index 04f96f74d..71d0f3bbb 100755 --- a/kernel/i8259.c +++ b/kernel/i8259.c @@ -51,39 +51,39 @@ int mine; intr_disable(); if (machine.protected) { - /* 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 - * has just one controller, because it must run in real mode.) - */ - outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); - outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC); + /* 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 + * has just one controller, because it must run in real mode.) + */ + outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); + outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC); /* ICW2 for master */ - outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */ - outb(INT_CTLMASK, ICW4_AT_MASTER); - outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ - outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); - outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC); + outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */ + outb(INT_CTLMASK, ICW4_AT_MASTER); + outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ + outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); + outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC); /* ICW2 for slave */ - outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ - outb(INT2_CTLMASK, ICW4_AT_SLAVE); - outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ + outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ + outb(INT2_CTLMASK, ICW4_AT_SLAVE); + outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ - /* Copy the BIOS vectors from the BIOS to the Minix location, so we - * can still make BIOS calls without reprogramming the i8259s. - */ + /* Copy the BIOS vectors from the BIOS to the Minix location, so we + * can still make BIOS calls without reprogramming the i8259s. + */ #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 #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 } else { - /* Use the BIOS interrupt vectors in real mode. We only reprogram the - * exceptions here, the interrupt vectors are reprogrammed on demand. - * SYS_VECTOR is the Minix system call for message passing. - */ - for (i = 0; i < 8; i++) set_vec(i, int_vec[i]); - set_vec(SYS_VECTOR, s_call); + /* Use the BIOS interrupt vectors in real mode. We only reprogram the + * exceptions here, the interrupt vectors are reprogrammed on demand. + * SYS_VECTOR is the Minix system call for message passing. + */ + for (i = 0; i < 8; i++) set_vec(i, int_vec[i]); + set_vec(SYS_VECTOR, s_call); } } @@ -100,14 +100,14 @@ irq_handler_t handler; irq_hook_t **line; 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]; id = 1; while (*line != NULL) { - if (hook == *line) return; /* extra initialization */ - line = &(*line)->next; - id <<= 1; + if (hook == *line) return; /* extra initialization */ + line = &(*line)->next; + id <<= 1; } if (id == 0) panic("Too many handlers for irq", irq); @@ -130,22 +130,20 @@ int id; /* Unregister an interrupt handler. */ irq_hook_t **line; - if (irq < 0 || irq >= NR_IRQ_VECTORS) { - return EINVAL; - } + if (irq < 0 || irq >= NR_IRQ_VECTORS) return(EINVAL); line = &irq_handlers[irq]; while (*line != NULL) { - if((*line)->id == id) { - (*line) = (*line)->next; - if(!irq_handlers[irq]) - irq_use &= ~(1 << irq); - return OK; - } - line = &(*line)->next; + if((*line)->id == id) { + (*line) = (*line)->next; + if(! irq_handlers[irq]) + irq_use &= ~(1 << irq); + return(OK); + } + line = &(*line)->next; } - return ENOENT; + return(ENOENT); } /*==========================================================================* @@ -161,12 +159,12 @@ irq_hook_t *hook; /* Call list of handlers for an IRQ. */ while (hook != NULL) { - /* 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. - */ - irq_actids[hook->irq] |= hook->id; - if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id; - hook = hook->next; + /* 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. + */ + irq_actids[hook->irq] |= hook->id; + if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id; + hook = hook->next; } /* The assembly code will now disable interrupts, unmask the IRQ if and only diff --git a/kernel/ipc.h b/kernel/ipc.h index cb9d8f7b3..1540e8c9b 100644 --- a/kernel/ipc.h +++ b/kernel/ipc.h @@ -18,9 +18,8 @@ /* Call masks indicating which system calls a process can make. */ #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 USER_CALL_MASK (~0) #endif /* IPC_H */ diff --git a/kernel/klibc.c b/kernel/klibc.c index 1c3cbd2d7..113ae5856 100644 --- a/kernel/klibc.c +++ b/kernel/klibc.c @@ -20,6 +20,7 @@ #include "kernel.h" +#include #include #define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10) @@ -159,7 +160,7 @@ int c; /* character to append */ kmess.km_size += 1; kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE; } else { - lock_alert(SYSTEM, PRINTF_PROC); + send_sig(PRINTF_PROC, SIGKMESS); } } diff --git a/kernel/main.c b/kernel/main.c index 13c3602f6..27cedbe3d 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -201,6 +201,9 @@ int how; /* reason to shut down */ 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 * occurred. This is done by setting a timer. The timer argument passes * the shutdown status. diff --git a/kernel/priv.h b/kernel/priv.h index 2d0281719..37dc89254 100755 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -26,6 +26,7 @@ struct priv { sys_map_t s_notify_pending; /* bit map with pending notifications */ short s_int_pending; /* pending hardware interrupts */ + sigset_t s_sig_pending; /* pending signals */ timer_t s_alarm_timer; /* synchronous alarm timer */ 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 *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 * the system privileges table is large enough for the number of processes * in the boot image. diff --git a/kernel/proc.c b/kernel/proc.c index 4f3c53418..70cf8a7d0 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -62,19 +62,27 @@ FORWARD _PROTOTYPE( void sched, (struct proc *rp) ); FORWARD _PROTOTYPE( void pick_proc, (void) ); +#if TEMP_CODE #define BuildOldMess(m,n) \ (m).NOTIFY_SOURCE = (n)->n_source, \ (m).NOTIFY_TYPE = (n)->n_type, \ (m).NOTIFY_FLAGS = (n)->n_flags, \ (m).NOTIFY_ARG = (n)->n_arg; +#endif #define BuildMess(m_ptr, src, dst_ptr) \ (m_ptr)->m_source = (src); \ (m_ptr)->m_type = NOTIFY_FROM(src); \ (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ - if ((src) == HARDWARE) { \ + switch (src) { \ + case HARDWARE: \ (m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \ 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) @@ -123,24 +131,16 @@ message *m_ptr; /* pointer to message in the caller's space */ return(EBADSRCDST); #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. * It will have to be made more elaborate later for machines which * 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 || vhi >= caller_ptr->p_memmap[S].mem_vir + caller_ptr->p_memmap[S].mem_len) 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 /* 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; case NOTIFY: result = mini_notify(caller_ptr, src_dst, m_ptr); +#if TEMP_CODE break; case ECHO: 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); result = OK; 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 * 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) && ! (flags & NON_BLOCKING) && (result == OK)) { caller_ptr->p_priority = caller_ptr->p_max_priority; diff --git a/kernel/proc.h b/kernel/proc.h index dc5c7f096..e1050e159 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -87,7 +87,7 @@ struct proc { #define BEG_USER_ADDR (&proc[NR_TASKS]) #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 proc_addr(n) (pproc_addr + NR_TASKS)[(n)] #define proc_nr(p) ((p)->p_nr) diff --git a/kernel/proto.h b/kernel/proto.h index 9605aa18a..cef1817e7 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -50,6 +50,7 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds, U16_t parmoff, U16_t parmsize) ); /* system.c */ +_PROTOTYPE( void send_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( void clear_proc, (int proc_nr) ); diff --git a/kernel/sendmask.h b/kernel/sendmask.h deleted file mode 100644 index 729b522b7..000000000 --- a/kernel/sendmask.h +++ /dev/null @@ -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 */ - diff --git a/kernel/system.c b/kernel/system.c index ab4fd6b86..1f965e382 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -11,7 +11,8 @@ * * In addition to the main sys_task() entry point, which starts the main loop, * 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 * umap_local: map virtual address in LOCAL_SEG to physical * umap_remote: map virtual address in REMOTE_SEG to physical @@ -78,9 +79,6 @@ PUBLIC void sys_task() /* Handle the request. */ if ((unsigned) m.m_type < NR_SYS_CALLS) { 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 { kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source); 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_EXEC, do_exec); /* update process after execute */ 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 */ /* Signal handling. */ @@ -153,7 +152,8 @@ PRIVATE void initialize(void) map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */ /* 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_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_PHYSVCOPY, do_physvcopy); /* vector with copy requests */ 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) { i = (int) (rc->p_ntf_q - ¬ify_buffer[0]); free_bit(i, notify_bitmap, NR_NOTIFY_BUFS); +#if TEMP_CODE rc->p_ntf_q = rc->p_ntf_q->n_next; } - - /* Now clean up the process table entry. Reset to defaults. */ - kstrncpy(rc->p_name, "", 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 + + /* 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 * *===========================================================================*/ @@ -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 * process being signaled is blocked while PM has not finished all signals * for it. - * It is not sufficient to ready the process when PM is informed, because - * PM can block waiting for FS to do a core dump. + * Race conditions between calls to this function and the system calls that + * 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; @@ -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 == 0) lock_unready(rp); /* make not ready */ 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; /* Check copy count. */ - if (bytes <= 0) { - kprintf("v_cp: copy count problem <= 0\n", NO_NUM); - return(EDOM); - } + if (bytes <= 0) return(EDOM); /* Do some more checks and map virtual addresses to physical addresses. */ vir_addr[_SRC_] = src_addr; @@ -539,16 +554,12 @@ vir_bytes bytes; /* # of bytes to copy */ phys_addr[i] = vir_addr[i]->offset; break; default: - kprintf("v_cp: Unknown segment type: %d\n", - vir_addr[i]->segment & SEGMENT_TYPE); return(EINVAL); } /* Check if mapping succeeded. */ - if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) { - kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_NUM); + if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) return(EFAULT); - } } /* Now copy bytes between physical addresseses. */ diff --git a/kernel/system.h b/kernel/system.h index c787f5683..099e81dfd 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -43,9 +43,9 @@ _PROTOTYPE( int do_trace, (message *m_ptr) ); #define do_trace do_unused #endif -_PROTOTYPE( int do_schedctl, (message *m_ptr) ); -#if ! USE_SCHEDCTL -#define do_schedctl do_unused +_PROTOTYPE( int do_nice, (message *m_ptr) ); +#if ! USE_NICE +#define do_nice do_unused #endif _PROTOTYPE( int do_copy, (message *m_ptr) ); diff --git a/kernel/system/Makefile b/kernel/system/Makefile index d81ad887a..a9d3d72c9 100644 --- a/kernel/system/Makefile +++ b/kernel/system/Makefile @@ -23,7 +23,7 @@ OBJECTS = \ $(SYSTEM)(do_newmap.o) \ $(SYSTEM)(do_exit.o) \ $(SYSTEM)(do_trace.o) \ - $(SYSTEM)(do_schedctl.o) \ + $(SYSTEM)(do_nice.o) \ $(SYSTEM)(do_times.o) \ $(SYSTEM)(do_alarm.o) \ $(SYSTEM)(do_irqctl.o) \ @@ -75,8 +75,8 @@ $(SYSTEM)(do_exit.o): do_exit.c $(SYSTEM)(do_trace.o): do_trace.c $(CC) do_trace.c -$(SYSTEM)(do_schedctl.o): do_schedctl.c - $(CC) do_schedctl.c +$(SYSTEM)(do_nice.o): do_nice.c + $(CC) do_nice.c $(SYSTEM)(do_times.o): do_times.c $(CC) do_times.c diff --git a/kernel/system/do_abort.c b/kernel/system/do_abort.c index 3a68bc8d7..e34c2efca 100644 --- a/kernel/system/do_abort.c +++ b/kernel/system/do_abort.c @@ -1,7 +1,3 @@ -#include "../system.h" -#include - - /* The system call implemented in this file: * m_type: SYS_ABORT * @@ -11,6 +7,10 @@ * m1_i3: ABRT_MON_LEN (length of monitor params) * m1_p1: ABRT_MON_ADDR (virtual address of params) */ + +#include "../system.h" +#include + #if USE_ABORT /*===========================================================================* @@ -24,7 +24,7 @@ message *m_ptr; /* pointer to request message */ * or ESC after debugging dumps). */ int how = m_ptr->ABRT_HOW; - + if (how == RBT_MONITOR) { /* The monitor is to run the specified instructions. */ 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); /* Validate length and address of shutdown code before copying. */ - if (length > kinfo.params_size || src_phys == 0) - phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11); + if (length > kinfo.params_size || src_phys == 0) + phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11); else phys_copy(src_phys, kinfo.params_base, (phys_bytes) length); } diff --git a/kernel/system/do_alarm.c b/kernel/system/do_alarm.c index a1d6c4ef8..3f52e2e97 100644 --- a/kernel/system/do_alarm.c +++ b/kernel/system/do_alarm.c @@ -5,10 +5,10 @@ * m2_i1: ALRM_PROC_NR (set alarm for this process) * m2_l1: ALRM_EXP_TIME (alarm's expiration time) * 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: - * 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" @@ -40,10 +40,10 @@ message *m_ptr; /* pointer to request message */ /* Get the timer structure and set the parameters for this alarm. */ tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer); 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. */ - uptime = get_uptime(); + uptime = get_uptime(); if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) { m_ptr->ALRM_TIME_LEFT = 0; } else { @@ -69,7 +69,7 @@ timer_t *tp; { /* 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 - * process given with a SYN_ALARM message. + * process with a notification message from CLOCK. */ lock_alert(CLOCK, tmr_arg(tp)->ta_int); } diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c index d6975012c..b2bce2c68 100644 --- a/kernel/system/do_copy.c +++ b/kernel/system/do_copy.c @@ -45,10 +45,8 @@ register message *m_ptr; /* pointer to request message */ /* 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 (! 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); + if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) return(EINVAL); - } /* Check if physical addressing is used without SYS_PHYSCOPY. */ 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 * vir_bytes. Especially copying by the PM on do_fork() is affected. */ - if (bytes != (vir_bytes) bytes) { - kprintf("do_vircopy: overflow\n", NO_NUM); - return(E2BIG); - } + if (bytes != (vir_bytes) bytes) return(E2BIG); /* Now try to make the actual virtual copy. */ return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) ); diff --git a/kernel/system/do_endksig.c b/kernel/system/do_endksig.c index e2babbfad..6f046364d 100644 --- a/kernel/system/do_endksig.c +++ b/kernel/system/do_endksig.c @@ -1,20 +1,8 @@ /* 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: - * SIG_REQUEST # request to perform (long) - * 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 + * The parameters for this system call are: + * m2_i1: SIG_PROC # process for which PM is done */ #include "../system.h" diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index d5e0635ce..c8db74a28 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -3,7 +3,9 @@ * * The parameters for this system call are: * m1_i1: PR_PROC_NR (process that did exec call) +#if DEAD_CODE * m1_i3: PR_TRACING (flag to indicate tracing is on/ off) +#endif * m1_p1: PR_STACK_PTR (new stack pointer) * m1_p2: PR_NAME_PTR (pointer to program name) * 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 */ { /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ - register struct proc *rp; reg_t sp; /* new sp */ phys_bytes phys_name; char *np; rp = proc_addr(m_ptr->PR_PROC_NR); +#if DEAD_CODE if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP); +#endif sp = (reg_t) m_ptr->PR_STACK_PTR; rp->p_reg.sp = sp; /* set the stack pointer */ #if (CHIP == M68000) diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index 8afdcd4eb..baf722ba1 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -26,25 +26,26 @@ register message *m_ptr; /* pointer to request message */ #if (CHIP == INTEL) reg_t old_ldt_sel; #endif - register struct proc *rpc; - struct proc *rpp; + register struct proc *rpc; /* child process pointer */ + struct proc *rpp; /* parent process pointer */ rpp = proc_addr(m_ptr->PR_PPROC_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) - old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */ -#endif - - *rpc = *rpp; /* copy 'proc' struct */ - -#if (CHIP == INTEL) - rpc->p_ldt_sel = old_ldt_sel; + old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */ + *rpc = *rpp; /* copy 'proc' struct */ + rpc->p_ldt_sel = old_ldt_sel; /* restore descriptors */ +#else + *rpc = *rpp; /* copy 'proc' struct */ #endif rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ + +#if TEMP_CODE rpc->p_ntf_q = NULL; /* remove pending notifications */ +#endif /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index ee0cc9f63..936ec2f06 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -6,8 +6,8 @@ * m1_i4: I_PROC_NR (process to store value at) * m1_p1: I_VAL_PTR (where to put it) * m1_i1: I_VAL_LEN (maximum length expected, optional) - * m1_p2: I_KEY_PTR (environment variable key) - * m1_i2: I_KEY_LEN (lenght of environment variable key) + * m1_p2: I_VAL_PTR2 (second, optional pointer) + * m1_i2: I_VAL_LEN2 (second length or process nr) * * Author: * Jorrit N. Herder @@ -29,26 +29,26 @@ register message *m_ptr; /* pointer to request message */ phys_bytes dst_phys; 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) { case GET_MACHINE: { - length = sizeof(struct machine); - src_phys = vir2phys(&machine); - break; + length = sizeof(struct machine); + src_phys = vir2phys(&machine); + break; } case GET_KINFO: { - length = sizeof(struct kinfo); - src_phys = vir2phys(&kinfo); - break; + length = sizeof(struct kinfo); + src_phys = vir2phys(&kinfo); + break; } case GET_IMAGE: { - length = sizeof(struct system_image) * NR_BOOT_PROCS; - src_phys = vir2phys(image); + length = sizeof(struct system_image) * NR_BOOT_PROCS; + src_phys = vir2phys(image); break; } case GET_IRQHOOKS: { - length = sizeof(struct irq_hook) * NR_IRQ_HOOKS; - src_phys = vir2phys(irq_hooks); + length = sizeof(struct irq_hook) * NR_IRQ_HOOKS; + src_phys = vir2phys(irq_hooks); break; } case GET_SCHEDINFO: { @@ -58,37 +58,36 @@ register message *m_ptr; /* pointer to request message */ */ length = sizeof(struct proc *) * NR_SCHED_QUEUES; src_phys = vir2phys(rdy_head); - dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_KEY_PTR, - length); + dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_VAL_PTR2, + length); if (src_phys == 0 || dst_phys == 0) return(EFAULT); phys_copy(src_phys, dst_phys, length); /* fall through */ } case GET_PROCTAB: { - length = sizeof(struct proc) * (NR_PROCS + NR_TASKS); - src_phys = vir2phys(proc); + length = sizeof(struct proc) * (NR_PROCS + NR_TASKS); + src_phys = vir2phys(proc); break; } case GET_PRIVTAB: { - length = sizeof(struct priv) * (NR_SYS_PROCS); - src_phys = vir2phys(priv); + length = sizeof(struct priv) * (NR_SYS_PROCS); + src_phys = vir2phys(priv); break; } case GET_PROC: { - nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN; - if (! isokprocn(nr)) return(EINVAL); /* validate request */ - length = sizeof(struct proc); - src_phys = vir2phys(proc_addr(nr)); + nr = (m_ptr->I_VAL_LEN2 == SELF) ? m_ptr->m_source : m_ptr->I_VAL_LEN2; + if (! isokprocn(nr)) return(EINVAL); /* validate request */ + length = sizeof(struct proc); + src_phys = vir2phys(proc_addr(nr)); break; } case GET_MONPARAMS: { - src_phys = kinfo.params_base; /* already is a physical */ - length = kinfo.params_size; - break; + src_phys = kinfo.params_base; /* already is a physical */ + length = kinfo.params_size; + break; } case GET_RANDOMNESS: { - static struct randomness copy; /* copy to keep counters */ - + static struct randomness copy; /* copy to keep counters */ int i; copy = krandom; @@ -107,9 +106,9 @@ register message *m_ptr; /* pointer to request message */ } #if DEBUG_TIME_LOCKS case GET_LOCKTIMING: { - length = sizeof(timingdata); - src_phys = vir2phys(timingdata); - break; + length = sizeof(timingdata); + src_phys = vir2phys(timingdata); + break; } #endif default: diff --git a/kernel/system/do_getksig.c b/kernel/system/do_getksig.c index 51e5bfcfb..8e3d0fe64 100644 --- a/kernel/system/do_getksig.c +++ b/kernel/system/do_getksig.c @@ -1,20 +1,10 @@ /* 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: - * SIG_REQUEST # request to perform (long) - * 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) + * The parameters for this system call are: + * m2_i1: SIG_PROC # process with pending signals + * m2_l1: SIG_MAP # bit map with pending signals * - * 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" @@ -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 * one. Find a process with pending signals. If no signals are available, * 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; /* Find the next process with pending signals. */ for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { if (rp->p_rts_flags & SIGNALED) { - m_ptr->SIG_PROC = rp->p_nr; - m_ptr->SIG_MAP = rp->p_pending; - sigemptyset(&rp->p_pending); /* ball is in PM's court */ - rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ + m_ptr->SIG_PROC = rp->p_nr; /* store signaled process */ + m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */ + sigemptyset(&rp->p_pending); /* ball is in PM's court */ + rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ return(OK); } } diff --git a/kernel/system/do_irqctl.c b/kernel/system/do_irqctl.c index 618c07f83..a30a06895 100644 --- a/kernel/system/do_irqctl.c +++ b/kernel/system/do_irqctl.c @@ -37,15 +37,15 @@ register message *m_ptr; /* pointer to request message */ /* Enable or disable IRQs. This is straightforward. */ case IRQ_ENABLE: case IRQ_DISABLE: - if (irq_hook_id >= NR_IRQ_HOOKS || - irq_hooks[irq_hook_id].proc_nr == NONE) return(EINVAL); + if (irq_hook_id >= NR_IRQ_HOOKS || + 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 (m_ptr->IRQ_REQUEST == IRQ_ENABLE) enable_irq(&irq_hooks[irq_hook_id]); else disable_irq(&irq_hooks[irq_hook_id]); break; - + /* 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. @@ -53,10 +53,7 @@ register message *m_ptr; /* pointer to request message */ case IRQ_SETPOLICY: /* Check if IRQ line is acceptable. */ - if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) { - kprintf("ST: irq line %d is not acceptable!\n", irq_vec); - return(EINVAL); - } + if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL); /* Find a free IRQ hook for this mapping. */ hook_ptr = NULL; @@ -77,18 +74,16 @@ register message *m_ptr; /* pointer to request message */ m_ptr->IRQ_HOOK_ID = irq_hook_id + 1; break; - case IRQ_RMPOLICY: - if (irq_hook_id >= NR_IRQ_HOOKS || - irq_hooks[irq_hook_id].proc_nr == NONE) { - r = EINVAL; - } else { - if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { - r = EPERM; - } else { - r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id); - } - } - break; + case IRQ_RMPOLICY: + if (irq_hook_id >= NR_IRQ_HOOKS || + irq_hooks[irq_hook_id].proc_nr == NONE) { + return(EINVAL); + } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { + return(EPERM); + } else { + r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id); + } + break; default: r = EINVAL; /* invalid IRQ_REQUEST */ diff --git a/kernel/system/do_kill.c b/kernel/system/do_kill.c index 0b33cc90f..9f8a248f4 100644 --- a/kernel/system/do_kill.c +++ b/kernel/system/do_kill.c @@ -1,20 +1,9 @@ /* 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: - * SIG_REQUEST # request to perform (long) - * 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 + * The parameters for this system call are: + * m2_i1: SIG_PROC # process to signal/ pending + * m2_i2: SIG_NUMBER # signal number to send to process */ #include "../system.h" @@ -29,11 +18,27 @@ PUBLIC int do_kill(m_ptr) message *m_ptr; /* pointer to request message */ { -/* Handle sys_kill(). Cause a signal to be sent to a process via PM. - * Note that this has nothing to do with the kill (2) system call, this - * is how the FS (and possibly other servers) get access to cause_sig. +/* Handle sys_kill(). Cause a signal to be sent to a process. The PM is the + * central server where all signals are processed and handler policies can + * 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); } diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c index 60d712bfb..74048d9d6 100644 --- a/kernel/system/do_newmap.c +++ b/kernel/system/do_newmap.c @@ -3,7 +3,7 @@ * * The parameters for this system call are: * 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" @@ -16,24 +16,21 @@ PUBLIC int do_newmap(m_ptr) message *m_ptr; /* pointer to request message */ { /* Handle sys_newmap(). Fetch the memory map from PM. */ - - register struct proc *rp; - phys_bytes src_phys; + register struct proc *rp; /* process whose map is to be loaded */ 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) */ + 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. */ caller = m_ptr->m_source; - k = m_ptr->PR_PROC_NR; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; - if (!isokprocn(k)) return(EINVAL); - rp = proc_addr(k); /* ptr to entry of user getting new map */ + if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL); + rp = proc_addr(m_ptr->PR_PROC_NR); /* Copy the map from PM. */ 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); phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); diff --git a/kernel/system/do_sdevio.c b/kernel/system/do_sdevio.c index cc723bcf6..58ea4fd57 100644 --- a/kernel/system/do_sdevio.c +++ b/kernel/system/do_sdevio.c @@ -44,8 +44,8 @@ register message *m_ptr; /* pointer to request message */ } } else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) { switch (m_ptr->DIO_TYPE) { - case DIO_BYTE: phys_outsb(port, phys_buf, count); break; - case DIO_WORD: phys_outsw(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; default: return(EINVAL); } } diff --git a/kernel/system/do_segctl.c b/kernel/system/do_segctl.c index 0b39813e4..5d1060097 100644 --- a/kernel/system/do_segctl.c +++ b/kernel/system/do_segctl.c @@ -37,13 +37,13 @@ register message *m_ptr; /* pointer to request message */ rp = proc_addr(m_ptr->m_source); index = -1; for (i=0; i < NR_REMOTE_SEGS; i++) { - if (! rp->p_priv->s_farmem[i].in_use) { - index = i; - 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_len = size; - break; - } + if (! rp->p_priv->s_farmem[i].in_use) { + index = i; + 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_len = size; + break; + } } if (index < 0) return(ENOSPC); @@ -63,7 +63,7 @@ register message *m_ptr; /* pointer to request message */ USER_PRIVILEGE); selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; offset = 0; - result = OK; + result = OK; } else { init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0, USER_PRIVILEGE); diff --git a/kernel/system/do_sigreturn.c b/kernel/system/do_sigreturn.c index d7abab433..e3d131ed9 100644 --- a/kernel/system/do_sigreturn.c +++ b/kernel/system/do_sigreturn.c @@ -1,20 +1,10 @@ /* 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: - * SIG_REQUEST # request to perform (long) - * 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) + * The parameters for this system call are: + * m2_i1: SIG_PROC # process returning from handler + * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure * - * 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" diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index 88c35469c..0656a4cac 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -1,20 +1,11 @@ /* 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: - * SIG_REQUEST # request to perform (long) - * 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) + * The parameters for this system call are: + * m2_i1: SIG_PROC # process to call signal handler + * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure + * m2_i3: SIG_FLAGS # flags for S_SIGRETURN call * - * 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" diff --git a/kernel/system/do_vdevio.c b/kernel/system/do_vdevio.c index 5b94870d1..e7ecb2549 100644 --- a/kernel/system/do_vdevio.c +++ b/kernel/system/do_vdevio.c @@ -48,24 +48,24 @@ register message *m_ptr; /* pointer to request message */ phys_bytes caller_phys; /* physical address at caller */ phys_bytes kernel_phys; /* physical address in kernel */ - + /* Check if nr of ports is ok and get size of (port,value) data. */ if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL); switch(m_ptr->DIO_TYPE) { - case DIO_BYTE: - if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL); - bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t)); - break; - case DIO_WORD: - if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL); - bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t)); - break; - case DIO_LONG: - if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL); - bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t)); - break; - default: /* this once and for all checks for a correct type */ - return(EINVAL); + case DIO_BYTE: + if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL); + bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t)); + break; + case DIO_WORD: + if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL); + bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t)); + break; + case DIO_LONG: + if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL); + bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t)); + break; + default: /* this once and for all checks for a correct type */ + return(EINVAL); } /* Calculate physical addresses and copy (port,value)-pairs from user. */ diff --git a/kernel/utility.c b/kernel/utility.c index 5835f8cc5..7d8753fa4 100755 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -1,9 +1,5 @@ /* This file contains a collection of miscellaneous procedures: * 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" @@ -12,33 +8,6 @@ #include -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 * @@ -49,8 +18,7 @@ int n; { /* The system has run aground of a fatal kernel error. Terminate execution. */ static int panicking = 0; - if (panicking ++) /* prevent recursive panics */ - return; + if (panicking ++) return; /* prevent recursive panics */ if (s != NULL) { kprintf("\nKernel panic: %s", karg(s)); @@ -62,6 +30,7 @@ int n; +#if TEMP_CODE /*===========================================================================* * free_bit * @@ -113,3 +82,4 @@ bit_t nr_bits; return(-1); } +#endif