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) {