worsley@ditmela.oz (Andrew Worsley) (05/18/89)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 7 (of 10)."
# Contents: kerneldif/proc.c.cdif kerneldif/proc.h.cdif
# kerneldif/protect.h.cdif kerneldif/type.h.cdif
# Wrapped by sys@besplex on Sun Mar 26 06:34:23 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'kerneldif/proc.c.cdif' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kerneldif/proc.c.cdif'\"
else
echo shar: Extracting \"'kerneldif/proc.c.cdif'\" \(26431 characters\)
sed "s/^X//" >'kerneldif/proc.c.cdif' <<'END_OF_FILE'
X*** kernel-1.3/proc.c Fri Oct 7 21:02:44 1988
X--- kernel/proc.c Thu Mar 23 01:05:42 1989
X***************
X*** 6,14 ****
X *
X! * It also has five minor entry points:
X *
X! * ready: put a process on one of the ready queues so it can be run
X! * unready: remove a process from the ready queues
X! * sched: a process has run too long; schedule another one
X! * mini_send: send a message (used by interrupt signals, etc.)
X! * pick_proc: pick a process to run (used by system initialization)
X */
X--- 6,16 ----
X *
X! * It also has several minor entry points:
X *
X! * lockready: put a process on one of the ready queues so it can be run
X! * lockunready: remove a process from the ready queues
X! * locksched: a process has run too long; schedule another one
X! * lockmini_send: send a message (used by interrupt signals, etc.)
X! * lockpick_proc: pick a process to run (used by system initialization)
X! * proc_init: initialize the process table
X! * unhold: repeat all held-up interrupts
X */
X***************
X*** 25,26 ****
X--- 27,30 ----
X
X+ PRIVATE unsigned char switching; /* nonzero to inhibit interrupt() */
X+
X /*===========================================================================*
X***************
X*** 28,32 ****
X *===========================================================================*/
X! PUBLIC interrupt(task, m_ptr)
X int task; /* number of task to be started */
X- message *m_ptr; /* interrupt message to send to the task */
X {
X--- 32,35 ----
X *===========================================================================*/
X! PUBLIC interrupt(task)
X int task; /* number of task to be started */
X {
X***************
X*** 34,81 ****
X
X! int i, n, old_map, this_bit;
X
X! #ifdef i8088
X! /* Re-enable the 8259A interrupt controller. */
X! if (ps && task==FLOPPY)port_out(0x3C, ENABLE);/* Nonspecific End-Of-Int ps */
X
X! port_out(INT_CTL, ENABLE); /* this re-enables the 8259A controller chip */
X! if (pc_at && task == WINCHESTER)
X! /* this re-enables the second controller chip */
X! port_out(INT2_CTL, ENABLE);
X! #endif
X!
X! /* Try to send the interrupt message to the indicated task. */
X! this_bit = 1 << (-task);
X! if (mini_send(HARDWARE, task, m_ptr) != OK) {
X! /* The message could not be sent to the task; it was not waiting. */
X! old_map = busy_map; /* save original map of busy tasks */
X! if (task == CLOCK) {
X! lost_ticks++;
X! } else {
X! busy_map |= this_bit; /* mark task as busy */
X! task_mess[-task] = m_ptr; /* record message pointer */
X }
X! } else {
X! /* Hardware interrupt was successfully sent as a message. */
X! busy_map &= ~this_bit; /* turn off the bit in case it was on */
X! old_map = busy_map;
X }
X
X! /* See if any tasks that were previously busy are now listening for msgs. */
X! if (old_map != 0) {
X! for (i = 2; i <= NR_TASKS; i++) {
X! /* Check each task looking for one with a pending interrupt. */
X! if ( (old_map>>i) & 1) {
X! /* Task 'i' has a pending interrupt. */
X! n = mini_send(HARDWARE, -i, task_mess[i]);
X! if (n == OK) busy_map &= ~(1 << i);
X! }
X! }
X }
X
X! /* If a task has just been readied and a user is running, run the task. */
X! if (rdy_head[TASK_Q] != NIL_PROC && (cur_proc >= 0 || cur_proc == IDLE))
X! pick_proc();
X! }
X
X
X--- 37,105 ----
X
X! register struct proc *rp; /* pointer to task's proc entry */
X
X! rp = proc_addr(task);
X
X! /* If this call would compete with other process-switching functions, put
X! * it on the 'held' queue to be flushed at the next non-competing restart().
X! * The competing conditions are:
X! * (1) k_reenter == (typeof k_reenter) -1:
X! * Call from the task level, typically from an output interrupt
X! * routine. An interrupt handler might reenter interrupt(). Rare,
X! * so not worth special treatment.
X! * (2) k_reenter > 0:
X! * Call from a nested interrupt handler. A previous interrupt handler
X! * might be inside interrupt() or sys_call().
X! * (3) switching != 0:
X! * Some process-switching function other than interrupt() is being
X! * called from the task level, typically sched() from CLOCK. An
X! * interrupt handler might call interrupt and pass the k_reenter test.
X! */
X! if (k_reenter != 0 || switching) {
X! lock();
X! if (!rp->p_int_held) {
X! rp->p_int_held = TRUE;
X! if (held_head != NIL_PROC)
X! held_tail->p_nextheld = rp;
X! else
X! held_head = rp;
X! held_tail = rp;
X! rp->p_nextheld = NIL_PROC;
X }
X! unlock();
X! return;
X }
X
X! /* If task is not waiting for an interrupt, record the blockage. */
X! if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
X! !isrxhardware(rp->p_getfrom)) {
X! rp->p_int_blocked = TRUE;
X! return;
X }
X
X! /* Destination is waiting for an interrupt.
X! * Send it a message with source HARDWARE and type HARD_INT.
X! * No more information can be reliably provided since interrupt messages
X! * are not queued.
X! */
X! rp->p_messbuf->m_source = HARDWARE;
X! rp->p_messbuf->m_type = HARD_INT;
X! rp->p_flags &= ~RECEIVING;
X! rp->p_int_blocked = FALSE;
X
X+ /* Duplicate relevant part of ready() in-line. */
X+ if (rdy_head[TASK_Q] != NIL_PROC)
X+ rdy_tail[TASK_Q]->p_nextready = rp;
X+ else
X+ rdy_head[TASK_Q] = rp;
X+ rdy_tail[TASK_Q] = rp;
X+ rp->p_nextready = NIL_PROC;
X+
X+ /* If a non-task is running and a task is ready, run the task.
X+ * Duplicate relevant part of pick_proc() in-line. One assignment!
X+ * Bill_ptr stays unchanged.
X+ */
X+ if (!istaskp(proc_ptr) && (rp = rdy_head[TASK_Q]) != NIL_PROC)
X+ proc_ptr = rp;
X+ }
X+
X
X***************
X*** 84,88 ****
X *===========================================================================*/
X! PUBLIC sys_call(function, caller, src_dest, m_ptr)
X int function; /* SEND, RECEIVE, or BOTH */
X- int caller; /* who is making this call */
X int src_dest; /* source to receive from or dest to send to */
X--- 108,111 ----
X *===========================================================================*/
X! PUBLIC int sys_call(function, src_dest, m_ptr)
X int function; /* SEND, RECEIVE, or BOTH */
X int src_dest; /* source to receive from or dest to send to */
X***************
X*** 92,95 ****
X * messages. These are done by trapping to the kernel with an INT instruction.
X! * The trap is caught and sys_call() is called to send or receive a message (or
X! * both).
X */
X--- 115,118 ----
X * messages. These are done by trapping to the kernel with an INT instruction.
X! * The trap is caught and sys_call() is called to send or receive a message
X! * (or both). The caller is always given by proc_ptr.
X */
X***************
X*** 100,110 ****
X /* Check for bad system call parameters. */
X! rp = proc_addr(caller);
X! if (src_dest < -NR_TASKS || (src_dest >= NR_PROCS && src_dest != ANY) ) {
X! rp->p_reg[RET_REG] = E_BAD_SRC;
X! return;
X! }
X! if (function != BOTH && caller >= LOW_USER) {
X! rp->p_reg[RET_REG] = E_NO_PERM; /* users only do BOTH */
X! return;
X! }
X
X--- 123,129 ----
X /* Check for bad system call parameters. */
X! if (!isoksrc_dest(src_dest))
X! return(E_BAD_SRC);
X! rp = proc_ptr;
X! if (function != BOTH && isuserp(rp))
X! return(E_NO_PERM); /* users only do BOTH */
X
X***************
X*** 112,122 ****
X if (function & SEND) {
X! n = mini_send(caller, src_dest, m_ptr); /* func = SEND or BOTH */
X! if (function == SEND || n != OK) rp->p_reg[RET_REG] = n;
X! if (n != OK) return; /* SEND failed */
X }
X
X! if (function & RECEIVE) {
X! n = mini_rec(caller, src_dest, m_ptr); /* func = RECEIVE or BOTH*/
X! rp->p_reg[RET_REG] = n;
X! }
X }
X--- 131,142 ----
X if (function & SEND) {
X! /* Function = SEND or BOTH. */
X! n = mini_send(rp, src_dest, m_ptr);
X! if (function == SEND || n != OK)
X! return(n); /* done, or SEND failed */
X }
X
X! /* Function = RECEIVE or BOTH.
X! * We have checked user calls are BOTH, and trust 'function' otherwise.
X! */
X! return(mini_rec(rp, src_dest, m_ptr));
X }
X***************
X*** 126,146 ****
X *===========================================================================*/
X! PUBLIC int mini_send(caller, dest, m_ptr)
X! int caller; /* who is trying to send a message? */
X int dest; /* to whom is message being sent? */
X message *m_ptr; /* pointer to message buffer */
X {
X! /* Send a message from 'caller' to 'dest'. If 'dest' is blocked waiting for
X! * this message, copy the message to it and unblock 'dest'. If 'dest' is not
X! * waiting at all, or is waiting for another source, queue 'caller'.
X */
X
X! register struct proc *caller_ptr, *dest_ptr, *next_ptr;
X vir_bytes vb; /* message buffer pointer as vir_bytes */
X vir_clicks vlo, vhi; /* virtual clicks containing message to send */
X- vir_clicks len; /* length of data segment in clicks */
X
X /* User processes are only allowed to send to FS and MM. Check for this. */
X! if (caller >= LOW_USER && (dest != FS_PROC_NR && dest != MM_PROC_NR))
X return(E_BAD_DEST);
X- caller_ptr = proc_addr(caller); /* pointer to source's proc entry */
X dest_ptr = proc_addr(dest); /* pointer to destination's proc entry */
X--- 146,165 ----
X *===========================================================================*/
X! PRIVATE int mini_send(caller_ptr, dest, m_ptr)
X! register struct proc *caller_ptr; /* who is trying to send a message? */
X int dest; /* to whom is message being sent? */
X message *m_ptr; /* pointer to message buffer */
X+
X {
X! /* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
X! * for this message, copy the message to it and unblock 'dest'. If 'dest' is
X! * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
X */
X
X! register struct proc *dest_ptr, *next_ptr;
X vir_bytes vb; /* message buffer pointer as vir_bytes */
X vir_clicks vlo, vhi; /* virtual clicks containing message to send */
X
X /* User processes are only allowed to send to FS and MM. Check for this. */
X! if (isuserp(caller_ptr) && !isservn(dest))
X return(E_BAD_DEST);
X dest_ptr = proc_addr(dest); /* pointer to destination's proc entry */
X***************
X*** 149,151 ****
X /* Check for messages wrapping around top of memory or outside data seg. */
X- len = caller_ptr->p_map[D].mem_len;
X vb = (vir_bytes) m_ptr;
X--- 168,169 ----
X***************
X*** 153,160 ****
X vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
X! if (vhi < vlo || vhi - caller_ptr->p_map[D].mem_vir >=len)return(E_BAD_ADDR);
X
X! /* Check for deadlock by 'caller' and 'dest' sending to each other. */
X if (dest_ptr->p_flags & SENDING) {
X next_ptr = caller_ptr->p_callerq;
X! while (next_ptr) {
X if (next_ptr == dest_ptr)
X--- 171,180 ----
X vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
X! if (vhi < vlo ||
X! vhi - caller_ptr->p_map[D].mem_vir >= caller_ptr->p_map[D].mem_len)
X! return(E_BAD_ADDR);
X
X! /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
X if (dest_ptr->p_flags & SENDING) {
X next_ptr = caller_ptr->p_callerq;
X! while (next_ptr != NIL_PROC) {
X if (next_ptr == dest_ptr)
X***************
X*** 166,171 ****
X /* Check to see if 'dest' is blocked waiting for this message. */
X! if ( (dest_ptr->p_flags & RECEIVING) && (dest_ptr->p_flags & SENDING) == 0 &&
X! (dest_ptr->p_getfrom == ANY || dest_ptr->p_getfrom == caller)){
X /* Destination is indeed waiting for this message. */
X! cp_mess(caller, caller_ptr->p_map[D].mem_phys, m_ptr,
X dest_ptr->p_map[D].mem_phys, dest_ptr->p_messbuf);
X--- 186,192 ----
X /* Check to see if 'dest' is blocked waiting for this message. */
X! if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
X! (dest_ptr->p_getfrom == ANY ||
X! dest_ptr->p_getfrom == proc_number(caller_ptr))) {
X /* Destination is indeed waiting for this message. */
X! cp_mess(proc_number(caller_ptr), caller_ptr->p_map[D].mem_phys, m_ptr,
X dest_ptr->p_map[D].mem_phys, dest_ptr->p_messbuf);
X***************
X*** 175,177 ****
X /* Destination is not waiting. Block and queue caller. */
X- if (caller == HARDWARE) return(E_OVERRUN);
X caller_ptr->p_messbuf = m_ptr;
X--- 196,197 ----
X***************
X*** 181,185 ****
X /* Process is now blocked. Put in on the destination's queue. */
X! if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC) {
X dest_ptr->p_callerq = caller_ptr;
X! } else {
X while (next_ptr->p_sendlink != NIL_PROC)
X--- 201,205 ----
X /* Process is now blocked. Put in on the destination's queue. */
X! if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
X dest_ptr->p_callerq = caller_ptr;
X! else {
X while (next_ptr->p_sendlink != NIL_PROC)
X***************
X*** 197,200 ****
X *===========================================================================*/
X! PRIVATE int mini_rec(caller, src, m_ptr)
X! int caller; /* process trying to get message */
X int src; /* which message source is wanted (or ANY) */
X--- 217,220 ----
X *===========================================================================*/
X! PRIVATE int mini_rec(caller_ptr, src, m_ptr)
X! register struct proc *caller_ptr; /* process trying to get message */
X int src; /* which message source is wanted (or ANY) */
X***************
X*** 209,226 ****
X
X! register struct proc *caller_ptr, *sender_ptr, *previous_ptr;
X! int sender;
X
X- caller_ptr = proc_addr(caller); /* pointer to caller's proc struct */
X-
X /* Check to see if a message from desired source is already available. */
X! sender_ptr = caller_ptr->p_callerq;
X! if ((caller_ptr->p_flags & SENDING) == 0) {
X! while (sender_ptr != NIL_PROC) {
X! sender = sender_ptr - proc - NR_TASKS;
X! if (src == ANY || src == sender) {
X /* An acceptable message has been found. */
X! cp_mess(sender, sender_ptr->p_map[D].mem_phys,
X! sender_ptr->p_messbuf, caller_ptr->p_map[D].mem_phys, m_ptr);
X! sender_ptr->p_flags &= ~SENDING; /* deblock sender */
X! if (sender_ptr->p_flags == 0) ready(sender_ptr);
X if (sender_ptr == caller_ptr->p_callerq)
X--- 229,244 ----
X
X! register struct proc *sender_ptr;
X! register struct proc *previous_ptr;
X! int dest;
X
X /* Check to see if a message from desired source is already available. */
X! if (!(caller_ptr->p_flags & SENDING)) {
X! /* Check caller queue. */
X! for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
X! previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
X! if (src == ANY || src == proc_number(sender_ptr)) {
X /* An acceptable message has been found. */
X! cp_mess(proc_number(sender_ptr),
X! sender_ptr->p_map[D].mem_phys, sender_ptr->p_messbuf,
X! caller_ptr->p_map[D].mem_phys, m_ptr);
X if (sender_ptr == caller_ptr->p_callerq)
X***************
X*** 229,237 ****
X previous_ptr->p_sendlink = sender_ptr->p_sendlink;
X return(OK);
X }
X! previous_ptr = sender_ptr;
X! sender_ptr = sender_ptr->p_sendlink;
X! }
X! }
X
X /* No suitable message is available. Block the process trying to receive. */
X--- 247,263 ----
X previous_ptr->p_sendlink = sender_ptr->p_sendlink;
X+ if ((sender_ptr->p_flags &= ~SENDING) == 0)
X+ ready(sender_ptr); /* deblock sender */
X return(OK);
X }
X! }
X
X+ /* Check for blocked interrupt. */
X+ if (caller_ptr->p_int_blocked && isrxhardware(src)) {
X+ m_ptr->m_source = HARDWARE;
X+ m_ptr->m_type = HARD_INT;
X+ caller_ptr->p_int_blocked = FALSE;
X+ return(OK);
X+ }
X+ }
X+
X /* No suitable message is available. Block the process trying to receive. */
X***************
X*** 245,250 ****
X */
X! if (sig_procs > 0 && caller == MM_PROC_NR && src == ANY) {
X inform();
X- pick_proc();
X- }
X return(OK);
X--- 271,274 ----
X */
X! if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
X inform();
X return(OK);
X***************
X*** 256,258 ****
X *===========================================================================*/
X! PUBLIC pick_proc()
X {
X--- 280,282 ----
X *===========================================================================*/
X! PRIVATE pick_proc()
X {
X***************
X*** 260,288 ****
X
X! register int q; /* which queue to use */
X
X! if (rdy_head[TASK_Q] != NIL_PROC) q = TASK_Q;
X! else if (rdy_head[SERVER_Q] != NIL_PROC) q = SERVER_Q;
X! else q = USER_Q;
X
X! /* Set 'cur_proc' and 'proc_ptr'. If system is idle, set 'cur_proc' to a
X! * special value (IDLE), and set 'proc_ptr' to point to an unused proc table
X! * slot, namely, that of task -1 (HARDWARE), so save() will have somewhere to
X! * deposit the registers when an interrupt occurs on an idle machine.
X! * Record previous process so that when clock tick happens, the clock task
X! * can find out who was running just before it began to run. (While the clock
X! * task is running, 'cur_proc' = CLOCKTASK.) In addition, set 'bill_ptr'
X! * to always point to the process to be billed for CPU time.
X */
X! prev_proc = cur_proc;
X! if (rdy_head[q] != NIL_PROC) {
X! /* Someone is runnable. */
X! cur_proc = rdy_head[q] - proc - NR_TASKS;
X! proc_ptr = rdy_head[q];
X! if (cur_proc >= LOW_USER) bill_ptr = proc_ptr;
X! } else {
X! /* No one is runnable. */
X! cur_proc = IDLE;
X! proc_ptr = proc_addr(HARDWARE);
X! bill_ptr = proc_ptr;
X! }
X }
X--- 284,305 ----
X
X! register struct proc *rp; /* which queue to use */
X
X! if ( (rp = rdy_head[TASK_Q]) == NIL_PROC &&
X! (rp = rdy_head[SERVER_Q]) == NIL_PROC &&
X! (rp = rdy_head[USER_Q]) == NIL_PROC) {
X! /* Run the idle task. */
X! bill_ptr = proc_ptr = cproc_addr(IDLE);
X! return;
X! }
X
X! /* The new process is selected just by pointing proc_ptr at it.
X! * When a clock tick occurs while a non-user is running, the clock task has
X! * to decide which process to bill for system time.
X! * It uses the last user (or idle) process, which is recorded in 'bill_ptr'.
X! * This is slightly inaccurate because the last user gets billed for all
X! * interrupt activity.
X */
X! proc_ptr = rp;
X! if (isuserp(rp))
X! bill_ptr = rp;
X }
X***************
X*** 292,294 ****
X *===========================================================================*/
X! PUBLIC ready(rp)
X register struct proc *rp; /* this process is now runnable */
X--- 309,311 ----
X *===========================================================================*/
X! PRIVATE ready(rp)
X register struct proc *rp; /* this process is now runnable */
X***************
X*** 302,318 ****
X
X! register int q; /* TASK_Q, SERVER_Q, or USER_Q */
X! int r, old_state;
X!
X! old_state = lock(); /* disable interrupts */
X! r = (rp - proc) - NR_TASKS; /* task or proc number */
X! q = (r < 0 ? TASK_Q : r < LOW_USER ? SERVER_Q : USER_Q);
X!
X! /* See if the relevant queue is empty. */
X! if (rdy_head[q] == NIL_PROC)
X! rdy_head[q] = rp; /* add to empty queue */
X else
X! rdy_tail[q]->p_nextready = rp; /* add to tail of nonempty queue */
X! rdy_tail[q] = rp; /* new entry has no successor */
X rp->p_nextready = NIL_PROC;
X- restore(old_state); /* restore interrupts to previous state */
X }
X--- 319,345 ----
X
X! if (istaskp(rp)) {
X! if (rdy_head[TASK_Q] != NIL_PROC)
X! /* Add to tail of nonempty queue. */
X! rdy_tail[TASK_Q]->p_nextready = rp;
X! else
X! rdy_head[TASK_Q] = rp; /* add to empty queue */
X! rdy_tail[TASK_Q] = rp;
X! rp->p_nextready = NIL_PROC; /* new entry has no successor */
X! return;
X! }
X! if (!isuserp(rp)) { /* others are similar */
X! if (rdy_head[SERVER_Q] != NIL_PROC)
X! rdy_tail[SERVER_Q]->p_nextready = rp;
X! else
X! rdy_head[SERVER_Q] = rp;
X! rdy_tail[SERVER_Q] = rp;
X! rp->p_nextready = NIL_PROC;
X! return;
X! }
X! if (rdy_head[USER_Q] != NIL_PROC)
X! rdy_tail[USER_Q]->p_nextready = rp;
X else
X! rdy_head[USER_Q] = rp;
X! rdy_tail[USER_Q] = rp;
X rp->p_nextready = NIL_PROC;
X }
X***************
X*** 323,325 ****
X *===========================================================================*/
X! PUBLIC unready(rp)
X register struct proc *rp; /* this process is no longer runnable */
X--- 350,352 ----
X *===========================================================================*/
X! PRIVATE unready(rp)
X register struct proc *rp; /* this process is no longer runnable */
X***************
X*** 329,359 ****
X register struct proc *xp;
X! int r, q, old_state;
X
X! old_state = lock(); /* disable interrupts */
X! r = rp - proc - NR_TASKS;
X! q = (r < 0 ? TASK_Q : r < LOW_USER ? SERVER_Q : USER_Q);
X! if ( (xp = rdy_head[q]) == NIL_PROC) {
X! restore(old_state);
X! return;
X }
X! if (xp == rp) {
X! /* Remove head of queue */
X! rdy_head[q] = xp->p_nextready;
X! if (rp == proc_ptr) pick_proc();
X } else {
X! /* Search body of queue. A process can be made unready even if it is
X! * not running by being sent a signal that kills it.
X! */
X! while (xp->p_nextready != rp)
X! if ( (xp = xp->p_nextready) == NIL_PROC) {
X! restore(old_state);
X! return;
X! }
X! xp->p_nextready = xp->p_nextready->p_nextready;
X! while (xp->p_nextready != NIL_PROC) xp = xp->p_nextready;
X! rdy_tail[q] = xp;
X }
X- restore(old_state); /* restore interrupts to prev state */
X- }
X
X
X--- 356,407 ----
X register struct proc *xp;
X! register struct proc **qhead; /* TASK_Q, SERVER_Q, or USER_Q rdy_head */
X! register struct proc **qtail;
X
X! if (istaskp(rp)) {
X! if ( (xp = rdy_head[TASK_Q]) == NIL_PROC)
X! return;
X! if (xp == rp) {
X! /* Remove head of queue */
X! rdy_head[TASK_Q] = xp->p_nextready;
X! if (rp == proc_ptr)
X! pick_proc();
X! return;
X! }
X! qhead = &rdy_head[TASK_Q];
X! qtail = &rdy_tail[TASK_Q];
X }
X! else if (!isuserp(rp)) {
X! if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC)
X! return;
X! if (xp == rp) {
X! rdy_head[SERVER_Q] = xp->p_nextready;
X! pick_proc();
X! return;
X! }
X! qhead = &rdy_head[SERVER_Q];
X! qtail = &rdy_tail[SERVER_Q];
X } else {
X! if ( (xp = rdy_head[USER_Q]) == NIL_PROC)
X! return;
X! if (xp == rp) {
X! rdy_head[USER_Q] = xp->p_nextready;
X! pick_proc();
X! return;
X! }
X! qhead = &rdy_head[USER_Q];
X! qtail = &rdy_tail[USER_Q];
X }
X
X+ /* Search body of queue. A process can be made unready even if it is
X+ * not running by being sent a signal that kills it.
X+ */
X+ while (xp->p_nextready != rp)
X+ if ( (xp = xp->p_nextready) == NIL_PROC)
X+ return;
X+ xp->p_nextready = xp->p_nextready->p_nextready;
X+ while (xp->p_nextready != NIL_PROC)
X+ xp = xp->p_nextready;
X+ *qtail = xp;
X+ }
X+
X
X***************
X*** 362,364 ****
X *===========================================================================*/
X! PUBLIC sched()
X {
X--- 410,412 ----
X *===========================================================================*/
X! PRIVATE sched()
X {
X***************
X*** 369,378 ****
X
X! int old_state;
X
X- old_state = lock(); /* disable interrupts */
X- if (rdy_head[USER_Q] == NIL_PROC) {
X- restore(old_state); /* restore interrupts to prev state */
X- return;
X- }
X-
X /* One or more user processes queued. */
X--- 417,421 ----
X
X! if (rdy_head[USER_Q] == NIL_PROC)
X! return;
X
X /* One or more user processes queued. */
X***************
X*** 383,385 ****
X pick_proc();
X! restore(old_state); /* restore interrupts to prev state */
X }
X--- 426,538 ----
X pick_proc();
X! }
X!
X!
X! /*==========================================================================*
X! * proc_init *
X! *==========================================================================*/
X! PUBLIC proc_init()
X! {
X! /* Clear process table.
X! * Set up mappings for proc_addr() and proc_number() macros.
X! */
X!
X! register struct proc *rp;
X! int proc_nr;
X!
X! for (rp = BEG_PROC_ADDR, proc_nr = -NR_TASKS; rp < END_PROC_ADDR;
X! ++rp, ++proc_nr) {
X! rp->p_flags = P_SLOT_FREE;
X! rp->p_nr = proc_nr; /* proc number from ptr */
X! (pproc_addr + NR_TASKS)[proc_nr] = rp; /* proc ptr from number */
X! }
X! }
X!
X!
X! /*==========================================================================*
X! * lockmini_send *
X! *==========================================================================*/
X! PUBLIC int lockmini_send(caller_ptr, dest, m_ptr)
X! struct proc *caller_ptr;
X! int dest;
X! message *m_ptr;
X! {
X! int mini_result;
X!
X! switching = TRUE;
X! mini_result = mini_send(caller_ptr, dest, m_ptr);
X! switching = FALSE;
X! return(mini_result);
X! }
X!
X!
X! /*==========================================================================*
X! * lockpick_proc *
X! *==========================================================================*/
X! PUBLIC lockpick_proc()
X! {
X! switching = TRUE;
X! pick_proc();
X! switching = FALSE;
X! }
X!
X!
X! /*==========================================================================*
X! * lockready *
X! *==========================================================================*/
X! PUBLIC lockready(rp)
X! struct proc *rp;
X! {
X! switching = TRUE;
X! ready(rp);
X! switching = FALSE;
X! }
X!
X!
X! /*==========================================================================*
X! * locksched *
X! *==========================================================================*/
X! PUBLIC locksched()
X! {
X! switching = TRUE;
X! sched();
X! switching = FALSE;
X! }
X!
X!
X! /*==========================================================================*
X! * lockunready *
X! *==========================================================================*/
X! PUBLIC lockunready(rp)
X! struct proc *rp;
X! {
X! switching = TRUE;
X! unready(rp);
X! switching = FALSE;
X! }
X!
X!
X! /*==========================================================================*
X! * unhold *
X! *==========================================================================*/
X! PUBLIC unhold()
X! {
X! /* Flush any held-up interrupts. k_reenter must be 0. held_head must not
X! * be NIL_PROC. Interrupts must be disabled. They will be enabled but will
X! * be disabled when this returns.
X! */
X!
X! register struct proc *rp; /* current head of held queue */
X!
X! if (switching)
X! return;
X! rp = held_head;
X! do {
X! if ( (held_head = rp->p_nextheld) == NIL_PROC)
X! held_tail = NIL_PROC;
X! rp->p_int_held = FALSE;
X! unlock(); /* reduce latency; held queue may change! */
X! interrupt(proc_number(rp));
X! lock(); /* protect the held queue */
X! }
X! while ( (rp = held_head) != NIL_PROC);
X }
END_OF_FILE
if test 26431 -ne `wc -c <'kerneldif/proc.c.cdif'`; then
echo shar: \"'kerneldif/proc.c.cdif'\" unpacked with wrong size!
fi
# end of 'kerneldif/proc.c.cdif'
fi
if test -f 'kerneldif/proc.h.cdif' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kerneldif/proc.h.cdif'\"
else
echo shar: Extracting \"'kerneldif/proc.h.cdif'\" \(4435 characters\)
sed "s/^X//" >'kerneldif/proc.h.cdif' <<'END_OF_FILE'
X*** kernel-1.3/proc.h Wed Aug 3 21:18:39 1988
X--- kernel/proc.h Thu Mar 23 03:04:33 1989
X***************
X*** 1,6 ****
X! /* Here is the declaration of the process table. Three assembly code routines
X! * reference fields in it. They are restart(), save(), and csv(). When
X! * changing 'proc', be sure to change the field offsets built into the code.
X! * It contains the process' registers, memory map, accounting, and message
X! * send/receive information.
X */
X--- 1,6 ----
X! /* Here is the declaration of the process table. It contains the process'
X! * registers, memory map, accounting, and message send/receive information.
X! * Many assembly code routines reference fields in it. The offsets to these
X! * fields are defined in the assembler include file sconst.h. When changing
X! * 'proc', be sure to change sconst.h to match.
X */
X***************
X*** 8,15 ****
X EXTERN struct proc {
X! int p_reg[NR_REGS]; /* process' registers */
X! int *p_sp; /* stack pointer */
X! struct pc_psw p_pcpsw; /* pc and psw as pushed by interrupt */
X int p_flags; /* P_SLOT_FREE, SENDING, RECEIVING, etc. */
X struct mem_map p_map[NR_SEGS];/* memory map */
X- int *p_splimit; /* lowest legal stack value */
X int p_pid; /* process id passed in from MM */
X--- 8,26 ----
X EXTERN struct proc {
X! union stackframe_u p_reg; /* process' registers saved in stack frame */
X! int p_nr; /* number of this process (for fast access) */
X!
X! #ifdef i80286
X! u16_t p_ldt_sel; /* selector in gdt giving ldt base and limit*/
X! struct segdesc_s p_ldt[2]; /* local descriptor table cs:ds */
X! /* 2 is LDT_SIZE - avoid include protect.h */
X! #endif
X!
X! u16_t p_splimit; /* lowest legal stack value */
X!
X! int p_int_blocked; /* nonzero if int msg blocked by busy task */
X! int p_int_held; /* nonzero if int msg held by busy syscall */
X! struct proc *p_nextheld; /* next in chain of held-up int processes */
X!
X int p_flags; /* P_SLOT_FREE, SENDING, RECEIVING, etc. */
X struct mem_map p_map[NR_SEGS];/* memory map */
X int p_pid; /* process id passed in from MM */
X***************
X*** 29,31 ****
X int p_pending; /* bit map for pending signals 1-16 */
X! } proc[NR_TASKS+NR_PROCS];
X
X--- 40,43 ----
X int p_pending; /* bit map for pending signals 1-16 */
X! unsigned p_pendcount; /* count of pending and unfinished signals */
X! };
X
X***************
X*** 36,42 ****
X #define RECEIVING 010 /* set when process blocked trying to recv */
X! #define PENDING 020 /* set when process has signals pending */
X
X! #define proc_addr(n) &proc[NR_TASKS + n]
X! #define NIL_PROC (struct proc *) 0
X
X EXTERN struct proc *proc_ptr; /* &proc[cur_proc] */
X--- 48,76 ----
X #define RECEIVING 010 /* set when process blocked trying to recv */
X! #define PENDING 020 /* set when inform() of signal pending */
X! #define SIG_PENDING 040 /* keeps to-be-signalled proc from running */
X
X! /* Magic process table addresses. */
X! #define BEG_PROC_ADDR (&proc[0])
X! #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
X! #define END_TASK_ADDR (&proc[NR_TASKS])
X! #define BEG_SERV_ADDR (&proc[NR_TASKS])
X! #define BEG_USER_ADDR (&proc[NR_TASKS + LOW_USER])
X
X+ #define NIL_PROC (struct proc *) 0
X+ #define isidlehardware( n ) ((n) == IDLE || (n) == HARDWARE)
X+ #define isokprocn( n ) ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS)
X+ #define isoksrc_dest( n ) (isokprocn( n ) || (n) == ANY)
X+ #define isoksusern( n ) ((unsigned) (n) < NR_PROCS)
X+ #define isokusern( n ) ((unsigned) ((n) - LOW_USER) < NR_PROCS - LOW_USER)
X+ #define isrxhardware( n ) ((n) == ANY || (n) == HARDWARE)
X+ #define isservn( n ) ((unsigned) (n) < LOW_USER)
X+ #define istaskp( p ) ((p) < END_TASK_ADDR && (p) != cproc_addr( IDLE ))
X+ #define isuserp( p ) ((p) >= BEG_USER_ADDR )
X+ #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
X+ #define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
X+ #define proc_number(p) ((p)->p_nr)
X+
X+ EXTERN struct proc proc[NR_TASKS + NR_PROCS]; /* process table */
X+ EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
X+ /* ptrs to process table slots (fast) */
X EXTERN struct proc *proc_ptr; /* &proc[cur_proc] */
X***************
X*** 45,48 ****
X EXTERN struct proc *rdy_tail[NQ]; /* pointers to ready list tails */
X-
X- EXTERN unsigned busy_map; /* bit map of busy tasks */
X- EXTERN message *task_mess[NR_TASKS+1]; /* ptrs to messages for busy tasks */
X--- 79 ----
END_OF_FILE
if test 4435 -ne `wc -c <'kerneldif/proc.h.cdif'`; then
echo shar: \"'kerneldif/proc.h.cdif'\" unpacked with wrong size!
fi
# end of 'kerneldif/proc.h.cdif'
fi
if test -f 'kerneldif/protect.h.cdif' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kerneldif/protect.h.cdif'\"
else
echo shar: Extracting \"'kerneldif/protect.h.cdif'\" \(5010 characters\)
sed "s/^X//" >'kerneldif/protect.h.cdif' <<'END_OF_FILE'
X*** /dev/null Thu Oct 13 22:40:42 1988
X--- kernel/protect.h Fri Mar 24 01:52:27 1989
X***************
X*** 0 ****
X--- 1,104 ----
X+ /* 286 software constants. */
X+
X+ /* Table sizes. */
X+ #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) /* spec. and LDT's */
X+ #define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */
X+ #define LDT_SIZE 2 /* contains CS and DS only */
X+
X+ /* Fixed global descriptors; 1 to 7 are prescribed by the BIOS. */
X+ #define GDT_INDEX 1 /* temp spot to store pointer to GDT */
X+ #define IDT_INDEX 2 /* temp spot to store pointer to GDT */
X+ #define DS_INDEX 3 /* kernel DS */
X+ #define ES_INDEX 4 /* kernel ES */
X+ #define SS_INDEX 5 /* kernel SS */
X+ #define CS_INDEX 6 /* kernel CS */
X+ #define BIOS_CS_INDEX 7 /* temp for BIOS */
X+ #define TSS_INDEX 8 /* kernel TSS */
X+ #define DB_TSS_INDEX 9 /* debugger TSS */
X+ #define DS_286_INDEX 10 /* scratch source segment for klib286 */
X+ #define ES_286_INDEX 11 /* scratch destination segment for klib286 */
X+ #define COLOR_INDEX 12 /* color screen segment */
X+ #define MONO_INDEX 13 /* mono screen segment */
X+ /* the next 2 only work for 386's but are
X+ * reserved for debugging 286 code on 386's
X+ */
X+ #define REAL_CS_INDEX 14 /* kernel CS suitable for real mode switch */
X+ #define REAL_DS_INDEX 15 /* kernel DS suitable for real mode switch */
X+ #define FIRST_LDT_INDEX 16
X+
X+ #define GDT_SELECTOR 0x08 /* (GDT_INDEX * DESC_SIZE) bad for asld */
X+ #define IDT_SELECTOR 0x10 /* (IDT_INDEX * DESC_SIZE) */
X+ #define DS_SELECTOR 0x18 /* (DS_INDEX * DESC_SIZE) */
X+ #define CS_SELECTOR 0x30 /* (CS_INDEX * DESC_SIZE) */
X+ #define BIOS_CS_SELECTOR 0x38 /* (BIOS_CS_INDEX * DESC_SIZE) */
X+ #define TSS_SELECTOR 0x40 /* (TSS_INDEX * DESC_SIZE) */
X+ #define DB_TSS_SELECTOR 0x48 /* (DB_TSS_INDEX * DESC_SIZE) */
X+ #define DS_286_SELECTOR 0x51 /* (DS_286_INDEX * DESC_SIZE + 1) */
X+ #define ES_286_SELECTOR 0x59 /* (DS_286_INDEX * DESC_SIZE + 1) */
X+ #define COLOR_SELECTOR 0x61 /* (COLOR_INDEX * DESC_SIZE + 1) */
X+ #define MONO_SELECTOR 0x69 /* (MONO_INDEX * DESC_SIZE + 1) */
X+ #define REAL_CS_SELECTOR 0x70 /* (REAL_CS_INDEX * DESC_SIZE) */
X+ #define REAL_DS_SELECTOR 0x78 /* (REAL_DS_INDEX * DESC_SIZE) */
X+
X+ /* Fixed local descriptors. */
X+ #define CS_LDT_INDEX 0 /* process CS */
X+ #define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */
X+
X+ /* Privileges. */
X+ #define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
X+ #define TASK_PRIVILEGE 1
X+ #define USER_PRIVILEGE 3
X+
X+ /* 286 hardware constants. */
X+
X+ /* Exception vector numbers. */
X+ #define BOUNDS_VECTOR 5 /* bounds check failed */
X+ #define INVAL_OP_VECTOR 6 /* invalid opcode */
X+ #define COPROC_NOT_VECTOR 7 /* coprocessor not available */
X+ #define DOUBLE_FAULT_VECTOR 8
X+ #define COPROC_SEG_VECTOR 9 /* coprocessor segment overrun */
X+ #define INVAL_TSS_VECTOR 10 /* invalid TSS */
X+ #define SEG_NOT_VECTOR 11 /* segment not present */
X+ #define STACK_FAULT_VECTOR 12 /* stack exception */
X+ #define PROTECTION_VECTOR 13 /* general protection */
X+
X+ /* Selector bits. */
X+ #define TI 0x04 /* table indicator */
X+ #define RPL 0x03 /* requester privilege level */
X+
X+ /* Descriptor structure offsets. */
X+ #define DESC_BASE 2 /* to base_low */
X+ #define DESC_BASE_MIDDLE 4 /* to base_middle */
X+ #define DESC_ACCESS 5 /* to access byte */
X+ #define DESC_SIZE 8 /* sizeof (struct segdesc_s) */
X+
X+ /* Segment sizes. */
X+ #define MAX_286_SEG_SIZE 0x10000L
X+ #define REAL_SEG_SIZE 0x10000L
X+
X+ /* Base and limit sizes and shifts. */
X+ #define BASE_MIDDLE_SHIFT 16 /* shift for base --> base_middle */
X+
X+ /* Access-byte and type-byte bits. */
X+ #define PRESENT 0x80 /* set for descriptor present */
X+ #define DPL 0x60 /* descriptor privilege level mask */
X+ #define DPL_SHIFT 5
X+ #define SEGMENT 0x10 /* set for segment-type descriptors */
X+
X+ /* Access-byte bits. */
X+ #define EXECUTABLE 0x08 /* set for executable segment */
X+ #define CONFORMING 0x04 /* set for conforming segment if executable */
X+ #define EXPAND_DOWN 0x04 /* set for expand-down segment if !executab */
X+ #define READABLE 0x02 /* set for readable segment if executable */
X+ #define WRITEABLE 0x02 /* set for writeable segment if !executable */
X+ #define TSS_BUSY 0x02 /* set if TSS descriptor is busy */
X+ #define ACCESSED 0x01 /* set if segment accessed */
X+
X+ /* Special descriptor types. */
X+ #define AVL_286_TSS 1 /* available 286 TSS */
X+ #define LDT 2 /* local descriptor table */
X+ #define BUSY_286_TSS 3 /* set transparently to the software */
X+ #define CALL_286_GATE 4 /* not used */
X+ #define TASK_GATE 5 /* only used by debugger */
X+ #define INT_286_GATE 6 /* interrupt gate, used for all vectors */
X+ #define TRAP_286_GATE 7 /* not used */
END_OF_FILE
if test 5010 -ne `wc -c <'kerneldif/protect.h.cdif'`; then
echo shar: \"'kerneldif/protect.h.cdif'\" unpacked with wrong size!
fi
# end of 'kerneldif/protect.h.cdif'
fi
if test -f 'kerneldif/type.h.cdif' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kerneldif/type.h.cdif'\"
else
echo shar: Extracting \"'kerneldif/type.h.cdif'\" \(2827 characters\)
sed "s/^X//" >'kerneldif/type.h.cdif' <<'END_OF_FILE'
X*** kernel-1.3/type.h Wed Aug 3 21:18:39 1988
X--- kernel/type.h Sun Mar 12 18:45:14 1989
X***************
X*** 1,22 ****
X! /* The 'pc_psw' struct is machine dependent. It must contain the information
X! * pushed onto the stack by an interrupt, in the same format as the hardware
X! * creates and expects. It is used for storing the interrupt status after a
X! * trap or interrupt, as well as for causing interrupts for signals.
X! */
X!
X! #ifdef i8088
X! struct pc_psw {
X! int (*pc)(); /* storage for program counter */
X! phys_clicks cs; /* code segment register */
X! unsigned psw; /* program status word */
X! };
X!
X! /* This struct is used to build data structure pushed by kernel upon signal. */
X! struct sig_info {
X! int signo; /* sig number at end of stack */
X! struct pc_psw sigpcpsw;
X! };
X! #endif
X!
X! PUBLIC struct tasktab {
X int (*initial_pc)();
X--- 1,2 ----
X! struct tasktab {
X int (*initial_pc)();
X***************
X*** 25 ****
X--- 5,58 ----
X };
X+
X+ #ifdef i8088
X+
X+ /* The u.._t types and their derivatives are used (only) when the precise
X+ * size must be specified for alignment of machine-dependent structures.
X+ * The offset_t type is the promotion of the smallest unsigned type large
X+ * enough to hold all machine offsets. The phys_bytes type is not right
X+ * since it is signed, so will break on future 386 systems which have real
X+ * or virtual memory in the top half of the address space. Also, signed
X+ * remainders and divisions by powers of 2 cannot be done as efficiently.
X+ */
X+ typedef unsigned long offset_t; /* machine offset */
X+ typedef unsigned char u8_t; /* unsigned 8 bits */
X+ typedef unsigned short u16_t; /* unsigned 16 bits */
X+ typedef unsigned long u32_t; /* unsigned 32 bits */
X+
X+ /* The stack frame layout is determined by the software, but for efficiency
X+ * it is laid out so the assembly code to use it is as simple as possible.
X+ * 80286 protected mode and all real modes use the same frame, built with
X+ * 16-bit registers. Real mode lacks an automatic stack switch, so little
X+ * is lost by using the 286 frame for it.
X+ */
X+ union stackframe_u {
X+ struct {
X+ u16_t es;
X+ u16_t ds;
X+ u16_t di; /* di through cx are not accessed in C */
X+ u16_t si; /* order is to match pusha/popa */
X+ u16_t bp;
X+ u16_t st; /* hole for another copy of sp */
X+ u16_t bx;
X+ u16_t dx;
X+ u16_t cx;
X+ u16_t retreg; /* ax */
X+ u16_t retadr; /* return address for assembly code save() */
X+ u16_t pc; /* interrupt pushes rest of frame */
X+ u16_t cs;
X+ u16_t psw;
X+ u16_t sp;
X+ u16_t ss;
X+ } r16;
X+ };
X+
X+ #ifdef i80286
X+ struct segdesc_s { /* segment descriptor */
X+ u16_t limit_low;
X+ u16_t base_low;
X+ u8_t base_middle;
X+ u8_t access; /* |P|DL|1|X|E|R|A| */
X+ u16_t reserved;
X+ };
X+ #endif /* i80286 */
X+ #endif /* i8088 */
END_OF_FILE
if test 2827 -ne `wc -c <'kerneldif/type.h.cdif'`; then
echo shar: \"'kerneldif/type.h.cdif'\" unpacked with wrong size!
fi
# end of 'kerneldif/type.h.cdif'
fi
echo shar: End of archive 7 \(of 10\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 10 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Division of Information Technology (Melbourne), Phone +61 3 347 8644
C.S.I.R.O. Fax +61 3 347 8987
55 Barry St. Telex AA 152914
Carlton, Vic, 3053, Australia E-mail: worsley@ditmela.oz.au