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