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

Reply via email to