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