|
@@ -1668,9 +1668,20 @@ void run_local_timers(void)
|
|
|
raise_softirq(TIMER_SOFTIRQ);
|
|
|
}
|
|
|
|
|
|
-static void process_timeout(unsigned long __data)
|
|
|
+/*
|
|
|
+ * Since schedule_timeout()'s timer is defined on the stack, it must store
|
|
|
+ * the target task on the stack as well.
|
|
|
+ */
|
|
|
+struct process_timer {
|
|
|
+ struct timer_list timer;
|
|
|
+ struct task_struct *task;
|
|
|
+};
|
|
|
+
|
|
|
+static void process_timeout(struct timer_list *t)
|
|
|
{
|
|
|
- wake_up_process((struct task_struct *)__data);
|
|
|
+ struct process_timer *timeout = from_timer(timeout, t, timer);
|
|
|
+
|
|
|
+ wake_up_process(timeout->task);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1704,7 +1715,7 @@ static void process_timeout(unsigned long __data)
|
|
|
*/
|
|
|
signed long __sched schedule_timeout(signed long timeout)
|
|
|
{
|
|
|
- struct timer_list timer;
|
|
|
+ struct process_timer timer;
|
|
|
unsigned long expire;
|
|
|
|
|
|
switch (timeout)
|
|
@@ -1738,13 +1749,14 @@ signed long __sched schedule_timeout(signed long timeout)
|
|
|
|
|
|
expire = timeout + jiffies;
|
|
|
|
|
|
- setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
|
|
|
- __mod_timer(&timer, expire, false);
|
|
|
+ timer.task = current;
|
|
|
+ timer_setup_on_stack(&timer.timer, process_timeout, 0);
|
|
|
+ __mod_timer(&timer.timer, expire, false);
|
|
|
schedule();
|
|
|
- del_singleshot_timer_sync(&timer);
|
|
|
+ del_singleshot_timer_sync(&timer.timer);
|
|
|
|
|
|
/* Remove the timer from the object tracker */
|
|
|
- destroy_timer_on_stack(&timer);
|
|
|
+ destroy_timer_on_stack(&timer.timer);
|
|
|
|
|
|
timeout = expire - jiffies;
|
|
|
|