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(¤t->sigmask_lock); - sig = dequeue_signal(&these, &info); - current->blocked = oldblocked; - recalc_sigpending(current); - } - spin_unlock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sigmask_lock); + sig = dequeue_signal(&these, &info); + current->blocked = oldblocked; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } + } else + spin_unlock_irq(¤t->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(¤t->sigmask_lock); } + } else spin_unlock_irq(¤t->sigmask_lock); if (sig) {