#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
-#define SETPSW(rp, new) /* permits only certain bits to be set */ \
+#define SETPSW(rp, new) /* permits only certain bits to be set */ \
((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
#define IF_MASK 0x00000200
#define IOPL_MASK 0x003000
ep = &ex_data[vec_nr];
if (vec_nr == 2) { /* spurious NMI on some machines */
- kprintf("got spurious NMI\n",NO_NUM);
+ kprintf("got spurious NMI\n");
return;
}
else
kprintf("\n%s\n", ep->msg);
kprintf("k_reenter = %d ", k_reenter);
- kprintf("process %d (%s)", proc_nr(saved_proc), saved_proc->p_name);
- kprintf("pc = %d:0x%x", (unsigned) saved_proc->p_reg.cs,
+ kprintf("process %d (%s), ", proc_nr(saved_proc), saved_proc->p_name);
+ kprintf("pc = %u:0x%x", (unsigned) saved_proc->p_reg.cs,
(unsigned) saved_proc->p_reg.pc);
panic("exception in a kernel task", NO_NUM);
#ifndef IPC_H
#define IPC_H
+#include <minix/com.h>
+
/* Masks and flags for system calls. */
#define SYSCALL_FUNC 0x0F /* mask for system call function */
#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */
#define FRESH_ANSWER 0x20 /* ignore pending notifications as answer */
/* (default behaviour for SENDREC calls) */
-/* System calls (numbers passed when trapping to the kernel). */
-#define ECHO 0 /* function code for echoing messages */
-#define SEND 1 /* function code for sending messages */
-#define RECEIVE 2 /* function code for receiving messages */
-#define SENDREC 3 /* function code for SEND + RECEIVE */
-#define NOTIFY 4 /* function code for notifications */
-#define ALERT 5 /* function code for alerting */
+/* System call numbers that are passed when trapping to the kernel. The
+ * numbers are carefully defined so that it can easily be seen (based on
+ * the bits that are on) which checks should be done in sys_call().
+ */
+#define ECHO 0 /* 0 0 0 0 1 (01) : echo a message */
+#define SEND 1 /* 0 0 0 1 1 (03) : blocking send */
+#define RECEIVE 2 /* 0 0 1 0 1 (05) : blocking receive */
+#define SENDREC 3 /* 0 0 1 1 1 (07) : SEND + RECEIVE */
+#define NOTIFY 4 /* temp */
+#define ALERT 5 /* 0 1 0 1 0 (10) : nonblocking notify */
+
+/* The following definitions determine whether a calls message buffer and/
+ * or destination processes should be validated.
+ */
+#define CHECK_PTR 0x01 /* 0 0 0 0 1 : validate message buffer */
+#define CHECK_DST 0x02 /* 0 0 0 1 0 : validate message destination */
+#define CHECK_SRC 0x04 /* 0 0 1 0 0 : validate message source */
-/* Call masks indicating which system calls a process can make. */
-#define EMPTY_CALL_MASK (0)
+/* Call masks indicating which system calls (traps) a process can make.
+ * The values here are used for the processes in the boot image.
+ */
+#define EMPTY_MASK (0)
+#define FILLED_MASK (~0)
#define USER_CALL_MASK (1 << SENDREC)
-#define SYSTEM_CALL_MASK (~0)
+/* Send masks determine to whom processes can send messages or notifications.
+ * The values here are used for the processes in the boot image. We rely on
+ * the initialization code in main() to match the s_nr_to_id() mapping for the
+ * processes in the boot image, so that the send mask that is defined here
+ * can be directly copied onto map[0] of the actual send mask. Privilege
+ * structure 0 is shared by user processes.
+ *
+ * Note that process numbers in the boot image should not be higher than
+ * "BITCHUNK_BITS - NR_TASKS", because a bitchunk_t field is used to store
+ * the send masks in the table that describes that processes in the image.
+ */
+#define s_nr_to_id(n) (NR_TASKS + (n) + 1)
+#define s(n) (1 << s_nr_to_id(n))
+#define USER_SEND_MASK (s(PM_PROC_NR) | s(FS_PROC_NR))
+#define DRIVER_SEND_MASK (s(PM_PROC_NR) | s(FS_PROC_NR) | s(SYSTEM) | \
+ s(CLOCK) | s(PRINTF_PROC) | s(TTY))
+#define SERVER_SEND_MASK (~0)
+#define SYSTEM_SEND_MASK (~1)
+
+/* Sanity check to make sure the send masks can be set. */
+extern int dummy[(BITCHUNK_BITS-NR_TASKS > INIT_PROC_NR) ? 1 : -1];
#endif /* IPC_H */
/* Clear the process table. Anounce each slot as empty and set up mappings
* for proc_addr() and proc_nr() macros. Do the same for the table with
- * system properties structures.
+ * privilege structures for the system processes.
*/
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
rp->p_rts_flags = SLOT_FREE; /* initialize free slot */
for (i=0; i < NR_BOOT_PROCS; ++i) {
ip = &image[i]; /* process' attributes */
rp = proc_addr(ip->proc_nr); /* get process pointer */
- 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); /* 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? */
+ (void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */
+ priv(rp)->s_flags = ip->flags; /* process flags */
+ priv(rp)->s_call_mask = ip->call_mask; /* allowed traps */
+ priv(rp)->s_send_mask.chunk[0] = ip->send_mask; /* restrict targets */
+ if (iskerneln(proc_nr(rp))) { /* part of the kernel? */
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
rp->p_priv->s_stack_guard = (reg_t *) ktsb;
*rp->p_priv->s_stack_guard = STACK_GUARD;
/* processes that are in the kernel */
hdrindex = 0; /* all use the first a.out header */
} else {
- hdrindex = 1 + i-NR_TASKS; /* drivers, servers, INIT follow */
+ hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */
}
/* The bootstrap loader created an array of the a.out headers at
* absolute address 'aout'. Get one element to e_hdr.
*/
phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
- (phys_bytes) A_MINHDR);
+ (phys_bytes) A_MINHDR);
/* Convert addresses to clicks and build process memory map */
text_base = e_hdr.a_syms >> CLICK_SHIFT;
text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
/* Initialize the server stack pointer. Take it down one word
* to give crtso.s something to use as "argc".
*/
- if (i-NR_TASKS >= 0) {
+ if (isusern(proc_nr(rp))) { /* user-space process? */
rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
rp->p_reg.sp -= sizeof(reg_t);
#define priv_id(rp) ((rp)->p_priv->s_id)
#define priv(rp) ((rp)->p_priv)
-#define id_to_nr(id) priv_addr(id)->s_proc_nr;
-#define nr_to_id(nr) priv(proc_addr(nr))->s_id;
+#define id_to_nr(id) priv_addr(id)->s_proc_nr
+#define nr_to_id(nr) priv(proc_addr(nr))->s_id
/* The system structures table and pointers to individual table slots. The
* pointers allow faster access because now a process entry can be found by
if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO))
return(EBADSRCDST);
-#if DEAD_CODE /* temporarily disabled for testing ALERT */
- /* 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.
+ /* If the call involves a message buffer, i.e., for SEND, RECEIVE, SENDREC,
+ * or ECHO, check the message pointer. This check allows a message to be
+ * anywhere in data or stack or gap. It will have to be made more elaborate
+ * 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);
-#endif
+ if (function & SENDREC) {
+ vb = (vir_bytes) m_ptr; /* virtual clicks */
+ vlo = vb >> CLICK_SHIFT; /* bottom of message */
+ vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* top of message */
+ 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);
+ }
+
+ /* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY,
+ * verify that the caller is allowed to send to the given destination and
+ * that the destination is still alive.
+ */
+ if (function & SEND) {
+ if (! get_sys_bit(priv(caller_ptr)->s_send_mask, nr_to_id(src_dst))) {
+ kprintf("Warning, send_mask denied %d sending to %d\n",
+ proc_nr(caller_ptr), src_dst);
+ return(ECALLDENIED);
+ }
+
+ if (isemptyn(src_dst)) return(EDEADDST); /* cannot send to the dead */
+ }
/* Now check if the call is known and try to perform the request. The only
* system calls that exist in MINIX are sending and receiving messages.
* - SENDREC: combines SEND and RECEIVE in a single system call
* - SEND: sender blocks until its message has been delivered
* - RECEIVE: receiver blocks until an acceptable message has arrived
- * - NOTIFY: sender continues; either directly deliver the message or
- * queue the notification message until it can be delivered
- * - ECHO: the message directly will be echoed to the sender
+ * - NOTIFY: nonblocking call; deliver notification or mark pending
+ * - ECHO: nonblocking call; directly echo back the message
*/
switch(function) {
- case SENDREC: /* has FRESH_ANSWER flag */
+ case SENDREC: /* has FRESH_ANSWER flag */
/* fall through */
case SEND:
- if (isemptyn(src_dst)) {
- result = EDEADDST; /* cannot send to the dead */
- break;
- }
-
-#if DEAD_CODE /* to be replaced by better mechanism */
- mask_entry = isuserp(proc_addr(src_dst)) ? USER_PROC_NR : src_dst;
- if (! isallowed(caller_ptr->p_sendmask, mask_entry)) {
- kprintf("WARNING: sys_call denied %d ", caller_ptr->p_nr);
- kprintf("sending to %d\n", proc_addr(src_dst)->p_nr);
- result = ECALLDENIED; /* call denied by send mask */
- break;
- }
-#endif
-
result = mini_send(caller_ptr, src_dst, m_ptr, flags);
if (function == SEND || result != OK) {
break; /* done, or SEND failed */
default:
result = EBADCALL; /* illegal system call */
}
-
- /* If the caller made a successfull, blocking system call it's priority may
- * 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 /* 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;
- caller_ptr->p_full_quantums = QUANTUMS(caller_ptr->p_priority);
- }
-#endif
/* Now, return the result of the system call to the caller. */
return(result);
#if DEBUG_SCHED_CHECK
check_runqueues("ready");
- if(rp->p_ready) kprintf("ready() already ready process\n", NO_NUM);
+ if(rp->p_ready) kprintf("ready() already ready process\n");
#endif
/* Processes, in principle, are added to the end of the queue. However,
#if DEBUG_SCHED_CHECK
check_runqueues("unready");
- if (! rp->p_ready) kprintf("unready() already unready process\n", NO_NUM);
+ if (! rp->p_ready) kprintf("unready() already unready process\n");
#endif
/* Now make sure that the process is not in its ready queue. Remove the
}
prev_xp = *xpp; /* save previous in chain */
}
+
+ /* The caller blocked. Reset the scheduling priority and quantums allowed.
+ * The process' priority may have been lowered if a process consumed too
+ * many full quantums in a row to prevent damage from infinite loops
+ */
+ rp->p_priority = rp->p_max_priority;
+ rp->p_full_quantums = QUANTUMS(rp->p_priority);
#if DEBUG_SCHED_CHECK
rp->p_ready = 0;
int q;
/* Check if this process is preemptible, otherwise leave it as is. */
- if (! (priv(sched_ptr)->s_flags & PREEMPTIBLE)) {
-#if DEAD_CODE
- kprintf("Warning, sched for nonpreemptible proc %d\n", sched_ptr->p_nr);
-#endif
- return;
- }
+ if (! (priv(sched_ptr)->s_flags & PREEMPTIBLE)) return;
-#if DEAD_CODE
- if (sched_ptr->p_nr == IS_PROC_NR) {
- kprintf("Scheduling IS: pri: %d, ", sched_ptr->p_priority);
- kprintf("qua %d", sched_ptr->p_full_quantums);
- }
-#endif
/* Process exceeded the maximum number of full quantums it is allowed
* to use in a row. Lower the process' priority, but make sure we don't
* end up in the IDLE queue. This helps to limit the damage caused by
*/
if (-- sched_ptr->p_full_quantums <= 0) { /* exceeded threshold */
if (sched_ptr->p_priority + 1 < IDLE_Q ) {
+ q = sched_ptr->p_priority + 1; /* backup new priority */
unready(sched_ptr); /* remove from queues */
- sched_ptr->p_priority ++; /* lower priority */
+ sched_ptr->p_priority = q; /* lower priority */
ready(sched_ptr); /* add to new queue */
-#if DEAD_CODE
-kprintf("Warning, proc %d got lower priority: ", sched_ptr->p_nr);
-kprintf("%d\n", sched_ptr->p_priority);
-#endif
}
sched_ptr->p_full_quantums = QUANTUMS(sched_ptr->p_priority);
}
/* Give the expired process a new quantum and see who is next to run. */
sched_ptr->p_sched_ticks = sched_ptr->p_quantum_size;
pick_proc();
-
-#if DEAD_CODE
- if (sched_ptr->p_nr == IS_PROC_NR) {
- kprintf("Next proc: %d, ", next_ptr->p_nr);
- kprintf("pri: %d, ", next_ptr->p_priority);
- kprintf("qua: %d\n", next_ptr->p_full_quantums);
- }
-#endif
}
#define IDLE_Q 15 /* lowest, only IDLE process goes here */
/* Each queue has a maximum number of full quantums associated with it. */
-#define QUANTUMS(q) (NR_SCHED_QUEUES - (q))
+#define QUANTUMS(q) (1 + (NR_SCHED_QUEUES - (q))/2)
/* Magic process table addresses. */
#define BEG_PROC_ADDR (&proc[0])
/* system.c */
_PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
-_PROTOTYPE( int set_priv, (register struct proc *rc,int sys_proc_flag) );
+_PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) );
_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:
- * set_priv: assign privilege structure to user or system process
+ * get_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
* umap_local: map virtual address in LOCAL_SEG to physical
/*===========================================================================*
- * set_priv *
+ * get_priv *
*===========================================================================*/
-PUBLIC int set_priv(rc, proc_type)
+PUBLIC int get_priv(rc, proc_type)
register struct proc *rc; /* new (child) process pointer */
int proc_type; /* system or user process flag */
{
#endif
register struct proc *rpc; /* child process pointer */
struct proc *rpp; /* parent process pointer */
+ int i;
rpp = proc_addr(m_ptr->PR_PPROC_NR);
rpc = proc_addr(m_ptr->PR_PROC_NR);
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;
+ /* If this is a system process, make sure the child process gets its own
+ * privilege structure for accounting.
+ */
+ if (priv(rpc)->s_flags & SYS_PROC) {
+ if (OK != (i=get_priv(rpc, SYS_PROC))) return(i); /* get structure */
+ for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
+ priv(rpc)->s_notify_pending.chunk[i] = 0; /* - notifications */
+ priv(rpc)->s_int_pending = 0; /* - interrupts */
+ sigemptyset(&priv(rpc)->s_sig_pending); /* - signals */
+ }
return(OK);
}
register struct proc *rp;
register struct priv *sp;
int proc_nr;
+ int i;
/* Extract message parameters. */
proc_nr = m_ptr->CTL_PROC_NR;
/* Make sure this process has its own privileges structure. */
if (! (priv(rp)->s_flags & SYS_PROC))
- set_priv(rp, SYS_PROC);
+ get_priv(rp, SYS_PROC);
/* Now update the process' privileges as requested. */
- rp->p_priv->s_call_mask = SYSTEM_CALL_MASK;
+ rp->p_priv->s_call_mask = FILLED_MASK;
+ for (i=0; i<BITMAP_CHUNKS(NR_SYS_PROCS); i++) {
+ rp->p_priv->s_send_mask.chunk[i] = FILLED_MASK;
+ }
+ unset_sys_bit(rp->p_priv->s_send_mask, USER_PRIV_ID);
+
+ /* All process that this process can send to must be able to reply.
+ * Therefore, their send masks should be updated as well.
+ */
+ for (i=0; i<NR_SYS_PROCS; i++) {
+ if (get_sys_bit(rp->p_priv->s_send_mask, i)) {
+ set_sys_bit(priv_addr(i)->s_send_mask, priv_id(rp));
+ }
+ }
return(OK);
}
if (rp->p_memmap[T].mem_len != 0) {
if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
- m_ptr->CTL_DATA= tr_data;
+ m_ptr->CTL_DATA = tr_data;
break;
}
/* Text space is actually data space - fall through. */
#define CLOCK_S SMALL_STACK
/* Stack space for all the task stacks. Declared as (char *) to align it. */
-#define TOT_STACK_SPACE (IDLE_S+HARDWARE_S+CLOCK_S+SYSTEM_S)
+#define TOT_STACK_SPACE (IDLE_S + HARDWARE_S + CLOCK_S + SYSTEM_S)
PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
* routine and stack size is also provided.
*/
#define USER_F (PREEMPTIBLE | BILLABLE | RDY_Q_HEAD)
+#define IDLE_F (BILLABLE | SYS_PROC)
#define SYS_F (PREEMPTIBLE | SYS_PROC)
#define TASK_F (SYS_PROC)
#define SYS_T 16 /* ticks */
PUBLIC struct system_image image[] = {
- { 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" },
+ { IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_MASK, EMPTY_MASK, "IDLE" },
+ { CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, FILLED_MASK, SYSTEM_SEND_MASK, "CLOCK" },
+ { SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, FILLED_MASK, SYSTEM_SEND_MASK, "SYS" },
+ { HARDWARE, 0, TASK_F, SYS_T, TASK_Q, HARDWARE_S, EMPTY_MASK, SYSTEM_SEND_MASK, "KERNEL" },
+ { PM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, SERVER_SEND_MASK, "PM" },
+ { FS_PROC_NR, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, SERVER_SEND_MASK, "FS" },
+ { SM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, SYSTEM_SEND_MASK, "SM" },
+ { IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "IS" },
+ { TTY, 0, SYS_F, SYS_T, 1, 0, FILLED_MASK, SYSTEM_SEND_MASK, "TTY" },
+ { MEMORY, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "MEMORY" },
#if ENABLE_AT_WINI
- { AT_WINI, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "AT_WINI" },
+ { AT_WINI, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "AT_WINI" },
#endif
#if ENABLE_FLOPPY
- { FLOPPY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FLOPPY" },
+ { FLOPPY, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "FLOPPY" },
#endif
#if ENABLE_PRINTER
- { PRINTER, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PRINTER" },
+ { PRINTER, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, DRIVER_SEND_MASK, "PRINTER" },
#endif
#if ENABLE_RTL8139
- { USR8139, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "RTL8139" },
+ { RTL8139, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "RTL8139" },
#endif
#if ENABLE_FXP
- { FXP, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FXP" },
+ { FXP, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "FXP" },
#endif
#if ENABLE_DPETH
- { DPETH, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "DPETH" },
+ { DPETH, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, DRIVER_SEND_MASK, "DPETH" },
#endif
#if ENABLE_LOG
- { LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "LOG" },
+ { LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, FILLED_MASK, SYSTEM_SEND_MASK, "LOG" },
#endif
- { INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, 0, "INIT" },
+ { INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, USER_SEND_MASK, "INIT" },
};
/* Verify the size of the system image table at compile time. If the number
int priority; /* scheduling priority */
int stksize; /* stack size for tasks */
char call_mask; /* allowed system calls */
- long send_mask; /* send mask protection */
+ bitchunk_t send_mask; /* send mask protection */
char proc_name[P_NAME_LEN]; /* name in process table */
};
* output driver when a new message is ready.
*/
+#include <stdarg.h>
#include "kernel.h"
#include <unistd.h>
-#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
PUBLIC void kprintf(const char *fmt, ...) /* format to be printed */
{
int c; /* next character in fmt */
+ int d;
unsigned long u; /* hold number argument */
int base; /* base of number arg */
int negative = 0; /* print minus sign */
* conversion after the switch statement.
*/
case 'd': /* output decimal */
- u = va_arg(argp, int);
- if (u < 0) { negative = 1; u = -u; }
+ d = va_arg(argp, signed int);
+ if (d < 0) { negative = 1; u = -d; } else { u = d; }
base = 10;
break;
case 'u': /* output unsigned long */
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
+ s = NULL; /* reset for next round */
}
else {
kputc(c); /* print and continue */