[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Mint 1.11 beta: fselect bug
Unfortunately Mint 1.11's collision detection code in Fselect doesn't
work at all. The following patch fixes this, implements collision
detection for exceptional conditions and add's a missing call to
dev->unselect.
Kay.
*** dosfile.c.orig Fri Aug 19 23:08:36 1994
--- dosfile.c Sat Aug 20 16:23:22 1994
***************
*** 281,286 ****
--- 281,288 ----
if (f->dev) {
(*f->dev->unselect)(f, (long)p, O_RDONLY);
(*f->dev->unselect)(f, (long)p, O_WRONLY);
+ (*f->dev->unselect)(f, (long)p, O_RDWR);
+ wake (SELECT_Q, (long)&select_coll);
}
f->links--;
***************
*** 967,996 ****
unsigned timeout;
long *rfdp, *wfdp, *xfdp;
{
! long rfd, wfd, xfd;
long mask, bytes;
int i, count;
FILEPTR *f;
PROC *p;
TIMEOUT *t;
int rsel;
! int collision;
if (rfdp) {
! rfd = *rfdp;
}
else
! rfd = 0;
if (wfdp) {
! wfd = *wfdp;
}
else
! wfd = 0;
if (xfdp) {
! xfd = *xfdp;
} else {
! xfd = 0;
}
/* watch out for aliasing */
--- 969,999 ----
unsigned timeout;
long *rfdp, *wfdp, *xfdp;
{
! long rfd, wfd, xfd, col_rfd, col_wfd, col_xfd;
long mask, bytes;
int i, count;
FILEPTR *f;
PROC *p;
TIMEOUT *t;
int rsel;
! long wait_cond;
! short sr;
if (rfdp) {
! col_rfd = rfd = *rfdp;
}
else
! col_rfd = rfd = 0;
if (wfdp) {
! col_wfd = wfd = *wfdp;
}
else
! col_wfd = wfd = 0;
if (xfdp) {
! col_xfd = xfd = *xfdp;
} else {
! col_xfd = xfd = 0;
}
/* watch out for aliasing */
***************
*** 1024,1081 ****
curproc->wait_cond = (long)wakeselect; /* flag */
- /* NOTE to the above note: since we can get here several times (in
- * case of collisions) after we've gone to sleep, we probably cannot
- * assume the filepointers are valid.
- * I'm not really sure, because `post_sig' sets curproc->wait_cond
- * to zero and then we cannot get here after we've gone to sleep.
- */
-
retry_after_collision:
mask = 1L;
! collision = 0;
count = 0;
for (i = 0; i < MAX_OPEN; i++) {
! if (rfd & mask) {
f = p->handle[i];
if (is_terminal(f))
rsel = tty_select(f, (long)p, O_RDONLY);
else
rsel = (*f->dev->select)(f, (long)p, O_RDONLY);
! if (rsel == 1) {
count++;
*rfdp |= mask;
! } else if (rsel == 2) {
! collision++;
! } else if (rsel == 0) {
! *rfdp &= ~mask;
}
}
! if (wfd & mask) {
f = p->handle[i];
if (is_terminal(f))
rsel = tty_select(f, (long)p, O_WRONLY);
else
rsel = (*f->dev->select)(f, (long)p, O_WRONLY);
! if (rsel == 1) {
count++;
*wfdp |= mask;
! } else if (rsel == 2) {
! collision++;
! } else if (rsel == 0) {
! *wfdp &= ~mask;
}
}
! if (xfd & mask) {
f = p->handle[i];
/* tesche: anybody worried about using O_RDWR for exceptional data? ;) */
! if ((*f->dev->select)(f, (long)p, O_RDWR) == 1) {
/* tesche: for old device drivers, which don't understand this
* call, this will never be true and therefore won't disturb us here.
*/
count++;
*xfdp |= mask;
}
}
mask = mask << 1L;
--- 1027,1094 ----
curproc->wait_cond = (long)wakeselect; /* flag */
retry_after_collision:
mask = 1L;
! wait_cond = (long)wakeselect;
count = 0;
for (i = 0; i < MAX_OPEN; i++) {
! if (col_rfd & mask) {
f = p->handle[i];
if (is_terminal(f))
rsel = tty_select(f, (long)p, O_RDONLY);
else
rsel = (*f->dev->select)(f, (long)p, O_RDONLY);
! switch (rsel) {
! case 1:
count++;
*rfdp |= mask;
! break;
! case 2:
! wait_cond = (long)&select_coll;
! break;
! case 0:
! col_rfd &= ~mask;
! break;
}
}
! if (col_wfd & mask) {
f = p->handle[i];
if (is_terminal(f))
rsel = tty_select(f, (long)p, O_WRONLY);
else
rsel = (*f->dev->select)(f, (long)p, O_WRONLY);
! switch (rsel) {
! case 1:
count++;
*wfdp |= mask;
! break;
! case 2:
! wait_cond = (long)&select_coll;
! break;
! case 0:
! col_wfd &= ~mask;
! break;
}
}
! if (col_xfd & mask) {
f = p->handle[i];
/* tesche: anybody worried about using O_RDWR for exceptional data? ;) */
! rsel = (*f->dev->select)(f, (long)p, O_RDWR);
/* tesche: for old device drivers, which don't understand this
* call, this will never be true and therefore won't disturb us here.
*/
+ switch (rsel) {
+ case 1:
count++;
*xfdp |= mask;
+ break;
+ case 2:
+ wait_cond = (long)&select_coll;
+ break;
+ case 0:
+ col_xfd &= ~mask;
+ break;
}
}
mask = mask << 1L;
***************
*** 1088,1094 ****
--- 1101,1110 ----
}
/* curproc->wait_cond changes when data arrives or the timeout happens */
+ sr = spl7();
while (curproc->wait_cond == (long)wakeselect) {
+ curproc->wait_cond = wait_cond;
+ spl(sr);
/*
* The 0x100 tells sleep() to return without sleeping
* when curproc->wait_cond changes. This way we don't
***************
*** 1098,1110 ****
* curproc. But sleep used to reset curproc->wait_cond
* to wakeselect causing curproc to sleep forever.
*/
! if (sleep(SELECT_Q|0x100, (long)wakeselect))
curproc->wait_cond = 0;
}
if (curproc->wait_cond == (long)&select_coll) {
curproc->wait_cond = (long)wakeselect;
goto retry_after_collision;
}
/* we can cancel the time out now (if it hasn't already happened) */
if (t) canceltimeout(t);
--- 1114,1129 ----
* curproc. But sleep used to reset curproc->wait_cond
* to wakeselect causing curproc to sleep forever.
*/
! if (sleep(SELECT_Q|0x100, wait_cond))
curproc->wait_cond = 0;
+ sr = spl7();
}
if (curproc->wait_cond == (long)&select_coll) {
curproc->wait_cond = (long)wakeselect;
+ spl(sr);
goto retry_after_collision;
}
+ spl(sr);
/* we can cancel the time out now (if it hasn't already happened) */
if (t) canceltimeout(t);
***************
*** 1181,1187 ****
}
/* wake other processes which got a collision */
! if (rfd || wfd)
wake(SELECT_Q, (long)&select_coll);
TRACE(("Fselect: returning %d", count));
--- 1200,1206 ----
}
/* wake other processes which got a collision */
! if (rfd || wfd || xfd)
wake(SELECT_Q, (long)&select_coll);
TRACE(("Fselect: returning %d", count));