On Mon, Jun 12, 2000 at 09:52:23AM +0100, David Woodhouse wrote:
> [EMAIL PROTECTED] said:
> > Unfortunately schedule_timeout() doesn't actually call del_timer_sync.
> >  
> 
> Er,... it did in -ac14. It looked 'obviously correct' to me. So I sent the
> patch to Alan with with a question mark indicating that I wanted him to
> comment rather than just apply it. In hindsight, perhaps I should have made
> that more explicit. 
> 
> Why _doesn't_ it work, though?

>From reading del_timer_sync, you're only allowed to use it if you use
timer_exit in your timer, like this:

--- linux/kernel/sched.c        Sun Jun 11 17:02:22 2000
+++ linux-prumpf/kernel/sched.c Sun Jun 11 18:43:20 2000
@@ -337,15 +337,23 @@
        spin_unlock_irqrestore(&runqueue_lock, flags);
 }
 
+struct foo_struct {
+       struct task_struct *process;
+       struct timer_list *timer;
+};
+
 static void process_timeout(unsigned long __data)
 {
-       struct task_struct * p = (struct task_struct *) __data;
+       struct foo_struct *p = (struct foo_struct *) __data;
+
+       wake_up_process(p->process);
 
-       wake_up_process(p);
+       timer_exit(p->timer);
 }
 
 signed long schedule_timeout(signed long timeout)
 {
+       struct foo_struct foo;
        struct timer_list timer;
        unsigned long expire;
 
@@ -383,8 +391,11 @@
 
        init_timer(&timer);
        timer.expires = expire;
-       timer.data = (unsigned long) current;
+       timer.data = (unsigned long) &foo;
        timer.function = process_timeout;
+
+       foo.process = current;
+       foo.timer = &timer;
 
        add_timer(&timer);
        schedule();

Of course, if you go through the complexity of doing this, you could just
use a finished flag in the struct and use del_timer by hand:

--- linux/kernel/sched.c        Sun Jun 11 17:02:22 2000
+++ linux-prumpf/kernel/sched.c Sun Jun 11 18:45:48 2000
@@ -337,15 +337,23 @@
        spin_unlock_irqrestore(&runqueue_lock, flags);
 }
 
+struct foo_struct {
+       struct task_struct *process;
+       int finished;
+};
+
 static void process_timeout(unsigned long __data)
 {
-       struct task_struct * p = (struct task_struct *) __data;
+       struct foo_struct *p = (struct foo_struct *) __data;
+
+       wake_up_process(p->process);
 
-       wake_up_process(p);
+       p->finished = 0;
 }
 
 signed long schedule_timeout(signed long timeout)
 {
+       struct foo_struct foo;
        struct timer_list timer;
        unsigned long expire;
 
@@ -383,12 +391,16 @@
 
        init_timer(&timer);
        timer.expires = expire;
-       timer.data = (unsigned long) current;
+       timer.data = (unsigned long) &foo;
        timer.function = process_timeout;
 
+       foo.process = current;
+       foo.finished = 0;
+
        add_timer(&timer);
        schedule();
-       del_timer_sync(&timer);
+       if(!del_timer(&timer))
+               while(!(foo.finished));
 
        timeout = expire - jiffies;
 
but that's basically unrolling del_timer_sync by hand.

        Philipp Rumpf
-
Linux SMP list: FIRST see FAQ at http://www.irisa.fr/prive/dmentre/smp-howto/
To Unsubscribe: send "unsubscribe linux-smp" to [EMAIL PROTECTED]

Reply via email to