[comp.os.minix] Protected mode MINIX for 80286 Part 7 - By Bruce Evans

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