sys_privctl() call to dynamically start servers and drivers.
- Shutdown sequence slightly adjusted: called as watchdog timer to let the
busy sys_abort() call from the PM return first.
- Changed umap_bios() to have more restrictive check: BIOS memory is now
allowed in BIOS_MEM_BEGIN to END (interrupt vectors) and BASE_MEM_TOP
to UPPER_MEM_END. Hopefully this keeps QEMU and Bochs happy.
#define USE_SDEVIO 1 /* perform I/O request on a buffer */
#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_PRIVCTL 1 /* system privileges control */
#define USE_NICE 1 /* change scheduling priority */
#define USE_UMAP 1 /* map virtual to physical address */
#define USE_VIRCOPY 1 /* copy using virtual addressing */
for (i=0; i < NR_BOOT_PROCS; ++i) {
ip = &image[i]; /* process' attributes */
rp = proc_addr(ip->proc_nr); /* get process pointer */
- (void) init_proc(rp, NIL_SYS_PROC);
-#if DEAD_CODE
- (ip->flags & SYS_PROC) ?
- NIL_SYS_PROC : NIL_PROC); /* initialize new process */
-#endif
- strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */
rp->p_max_priority = ip->priority; /* max scheduling priority */
rp->p_priority = ip->priority; /* current priority */
rp->p_quantum_size = ip->quantum; /* quantum size in ticks */
rp->p_sched_ticks = ip->quantum; /* current credit */
- rp->p_full_quantums = QUANTUMS(ip->priority); /* quantums left */
+ rp->p_full_quantums = QUANTUMS(ip->priority); /* nr quantums left */
+ strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
+ (void) set_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */
rp->p_priv->s_flags = ip->flags; /* process flags */
rp->p_priv->s_call_mask = ip->call_mask;/* allowed system calls */
if (i-NR_TASKS < 0) { /* part of the kernel? */
/*==========================================================================*
* prepare_shutdown *
*==========================================================================*/
-PUBLIC void prepare_shutdown(how)
-int how; /* reason to shut down */
+PUBLIC void prepare_shutdown(tp)
+timer_t *tp;
{
-/* This function prepares to shutdown MINIX. It uses a global flag to make
- * sure it is only executed once. Unless a CPU exception occurred, the
+/* This function prepares to shutdown MINIX. It is called by a watchdog
+ * timer if this is a normal abort so that the sys_abort() call can return
+ * first. The timer structure passes the shutdown status as an argument.
*/
- static timer_t shutdown_timer; /* timer for watchdog function */
register struct proc *rp;
+ static timer_t shutdown_timer;
+ int how = tmr_arg(tp)->ta_int;
message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still
* run their shutdown code, e.g, to synchronize the FS or to let the TTY
* switch to the first console.
*/
+ kprintf("Sending SIGKSTOP to system processes ...\n");
for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
- if (! isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && ! iskernelp(rp))
+ if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !iskernelp(rp))
send_sig(proc_nr(rp), SIGKSTOP);
}
* scheduled by setting a watchog timer that calls shutdown(). The timer
* argument passes the shutdown status.
*/
- kprintf("Informed system about upcoming shutdown with SIGKSTOP signal.\n");
- kprintf("Time for cleanup is allowed. MINIX will now be brought down.\n");
- tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
+ kprintf("MINIX will now be shut down ...\n");
+ tmr_arg(&shutdown_timer)->ta_int = how;
set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
}
return(OK); /* report success */
}
+#if TEMP_CODE
ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
while (*ntf_q_pp != NULL) {
if (src == ANY || src == (*ntf_q_pp)->n_source) {
ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
}
}
+#endif
/* Check caller queue. Use pointer pointers to keep code simple. */
xpp = &caller_ptr->p_caller_q;
#define SIGNALED 0x10 /* set when new kernel signal arrives */
#define SIG_PENDING 0x20 /* unready while signal being processed */
#define P_STOP 0x40 /* set when process is being traced */
-#define NO_PRIV 0x80 /* privilege structure not yet initialized */
/* Scheduling priorities for p_priority. Values must start at zero (highest
* priority) and increment. Priorities of the processes in the boot image can
/* main.c */
_PROTOTYPE( void main, (void) );
-_PROTOTYPE( void prepare_shutdown, (int how) );
-_PROTOTYPE( void stop_sequence, (struct timer *tp) );
+_PROTOTYPE( void prepare_shutdown, (struct timer *tp) );
/* utility.c */
_PROTOTYPE( void kprintf, (const char *fmt, ...) );
/* 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, (register struct proc *rc, struct proc *rp) );
-_PROTOTYPE( void clear_proc, (register struct proc *rc) );
+_PROTOTYPE( int set_priv, (register struct proc *rc,int sys_proc_flag) );
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( void sys_task, (void) );
*
* In addition to the main sys_task() entry point, which starts the main loop,
* there are several other minor entry points:
- * send_sig: send signal directly to a system process
+ * set_priv: assign privilege structure to user or system process
+ * send_sig: send a signal directly to a system process
* cause_sig: take action to cause a signal to occur via PM
- * init_proc: initialize a process, during start up or fork
- * 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
* umap_bios: map virtual address in BIOS_SEG to physical
* generic_handler: interrupt handler for user-level device drivers
*
* Changes:
- * Apr 25, 2005 new init_proc() function (Jorrit N. Herder)
* Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
- * Oct 29, 2004 new clear_proc() function (Jorrit N. Herder)
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
* Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
#include <signal.h>
#include <unistd.h>
#include <sys/sigcontext.h>
-#include <sys/svrctl.h>
#if (CHIP == INTEL)
#include <ibm/memory.h>
#include "protect.h"
call_vec[i] = do_unused;
}
- /* Process management. */
map(SYS_FORK, do_fork); /* a process forked a new process */
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
map(SYS_EXEC, do_exec); /* update process after execute */
/* System control. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
+ map(SYS_PRIVCTL, do_privctl); /* system privileges control */
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
- map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
/* Copying. */
map(SYS_UMAP, do_umap); /* map virtual to physical address */
/*===========================================================================*
- * init_proc *
+ * set_priv *
*===========================================================================*/
-PUBLIC int init_proc(rc, rp)
+PUBLIC int set_priv(rc, proc_type)
register struct proc *rc; /* new (child) process pointer */
-struct proc *rp; /* prototype (parent) process */
+int proc_type; /* system or user process flag */
{
- register struct priv *sp; /* process' privilege structure */
- int i;
-
- /* If there is a prototype process to initialize from, use it. Otherwise,
- * assume the caller will take care of initialization, but make sure that
- * the new process gets a pointer to a system properties structure.
- */
- if (rp == NIL_PROC) { /* new user process */
- kprintf("init_proc() for new user proc %d\n", proc_nr(rc));
- sp = &priv[USER_PRIV_ID];
- sp->s_proc_nr = ANY; /* misuse for users */
- rc->p_priv = sp; /* assign to process */
- return(OK);
- } else if (rp == NIL_SYS_PROC) { /* new system process */
- for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
- if (sp->s_proc_nr == NONE) { /* found free slot */
- sp->s_proc_nr = proc_nr(rc); /* set association */
- rc->p_priv = sp; /* assign to process */
- return(OK);
- }
- }
- kprintf("No free PRIV structure!\n", NO_NUM);
- return(ENOSPC); /* out of resources */
- } else { /* forked process */
-
- kprintf("init_proc() from prototype %d\n", proc_nr(rp));
- }
-}
-
-
-/*===========================================================================*
- * clear_proc *
- *===========================================================================*/
-PUBLIC void clear_proc(rc)
-register struct proc *rc; /* slot of process to clean up */
-{
- register struct proc *rp; /* iterate over process table */
- register struct proc **xpp; /* iterate over caller queue */
- int i;
-
- /* Turn off any alarm timers at the clock. */
- reset_timer(&priv(rc)->s_alarm_timer);
-
- /* Make sure that the exiting process is no longer scheduled. */
- if (rc->p_rts_flags == 0) lock_unready(rc);
-
- /* If the process being terminated happens to be queued trying to send a
- * message (e.g., the process was killed by a signal, rather than it doing
- * a normal exit), then it must be removed from the message queues.
- */
- if (rc->p_rts_flags & SENDING) {
- /* Check all proc slots to see if the exiting process is queued. */
- for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
- if (rp->p_caller_q == NIL_PROC) continue;
- /* Make sure that the exiting process is not on the queue. */
- xpp = &rp->p_caller_q;
- while (*xpp != NIL_PROC) { /* check entire queue */
- if (*xpp == rc) { /* process is on the queue */
- *xpp = (*xpp)->p_q_link; /* replace by next process */
- break;
- }
- xpp = &(*xpp)->p_q_link; /* proceed to next queued */
- }
- }
- }
-
- /* Check the table with IRQ hooks to see if hooks should be released. */
- for (i=0; i < NR_IRQ_HOOKS; i++) {
- if (irq_hooks[i].proc_nr == proc_nr(rc)) {
- rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
- irq_hooks[i].proc_nr = NONE; /* mark hook as free */
- }
+/* Get a privilege structure. All user processes share the same privilege
+ * structure. System processes get their own privilege structure.
+ */
+ register struct priv *sp; /* privilege structure */
+
+ if (proc_type == SYS_PROC) { /* find a new slot */
+ for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp)
+ if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break;
+ if (sp->s_proc_nr != NONE) return(ENOSPC);
+ rc->p_priv = sp; /* assign new slot */
+ rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
+ } else {
+ rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */
+ rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */
}
-
- /* 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(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
+ return(OK);
}
*/
/* Check all acceptable ranges. */
-#if DEAD_CODE /* to be replaced by proper ranges, e.g. 640 - 1 KB */
if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END)
return (phys_bytes) vir_addr;
- else if (vir_addr >= UPPER_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
+ else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
-#else
+
+#if DEAD_CODE /* brutal fix for QEMU and Bochs, if above doesn't work */
if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
#endif
#define do_getinfo do_unused
#endif
-_PROTOTYPE( int do_svrctl, (message *m_ptr) );
-#if ! USE_SVRCTL
-#define do_svrctl do_unused
+_PROTOTYPE( int do_privctl, (message *m_ptr) );
+#if ! USE_PRIVCTL
+#define do_privctl do_unused
#endif
_PROTOTYPE( int do_segctl, (message *m_ptr) );
$(SYSTEM)(do_vcopy.o) \
$(SYSTEM)(do_umap.o) \
$(SYSTEM)(do_memset.o) \
- $(SYSTEM)(do_svrctl.o) \
+ $(SYSTEM)(do_privctl.o) \
$(SYSTEM)(do_segctl.o) \
$(SYSTEM)(do_getksig.o) \
$(SYSTEM)(do_endksig.o) \
$(SYSTEM)(do_abort.o): do_abort.c
$(CC) do_abort.c
-$(SYSTEM)(do_svrctl.o): do_svrctl.c
- $(CC) do_svrctl.c
+$(SYSTEM)(do_privctl.o): do_privctl.c
+ $(CC) do_privctl.c
$(SYSTEM)(do_segctl.o): do_segctl.c
$(CC) do_segctl.c
* or ESC after debugging dumps).
*/
int how = m_ptr->ABRT_HOW;
+ timer_t *tp;
+ /* See if the monitor is to run the specified instructions. */
if (how == RBT_MONITOR) {
- /* The monitor is to run the specified instructions. */
int proc_nr = m_ptr->ABRT_MON_PROC;
int length = m_ptr->ABRT_MON_LEN + 1;
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
else
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
}
- prepare_shutdown(how);
+
+ /* Set a watchdog timer to shut down, so that this call returns first.
+ * The timer will expire at the next clock tick, which can be any moment.
+ * The CLOCK task is only scheduled when the SYSTEM task is done, though.
+ */
+ tp = &priv(proc_addr(KERNEL))->s_alarm_timer;
+ tmr_arg(tp)->ta_int = how; /* pass status as timer argument */
+ set_timer(tp, get_uptime(), prepare_shutdown);
return(OK); /* pro-forma (really EDISASTER) */
}
* m_type: SYS_SETALARM
*
* The parameters for this system call are:
- * 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_TIME_LEFT (return seconds left of previous)
clock_t uptime; /* placeholder for current uptime */
/* Extract shared parameters from the request message. */
- proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */
- if (SELF == proc_nr) proc_nr = m_ptr->m_source;
- if (! isokprocn(proc_nr)) return(EINVAL);
+ proc_nr = m_ptr->m_source; /* process to interrupt later */
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
}
- /* Finally, (re)set the timer depending on 'exp_time'. */
+ /* Finally, (re)set the timer depending on the expiration time. */
if (exp_time == 0) {
reset_timer(tp);
} else {
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
- * physical addressing.
+ * physical addressing. Although a single handler function is used, there
+ * are two different system calls so that permissions can be checked.
*/
struct vir_addr vir_addr[2]; /* virtual source and destination address */
vir_bytes bytes; /* number of bytes to copy */
PUBLIC int do_devio(m_ptr)
register message *m_ptr; /* pointer to request message */
{
- /* Perform actual device I/O for byte, word, and long values. */
+/* Process a single I/O request for byte, word, and long values. */
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
switch (m_ptr->DIO_TYPE) {
case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
#if USE_EXIT
+FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc));
+
/*===========================================================================*
* do_exit *
*===========================================================================*/
clear_proc(proc_addr(m_ptr->m_source));
return(EDONTREPLY);
}
+
+
+/*===========================================================================*
+ * clear_proc *
+ *===========================================================================*/
+PRIVATE void clear_proc(rc)
+register struct proc *rc; /* slot of process to clean up */
+{
+ register struct proc *rp; /* iterate over process table */
+ register struct proc **xpp; /* iterate over caller queue */
+ int i;
+
+ /* Turn off any alarm timers at the clock. */
+ reset_timer(&priv(rc)->s_alarm_timer);
+
+ /* Make sure that the exiting process is no longer scheduled. */
+ if (rc->p_rts_flags == 0) lock_unready(rc);
+
+ /* If the process being terminated happens to be queued trying to send a
+ * message (e.g., the process was killed by a signal, rather than it doing
+ * a normal exit), then it must be removed from the message queues.
+ */
+ if (rc->p_rts_flags & SENDING) {
+ /* Check all proc slots to see if the exiting process is queued. */
+ for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
+ if (rp->p_caller_q == NIL_PROC) continue;
+ /* Make sure that the exiting process is not on the queue. */
+ xpp = &rp->p_caller_q;
+ while (*xpp != NIL_PROC) { /* check entire queue */
+ if (*xpp == rc) { /* process is on the queue */
+ *xpp = (*xpp)->p_q_link; /* replace by next process */
+ break;
+ }
+ xpp = &(*xpp)->p_q_link; /* proceed to next queued */
+ }
+ }
+ }
+
+ /* Check the table with IRQ hooks to see if hooks should be released. */
+ for (i=0; i < NR_IRQ_HOOKS; i++) {
+ if (irq_hooks[i].proc_nr == proc_nr(rc)) {
+ rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
+ irq_hooks[i].proc_nr = NONE; /* mark hook as free */
+ }
+ }
+
+ /* 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(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
+}
+
#endif /* USE_EXIT */
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */
-
#if (CHIP == INTEL)
reg_t old_ldt_sel;
#endif
#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 */
rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
PUBLIC int do_getinfo(m_ptr)
register message *m_ptr; /* pointer to request message */
{
-/* Request system information to be copied to caller's address space. */
+/* Request system information to be copied to caller's address space. This
+ * call simply copies entire data structures to the caller.
+ */
size_t length;
phys_bytes src_phys;
phys_bytes dst_phys;
/* Try to make the actual copy for the requested data. */
if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
- proc_nr = m_ptr->m_source; /* only caller can request copy */
+ proc_nr = m_ptr->m_source; /* only caller can request copy */
dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length);
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, length);
* m_type: SYS_MEMSET
*
* The parameters for this system call are:
- * m5_l1: CP_SRC_ADDR (virtual address)
- * m5_l2: CP_DST_ADDR (returns physical address)
- * m5_l3: CP_NR_BYTES (size of datastructure)
+ * m1_p1: MEM_PTR (virtual address)
+ * m1_i1: MEM_COUNT (returns physical address)
+ * m1_i2: MEM_PATTERN (size of datastructure)
*/
#include "../system.h"
PUBLIC int do_memset(m_ptr)
register message *m_ptr;
{
-/* Handle sys_memset(). */
+/* Handle sys_memset(). This writes a pattern into the specified memory. */
unsigned long p;
- unsigned char c = m_ptr->MEM_CHAR;
+ unsigned char c = m_ptr->MEM_PATTERN;
p = c | (c << 8) | (c << 16) | (c << 24);
phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
return(OK);
#endif
/* Restore the registers. */
- memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
+ memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
return(OK);
}
#endif /* USE_SIGRETURN */
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
/* Copy the registers to the sigcontext structure. */
- memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
+ memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
/* Finish the sigcontext initialization. */
sc.sc_flags = SC_SIGCONTEXT;
PUBLIC int do_vcopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
-/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
+/* Handle sys_virvcopy() and sys_physvcopy() that pass a vector with copy
+ * requests. Although a single handler function is used, there are two
+ * different system calls so that permissions can be checked.
+ */
int nr_req;
int caller_pid;
vir_bytes caller_vir;
#if USE_VDEVIO
-
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
pvw_pair_t *pvw_pairs; /* needed for word values */
pvl_pair_t *pvl_pairs; /* needed for long values */
int i;
- pid_t caller_pid; /* process id of caller */
+ int caller_proc; /* process number of caller */
size_t bytes; /* # bytes to be copied */
vir_bytes caller_vir; /* virtual address at caller */
phys_bytes caller_phys; /* physical address at caller */
}
/* Calculate physical addresses and copy (port,value)-pairs from user. */
- caller_pid = (pid_t) m_ptr->m_source;
+ caller_proc = m_ptr->m_source;
caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
- caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
+ caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
if (0 == caller_phys) return EFAULT;
kernel_phys = vir2phys(vdevio_pv_buf);
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
* or PRIVATE. The reason for this is that extern variables cannot have a
* default initialization. If such variables are shared, they must also be
* declared in one of the *.h files without the initialization. Examples
- * include 'tasktab' (this file) and 'idt'/'gdt' (protect.c).
+ * include 'system_image' (this file) and 'idt' and 'gdt' (protect.c).
*
* Changes:
* Nov 10, 2004 removed controller->driver mappings (Jorrit N. Herder)
* Oct 17, 2004 updated above and tasktab comments (Jorrit N. Herder)
- * May 01, 2004 included p_sendmask in tasktab (Jorrit N. Herder)
+ * May 01, 2004 changed struct for system image (Jorrit N. Herder)
*/
#define _TABLE
* mask, and a name for the process table. For kernel processes, the startup
* routine and stack size is also provided.
*/
-#define IDLE_F (PREEMPTIBLE | BILLABLE)
-#define USER_F (PREEMPTIBLE | RDY_Q_HEAD)
+#define USER_F (PREEMPTIBLE | BILLABLE | RDY_Q_HEAD)
#define SYS_F (PREEMPTIBLE | SYS_PROC)
-#define TCB_F (SYS_PROC) /* trusted computing base */
+#define TASK_F (SYS_PROC)
#define IDLE_T 32 /* ticks */
#define USER_T 8 /* ticks */
#define SYS_T 16 /* ticks */
PUBLIC struct system_image image[] = {
- { IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" },
- { CLOCK, clock_task, TCB_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" },
- { SYSTEM, sys_task, TCB_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" },
- { HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" },
- { PM_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" },
- { FS_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" },
+ { IDLE, idle_task, USER_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" },
+ { CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" },
+ { SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" },
+ { HARDWARE, 0, TASK_F, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" },
+ { PM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" },
+ { FS_PROC_NR, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" },
{ IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "IS" },
{ TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, 0, "TTY" },
{ MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "MEMORY" },
#include <stdlib.h>
#include <signal.h>
#include <minix/com.h>
+#include "proc.h"
#define END_OF_KMESS -1
FORWARD _PROTOTYPE(void kputc, (int c));
{
/* The system has run aground of a fatal kernel error. Terminate execution. */
static int panicking = 0;
+ timer_t *tp;
if (panicking ++) return; /* prevent recursive panics */
if (mess != NULL) {
if (nr != NO_NUM) kprintf(" %d", nr);
kprintf("\n",NO_NUM);
}
- prepare_shutdown(RBT_PANIC);
+
+ /* Make a direct call to shutdown. Interface requires to pass the shutdown
+ * status by means of a timer.
+ */
+ tp = &priv(proc_addr(KERNEL))->s_alarm_timer;
+ tmr_arg(tp)->ta_int = RBT_PANIC;
+ prepare_shutdown(tp);
}