summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt benh@kernel.crashing.org <benh@tika.localdomain>2006-11-28 12:14:03 +1100
committerBenjamin Herrenschmidt <benh@tika.localdomain>2006-11-28 12:14:03 +1100
commit56d2a170bcddf2906d7ce6b5ba27a14c44947013 (patch)
treed7c078d0ccc75a629f4fac7741e48bf6bd493a0b
parentd05c451f30a391b5fe582fa5a0d5e7a32673b57a (diff)
Fix timeout handling with more than one timeout
The code would do a delete/insert pass while walking the queue which had the effect of breaking the "order" linkage (insert re-initializes pretty much everything). I fixed that by adding a new _twin_queue_reorder() which is to be called on an element that is to be re-ordered and which works at any time, even during a queue walking and using it from the timeout code. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--twin_queue.c16
-rw-r--r--twin_timeout.c6
-rw-r--r--twinint.h5
3 files changed, 24 insertions, 3 deletions
diff --git a/twin_queue.c b/twin_queue.c
index 985d92a..171a6eb 100644
--- a/twin_queue.c
+++ b/twin_queue.c
@@ -53,6 +53,22 @@ _twin_queue_remove (twin_queue_t **head,
}
void
+_twin_queue_reorder (twin_queue_t **head,
+ twin_queue_proc_t proc,
+ twin_queue_t *elem)
+{
+ twin_queue_t **prev, *q;
+
+ _twin_queue_remove(head, elem);
+
+ for (prev = head; (q = *prev); prev = &q->next)
+ if ((*proc) (elem, q) == TWIN_AFTER)
+ break;
+ elem->next = *prev;
+ *prev = elem;
+}
+
+void
_twin_queue_delete (twin_queue_t **head,
twin_queue_t *old)
{
diff --git a/twin_timeout.c b/twin_timeout.c
index 6640eca..189b305 100644
--- a/twin_timeout.c
+++ b/twin_timeout.c
@@ -63,9 +63,9 @@ _twin_run_timeout (void)
delay = (*timeout->proc) (now, timeout->closure);
if (delay >= 0)
{
- _twin_queue_remove ((twin_queue_t **) &head,
- &timeout->queue);
- _twin_queue_timeout (timeout, twin_now () + delay);
+ timeout->time = twin_now() + delay;
+ _twin_queue_reorder ((twin_queue_t **) &head,
+ _twin_timeout_order, &timeout->queue);
}
else
_twin_queue_delete ((twin_queue_t **) &head,
diff --git a/twinint.h b/twinint.h
index 85d84de..3889253 100644
--- a/twinint.h
+++ b/twinint.h
@@ -416,6 +416,11 @@ _twin_queue_remove (twin_queue_t **head,
twin_queue_t *old);
void
+_twin_queue_reorder (twin_queue_t **head,
+ twin_queue_proc_t proc,
+ twin_queue_t *elem);
+
+void
_twin_queue_delete (twin_queue_t **head,
twin_queue_t *old);