sigtimedwait with a zero timeout

From: Henrik Nordstrom (hno@hem.passagen.se)
Date: Wed Sep 20 2000 - 17:07:15 EST


Hi.

While playing with signal queues it was discovered that sigtimedwait
with a zero timeout apparently does block somewhat even if it should
not.

Why:

It forces a schedule()

Also the actual delay seems to be at least 10msec more than requested,
but I guess that is an effect of the schedule()?

Attached is a small patch to optimize this case. (the .patchw version is
with -w to more clearly indicate the minimal changes made)

Some timings to prove the point: (Intel)

Linux-2.4.0-test7 without the patch:
timeout = 0 nsec: blocks for 10msec
timeout = 10 nsec: blocks for 20msec

Linux-2.4.0-test8 with the patch:
timeout = 0 nsec: does not block. ~0.1200 msec on my laptop.
timeout = 10 nsec: blocks for 20msec

Due to laziness I have not timed 2.4.0-test8 without the patch.

--
Henrik Nordstrom

--- linux-2.4.0-test7-reiserfs-3.6.14-raw-hno/kernel/signal.c.orig Sat Sep 16 11:47:04 2000 +++ linux-2.4.0-test7-reiserfs-3.6.14-raw-hno/kernel/signal.c Sat Sep 16 11:52:18 2000 @@ -848,15 +848,18 @@ timeout = (timespec_to_jiffies(&ts) + (ts.tv_sec || ts.tv_nsec)); - current->state = TASK_INTERRUPTIBLE; - timeout = schedule_timeout(timeout); + if (timeout) { + current->state = TASK_INTERRUPTIBLE; + timeout = schedule_timeout(timeout); - spin_lock_irq(&current->sigmask_lock); - sig = dequeue_signal(&these, &info); - current->blocked = oldblocked; - recalc_sigpending(current); - } - spin_unlock_irq(&current->sigmask_lock); + spin_lock_irq(&current->sigmask_lock); + sig = dequeue_signal(&these, &info); + current->blocked = oldblocked; + recalc_sigpending(current); + spin_unlock_irq(&current->sigmask_lock); + } + } else + spin_unlock_irq(&current->sigmask_lock); if (sig) { ret = sig;

--- linux-2.4.0-test7-reiserfs-3.6.14-raw-hno/kernel/signal.c.orig Sat Sep 16 11:47:04 2000 +++ linux-2.4.0-test7-reiserfs-3.6.14-raw-hno/kernel/signal.c Sat Sep 16 11:52:18 2000 @@ -848,6 +848,7 @@ timeout = (timespec_to_jiffies(&ts) + (ts.tv_sec || ts.tv_nsec)); + if (timeout) { current->state = TASK_INTERRUPTIBLE; timeout = schedule_timeout(timeout); @@ -855,7 +856,9 @@ sig = dequeue_signal(&these, &info); current->blocked = oldblocked; recalc_sigpending(current); + spin_unlock_irq(&current->sigmask_lock); } + } else spin_unlock_irq(&current->sigmask_lock); if (sig) {

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 23 2000 - 21:00:24 EST