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

Re: Talarm() problem



Here is a solution to the timeout problem. The strategy is as follows:

- when a timeout expires instead of disposing it, put it on a special
list of expired timeouts
- in add[root]timeout first check this list if there is a timeout that
has the same process and function attached and reuse it
- cancel[root]timeout looks at this list, too, as well as
cancelalltimeouts

I think this is the only way to reliably prevent cancel[root]timeout
from cancelling the wrong timeout. Since timeouts are normally used
for periodically calling a certain function, add[root]timeout will
always reuse the same timout structure and thus remove it from the
list of expired timeouts. I have verified this by adding a function to
print out this list, and everytime i checked it was empty.

Btw, what's the purpose of the wierd cast in timout()? There is no
place where the exact value of kintr matters, just if it is zero or
not. I have changed it to a simple assignment.


--- orig/timeout.c	Mon Aug  8 07:23:38 1994
+++ timeout.c	Sat Aug 13 20:53:14 1994
@@ -32,6 +32,7 @@
  */
 static TIMEOUT timeouts[TIMEOUTS] = { { 0, }, };
 TIMEOUT *tlist = NULL;
+TIMEOUT *expire_list = NULL;
 
 
 static TIMEOUT *
@@ -116,8 +117,20 @@
 	void (*func) P_((PROC *));
 {
 	TIMEOUT *t;
+	TIMEOUT **prev;
 
-	t = newtimeout(0);
+	/* Try to reuse an already expired timeout that had the
+	   same function attached */
+	prev = &expire_list;
+	for (t = *prev; t != NULL; prev = &t->next, t = *prev)
+	  if (t->proc == curproc && t->func == func)
+	    {
+	      *prev = t->next;
+	      break;
+	    }
+
+	if (t == NULL)
+	  t = newtimeout(0);
 
 /* BUG: we should have some fallback mechanism for timeouts when the
    kernel memory is exhausted
@@ -156,8 +169,23 @@
 	short flags;
 {
 	TIMEOUT *t;
+	TIMEOUT **prev;
+
+	/* Try to reuse an already expired timeout that had the
+	   same function attached */
+	prev = &expire_list;
+	for (t = *prev; t != NULL; t = *prev)
+	  {
+	    if (t->proc == rootproc && t->func == func)
+	      {
+		*prev = t->next;
+		break;
+	      }
+	    prev = &t->next;
+	  }
 
-	t = newtimeout(flags & 1);
+	if (!t)
+	  t = newtimeout(flags & 1);
 	if (!t) return NULL;
 	t->proc = rootproc;
 	t->func = func;
@@ -197,6 +225,19 @@
 			cur = cur->next;
 		}
 	}
+	prev = &expire_list;
+	for (cur = *prev; cur; cur = *prev)
+	  {
+	    if (cur->proc == curproc)
+	      {
+		*prev = cur->next;
+		spl (sr);
+		disposetimeout (cur);
+		sr = spl7 ();
+	      }
+	    else
+	      prev = &cur->next;
+	  }
 	spl (sr);
 }
 
@@ -217,6 +258,20 @@
 	TIMEOUT *cur, **prev;
 	short sr = spl7();
 
+	/* First look at the list of expired timeouts */
+	prev = &expire_list;
+	for (cur = *prev; cur; cur = *prev)
+	  {
+	    if (cur == this && cur->proc == curproc)
+	      {
+		*prev = cur->next;
+		spl (sr);
+		disposetimeout (this);
+		return;
+	      }
+	    prev = &cur->next;
+	  }
+
 	prev = &tlist;
 	for (cur = tlist; cur; cur = cur->next) {
 		if (cur == this && cur->proc == curproc) {
@@ -239,6 +294,21 @@
 {
 	TIMEOUT *cur, **prev;
 	short sr = spl7();
+
+
+	/* First look at the list of expired timeouts */
+	prev = &expire_list;
+	for (cur = *prev; cur; cur = *prev)
+	  {
+	    if (cur == this && cur->proc == rootproc)
+	      {
+		*prev = cur->next;
+		spl (sr);
+		disposetimeout (this);
+		return;
+	      }
+	    prev = &cur->next;
+	  }
 	
 	prev = &tlist;
 	for (cur = tlist; cur; cur = cur->next) {
@@ -276,9 +346,8 @@
 timeout()
 {
 	int ms;		/* time between ticks */
-	char *kintrptr = (char *)&kintr;
 
-	*kintrptr = (keyrec->head != keyrec->tail) ? -1 : 0;
+	kintr = keyrec->head != keyrec->tail;
 
 	ms = *((short *)0x442L);
 	if (proc_clock > 0)
@@ -327,10 +396,11 @@
  * timeout function installes a new timeout. */
 		if (tlist)
 			tlist->when += delta;
+		old->next = expire_list;
+		expire_list = old;
 		spl(sr);
 /* ++kay: debug output at spl7 hangs the system, so moved it here */
 		TRACE(("doing timeout code for pid %d", p->pid));
-		disposetimeout(old);
 
 	/* call the timeout function */
 		(*evnt)(p);