[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ser. overruns/deadlock fix



The following set of patches rel to h1 Megapatch (sorry, hadn't yet
the time to get h2 or h3) is a better solution (at least I think) to
the 'endless serial overruns' story, because it avoids the spl7()
in Fselect() completely plus fixes an Fselect deadlock.

The solution is as follows:

curproc->wait_cond = condition;
while (curproc->wait_cond == condition) {
	sleep (SELECT_Q | 0x100, condition);
}

works the same as

curproc->wait_cond = condition;
sr = spl7();
while (curproc->wait_cond == condition) {
	sleep (SELECT_Q, condition);
}
spl(sr);

The 0x100 tells sleep() to return without sleeping when curproc->wait_cond
changes. This way we don't need spl7 (avoiding endless serial overruns).
Also fixes a deadlock with checkkeys/checkbttys. They are called from
sleep and may wakeselect() curproc. But sleep used to reset curproc->wait_cond
to (long)wakeselect causing curproc to sleep forever.

Kay.

*** ../mint-110h1.orig/proc.c	Mon Jun 20 23:20:20 1994
--- proc.c	Mon Jun 20 23:24:10 1994
***************
*** 9,15 ****
  #include "mint.h"
  #include "xbra.h"
  
! static void do_wakeup_things P_((short sr));
  
  extern short proc_clock;
  
--- 9,15 ----
  #include "mint.h"
  #include "xbra.h"
  
! static void do_wakeup_things P_((void));
  
  extern short proc_clock;
  
***************
*** 419,426 ****
   */
  
  static void
! do_wakeup_things(sr)
! short sr;
  {
  /*
   * check for stack underflow, just in case
--- 419,425 ----
   */
  
  static void
! do_wakeup_things()
  {
  /*
   * check for stack underflow, just in case
***************
*** 430,438 ****
  
  	p = curproc;
  
- 	if ((sr & 0x700) < 0x500) {
- /* skip all this if int level is too high */
- 
  	if ( p->pid != 0 &&
  	     ((long)&foo) < (long)p->stack + ISTKSIZE + 512 ) {
  		ALERT("stack underflow");
--- 429,434 ----
***************
*** 455,461 ****
  	checkalarms();
  	if (p->sigpending)
  		check_sigs();		/* check for signals */
- 	}
  
  	if (p->slices >= 0) {
  	proc_clock = TIME_SLICE;	/* get a fresh time slice */
--- 451,456 ----
***************
*** 472,483 ****
   */
  
  int ARGS_ON_STACK 
! sleep(que, cond)
! 	int que;
  	long cond;
  {
  	PROC *p;
! 	short sr;
  	ulong onsigs = curproc->nsigs;
  	extern short kintr;	/* in bios.c */
  #ifndef MULTITOS
--- 467,478 ----
   */
  
  int ARGS_ON_STACK 
! sleep(_que, cond)
! 	int _que;
  	long cond;
  {
  	PROC *p;
! 	short sr, que = _que & 0xff;
  	ulong onsigs = curproc->nsigs;
  	extern short kintr;	/* in bios.c */
  #ifndef MULTITOS
***************
*** 490,509 ****
   * if there have been keyboard interrupts since our last sleep, check for
   * special keys like CTRL-ALT-Fx
   */
! 
! 	sr = spl7();
! 	if (kintr && (sr & 0x700) < 0x500) {
! /* can't call checkkeys if sleep was called with interrupts off  -nox */
! 		spl(sr);
  		(void)checkkeys();
- 		sr = spl7();
  		kintr = 0;
  	}
  
! 	if (que == READY_Q && !sys_q[READY_Q]) {
  /* we're just going to wake up again right away! */
  		spl(sr);
! 		do_wakeup_things(sr);
  		return (onsigs != curproc->nsigs);
  	}
  
--- 485,507 ----
   * if there have been keyboard interrupts since our last sleep, check for
   * special keys like CTRL-ALT-Fx
   */
! 	checkbttys();
! 	if (kintr) {
  		(void)checkkeys();
  		kintr = 0;
  	}
  
! 	sr = spl7();
! /*
!  * kay: If _que & 0x100 != 0 then take curproc->wait_cond != cond as an
!  * indicatation that the wakeup has already happend before we actually
!  * go to sleep and return immediatly.
!  */
! 	if ((_que & 0x100 && curproc->wait_cond != cond) ||
! 	    (que == READY_Q && !sys_q[READY_Q])) {
  /* we're just going to wake up again right away! */
  		spl(sr);
! 		do_wakeup_things();
  		return (onsigs != curproc->nsigs);
  	}
  
***************
*** 559,566 ****
  
  	rm_q(READY_Q, p);
  
- 	spl(sr);
- 
  	if (save_context(&(curproc->ctxt[CURRENT]))) {
  /*
   * restore per-process variables here
--- 557,562 ----
***************
*** 571,577 ****
  #endif
  			*((void **)0x44eL) = curproc->logbase;
  #endif
! 		do_wakeup_things(sr);
  		return (onsigs != curproc->nsigs);
  	}
  /*
--- 567,573 ----
  #endif
  			*((void **)0x44eL) = curproc->logbase;
  #endif
! 		do_wakeup_things();
  		return (onsigs != curproc->nsigs);
  	}
  /*
***************
*** 583,588 ****
--- 579,590 ----
  #endif
  		curproc->logbase = *((void **)0x44eL);
  #endif
+ 
+ /*
+  * kay: We were at spl7 when doing the save_context(). Correct this.
+  */
+ 	curproc->ctxt[CURRENT].sr &= ~0x0700;
+ 	curproc->ctxt[CURRENT].sr |= sr & 0x0700;
  	curproc->ctxt[CURRENT].regs[0] = 1;
  	curproc = p;
  	proc_clock = TIME_SLICE;	/* fresh time */
*** ../mint-110h1.orig/dosfile.c	Mon Jun 20 23:19:54 1994
--- dosfile.c	Mon Jun 20 11:54:44 1994
***************
*** 977,983 ****
  	FILEPTR *f;
  	PROC *p;
  	TIMEOUT *t;
- 	short sr;
  
  	if (xfdp)
  		*xfdp = 0;
--- 977,982 ----
***************
*** 1045,1051 ****
  	}
  
  	if (count == 0) {
- 		ulong onsigs;
  		/* OK, now let's set a timeout */
  
  		if (timeout) {
--- 1044,1049 ----
***************
*** 1054,1079 ****
  			t = 0;
  		}
  
- 		TRACE(("sleeping in Fselect"));
- 		sr = spl7();
- 
  	/* curproc->wait_cond changes when data arrives or the timeout happens */
- 		onsigs = curproc->nsigs;
  		while (curproc->wait_cond == (long)wakeselect) {
- #if 0
- /* better not call BIOS with interrupts off, especially not Bconin... :) */
  			TRACE(("sleeping in Fselect"));
! #endif
! 			sleep(SELECT_Q, (long)wakeselect);
! 			if (curproc->sigpending) {
! 				spl(sr);	/* check for signals */
! 				check_sigs();
! 				sr = spl7();
! 			}
! 			if (onsigs != curproc->nsigs)
  				break;
  		}
- 		spl(sr);
  
  	/* we can cancel the time out now (if it hasn't already happened) */
  		if (t) canceltimeout(t);
--- 1052,1072 ----
  			t = 0;
  		}
  
  	/* curproc->wait_cond changes when data arrives or the timeout happens */
  		while (curproc->wait_cond == (long)wakeselect) {
  			TRACE(("sleeping in Fselect"));
! 			/*
! 			 * The 0x100 tells sleep() to return without sleeping
! 			 * when curproc->wait_cond changes. This way we don't
! 			 * need spl7 (avoiding endless serial overruns).
! 			 * Also fixes a deadlock with checkkeys/checkbttys.
! 			 * They are called from sleep and may wakeselect()
! 			 * curproc. But sleep used to reset curproc->wait_cond
! 			 * to wakeselect causing curproc to sleep forever.
! 			 */
! 			if (sleep(SELECT_Q|0x100, (long)wakeselect))
  				break;
  		}
  
  	/* we can cancel the time out now (if it hasn't already happened) */
  		if (t) canceltimeout(t);