On Mon, Jun 12, 2000 at 09:52:23AM +0100, David Woodhouse wrote:
> andrewm@uow.edu.au 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
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:25 EST