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

fselect() ...



These diffs make Fselect() work for multiple
processes selecting on the same file.

The diffs are relative to 1.09 with my sleep()
patches already applied (look at my previous
message, the new Fselect() will only work with
the patched sleep()).

Cheers -- Kay.

*** ../new/biosfs.c	Fri Oct 22 20:58:26 1993
--- biosfs.c	Mon Sep 13 21:41:28 1993
***************
*** 1236,1243 ****
  		}
  		if (tty) {
  		/* avoid collisions with other processes */
! 			if (!tty->rsel)
! 				tty->rsel = p;
  		}
  		return 0;
  	} else if (mode == O_WRONLY) {
--- 1240,1248 ----
  		}
  		if (tty) {
  		/* avoid collisions with other processes */
! 			if (tty->rsel)
! 				return 2; /* collsion */
! 			tty->rsel = p;
  		}
  		return 0;
  	} else if (mode == O_WRONLY) {
***************
*** 1246,1253 ****
  			return 1;
  		}
  		if (tty) {
! 			if (!tty->wsel)
! 				tty->wsel = p;
  		}
  		return 0;
  	}
--- 1251,1259 ----
  			return 1;
  		}
  		if (tty) {
! 			if (tty->wsel)
! 				return 2; /* collision */
! 			tty->wsel = p;
  		}
  		return 0;
  	}
***************
*** 1482,1489 ****
  	if (mousetail - mousehead)
  		return 1;	/* input waiting already */
  
! 	if (!mousersel)
! 		mousersel = p;
  	return 0;
  }
  
--- 1488,1496 ----
  	if (mousetail - mousehead)
  		return 1;	/* input waiting already */
  
! 	if (mousersel)
! 		return 2; /* collision */
! 	mousersel = p;
  	return 0;
  }
  
*** ../new/dosfile.c	Fri Oct 22 20:58:26 1993
--- dosfile.c	Fri Oct 22 19:11:58 1993
***************
*** 11,16 ****
--- 11,19 ----
  static long do_dup P_((int,int));
  static void unselectme P_((PROC *));
  
+ /* wait condition for selecting processes which got collisions */
+ short select_coll;
+ 
  /*
   * first, some utility routines
   */
***************
*** 274,279 ****
--- 277,284 ----
  	if (f->dev) {
  		(*f->dev->unselect)(f, (long)p, O_RDONLY);
  		(*f->dev->unselect)(f, (long)p, O_WRONLY);
+ /* give other processes a chance to select on this file */
+ 		wake(SELECT_Q, (long)&select_coll);
  	}
  
  	f->links--;
***************
*** 957,983 ****
  	unsigned timeout;
  	long *rfdp, *wfdp, *xfdp;
  {
! 	long rfd, wfd;
  	long mask, bytes;
  	int i, count;
  	FILEPTR *f;
  	PROC *p;
! 	TIMEOUT *t;
  	short sr;
  
  	if (xfdp)
  		*xfdp = 0;
  
  	if (rfdp) {
! 		rfd = *rfdp; *rfdp = 0;
  	}
  	else
! 		rfd = 0;
  	if (wfdp) {
! 		wfd = *wfdp; *wfdp = 0;
  	}
  	else
! 		wfd = 0;
  
  	TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
  	p = curproc;			/* help the optimizer out */
--- 962,988 ----
  	unsigned timeout;
  	long *rfdp, *wfdp, *xfdp;
  {
! 	long rfd, wfd, orfd, owfd;
  	long mask, bytes;
  	int i, count;
  	FILEPTR *f;
  	PROC *p;
! 	TIMEOUT *t = 0;
  	short sr;
  
  	if (xfdp)
  		*xfdp = 0;
  
  	if (rfdp) {
! 		orfd = rfd = *rfdp; *rfdp = 0;
  	}
  	else
! 		orfd = rfd = 0;
  	if (wfdp) {
! 		owfd = wfd = *wfdp; *wfdp = 0;
  	}
  	else
! 		owfd = wfd = 0;
  
  	TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
  	p = curproc;			/* help the optimizer out */
***************
*** 985,991 ****
  	/* first, validate the masks */
  	mask = 1L;
  	for (i = 0; i < MAX_OPEN; i++) {
! 		if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) {
  			DEBUG(("Fselect: invalid handle: %d", i));
  			return EIHNDL;
  		}
--- 990,996 ----
  	/* first, validate the masks */
  	mask = 1L;
  	for (i = 0; i < MAX_OPEN; i++) {
! 		if ( ((orfd & mask) || (owfd & mask)) && !(p->handle[i]) ) {
  			DEBUG(("Fselect: invalid handle: %d", i));
  			return EIHNDL;
  		}
***************
*** 1001,1043 ****
   * closed one of the handles.
   */
  
- 	mask = 1L;
  	count = 0;
  	curproc->wait_cond = (long)wakeselect;		/* flag */
  
  	for (i = 0; i < MAX_OPEN; i++) {
  		if (rfd & mask) {
  			f = p->handle[i];
! 			if ((*f->dev->select)(f, (long)p, O_RDONLY)) {
  				count++;
  				*rfdp |= mask;
  			}
  		}
  		if (wfd & mask) {
  			f = p->handle[i];
! 			if ((*f->dev->select)(f, (long)p, O_WRONLY)) {
  				count++;
  				*wfdp |= mask;
  			}
  		}
  		mask = mask << 1L;
  	}
  
  	if (count == 0) {
! 		/* OK, now let's set a timeout */
  
! 		if (timeout) {
  			t = addtimeout((long)timeout, unselectme);
- 		} else {
- 			t = 0;
  		}
  
  		sr = spl7();
  
  	/* curproc->wait_cond changes when data arrives or the timeout happens */
  		while (curproc->wait_cond == (long)wakeselect) {
  			TRACE(("sleeping in Fselect"));
! 			sleep(SELECT_Q, (long)wakeselect);
  		}
  		spl(sr);
  
--- 1006,1075 ----
   * closed one of the handles.
   */
  
  	count = 0;
  	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;
+ 	
  	for (i = 0; i < MAX_OPEN; i++) {
  		if (rfd & mask) {
  			f = p->handle[i];
! 			if (f) {
! 			    switch ((*f->dev->select)(f, (long)p, O_RDONLY)) {
! 			    case 1:
  				count++;
  				*rfdp |= mask;
+ 			    case 0:
+ 				rfd &= ~mask;
+ 			    }
  			}
  		}
  		if (wfd & mask) {
  			f = p->handle[i];
! 			if (f) {
! 			    switch ((*f->dev->select)(f, (long)p, O_WRONLY)) {
! 			    case 1:
  				count++;
  				*wfdp |= mask;
+ 			    case 0:
+ 				wfd &= ~mask;
+ 			    }
  			}
  		}
  		mask = mask << 1L;
  	}
  
  	if (count == 0) {
! 	/* OK, now let's set a timeout, but only the first time we get here */
  
! 		if (!t && timeout) {
  			t = addtimeout((long)timeout, unselectme);
  		}
  
  		sr = spl7();
  
  	/* curproc->wait_cond changes when data arrives or the timeout happens */
  		while (curproc->wait_cond == (long)wakeselect) {
+ 			long cond = (rfd || wfd) ? (long)&select_coll
+ 						 : (long)wakeselect;
+ 						 
  			TRACE(("sleeping in Fselect"));
! 			if (sleep(SELECT_Q, cond))
! 				curproc->wait_cond = 0;
! 		}
! 		if (curproc->wait_cond == (long)&select_coll) {
! 			curproc->wait_cond = (long)wakeselect;
! 			spl(sr);
! 			goto retry_after_collision;
  		}
  		spl(sr);
  
***************
*** 1047,1053 ****
  	/* OK, let's see what data arrived (if any) */
  		mask = 1L;
  		for (i = 0; i < MAX_OPEN; i++) {
! 			if (rfd & mask) {
  				f = p->handle[i];
  				if (f) {
  				    bytes = 1L;
--- 1079,1085 ----
  	/* OK, let's see what data arrived (if any) */
  		mask = 1L;
  		for (i = 0; i < MAX_OPEN; i++) {
! 			if (orfd & mask) {
  				f = p->handle[i];
  				if (f) {
  				    bytes = 1L;
***************
*** 1058,1064 ****
  				    }
  				}
  			}
! 			if (wfd & mask) {
  				f = p->handle[i];
  				if (f) {
  				    bytes = 1L;
--- 1090,1096 ----
  				    }
  				}
  			}
! 			if (owfd & mask) {
  				f = p->handle[i];
  				if (f) {
  				    bytes = 1L;
***************
*** 1071,1089 ****
  			}
  			mask = mask << 1L;
  		}
! 	}
  
  	/* at this point, we either have data or a time out */
  	/* cancel all the selects */
  	mask = 1L;
  
  	for (i = 0; i < MAX_OPEN; i++) {
! 		if (rfd & mask) {
  			f = p->handle[i];
  			if (f)
  				(*f->dev->unselect)(f, (long)p, O_RDONLY);
  		}
! 		if (wfd & mask) {
  			f = p->handle[i];
  			if (f)
  				(*f->dev->unselect)(f, (long)p, O_WRONLY);
--- 1103,1127 ----
  			}
  			mask = mask << 1L;
  		}
! 	} else if (t) {
  
+ 	/* in case data arrived after a collsion, there
+ 	 * could be a timeout pending even if count > 0
+ 	 */
+ 		canceltimeout(t);
+ 	}
+ 	
  	/* at this point, we either have data or a time out */
  	/* cancel all the selects */
  	mask = 1L;
  
  	for (i = 0; i < MAX_OPEN; i++) {
! 		if (orfd & mask) {
  			f = p->handle[i];
  			if (f)
  				(*f->dev->unselect)(f, (long)p, O_RDONLY);
  		}
! 		if (owfd & mask) {
  			f = p->handle[i];
  			if (f)
  				(*f->dev->unselect)(f, (long)p, O_WRONLY);
***************
*** 1091,1096 ****
--- 1129,1138 ----
  		mask = mask << 1L;
  	}
  
+ 	/* wake other processes which got a collision */
+ 	if (orfd || owfd)
+ 		wake(SELECT_Q, (long)&select_coll);
+ 
  	TRACE(("Fselect: returning %d", count));
  	return count;
  }
*** ../new/pipefs.c	Fri Oct 22 20:58:28 1993
--- pipefs.c	Mon Sep 13 21:44:34 1993
***************
*** 1010,1018 ****
  			return 1;
  		}
  
! /* BUG: multiple selects fail, only the first one works */
! 		if (!p->rsel)
! 			p->rsel = proc;
  		return 0;
  	} else if (mode == O_WRONLY) {
  		p = (f->flags & O_HEAD) ? this->inp : this->outp;
--- 1010,1018 ----
  			return 1;
  		}
  
! 		if (p->rsel)
! 			return 2; /* collision */
! 		p->rsel = proc;
  		return 0;
  	} else if (mode == O_WRONLY) {
  		p = (f->flags & O_HEAD) ? this->inp : this->outp;
***************
*** 1024,1031 ****
  		if (j >= PIPESIZ) j = 0;
  		if (j != p->head || p->readers <= 0)
  			return 1;	/* data may be written */
! 		if (!p->wsel)
! 			p->wsel = proc;
  		return 0;
  	}
  	return 0;
--- 1024,1032 ----
  		if (j >= PIPESIZ) j = 0;
  		if (j != p->head || p->readers <= 0)
  			return 1;	/* data may be written */
! 		if (p->wsel)
! 			return 2; /* collsion */
! 		p->wsel = proc;
  		return 0;
  	}
  	return 0;
*** ../new/proc.c	Fri Oct 22 20:59:28 1993
--- proc.c	Fri Oct 22 19:58:24 1993
***************
*** 612,620 ****
  {
  	PROC *p = (PROC *)param;
  	short s;
! 
  	s = spl7();	/* block interrupts */
! 	if(p->wait_cond == (long)wakeselect) {
  		p->wait_cond = 0;
  	}
  	if (p->wait_q == SELECT_Q) {
--- 612,622 ----
  {
  	PROC *p = (PROC *)param;
  	short s;
! 	extern short select_coll; /* in dosfile.c */
! 	
  	s = spl7();	/* block interrupts */
! 	if(p->wait_cond == (long)wakeselect ||
! 	   p->wait_cond == (long)&select_coll) {
  		p->wait_cond = 0;
  	}
  	if (p->wait_q == SELECT_Q) {
*** ../new/signal.c	Fri Oct 22 20:59:36 1993
--- signal.c	Fri Oct 22 20:58:10 1993
***************
*** 85,93 ****
  
  /* otherwise, make sure the process is awake */
  	if (p->wait_q && p->wait_q != READY_Q) {
! 		short sr = spl7();
! 		if (p->wait_q == SELECT_Q)
! 			p->wait_cond = 0;
  		rm_q(p->wait_q, p);
  		add_q(READY_Q, p);
  		spl(sr);
--- 85,91 ----
  
  /* otherwise, make sure the process is awake */
  	if (p->wait_q && p->wait_q != READY_Q) {
! 		sr = spl7();
  		rm_q(p->wait_q, p);
  		add_q(READY_Q, p);
  		spl(sr);