[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);