Skip to content

Commit

Permalink
hrtimer: Move schedule_work call to helper thread
Browse files Browse the repository at this point in the history
When run ltp leapsec_timer test, the following call trace is caught:

BUG: sleeping function called from invalid context at kernel/rtmutex.c:659
in_atomic(): 1, irqs_disabled(): 1, pid: 0, name: swapper/1
Preemption disabled at:[<ffffffff810857f3>] cpu_startup_entry+0x133/0x310

CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.10.10-rt3 #2
Hardware name: Intel Corporation Calpella platform/MATXM-CORE-411-B, BIOS 4.6.3 08/18/2010
ffffffff81c2f800 ffff880076843e40 ffffffff8169918d ffff880076843e58
ffffffff8106db31 ffff88007684b4a0 ffff880076843e70 ffffffff8169d9c0
ffff88007684b4a0 ffff880076843eb0 ffffffff81059da1 0000001876851200
Call Trace:
<IRQ>  [<ffffffff8169918d>] dump_stack+0x19/0x1b
[<ffffffff8106db31>] __might_sleep+0xf1/0x170
[<ffffffff8169d9c0>] rt_spin_lock+0x20/0x50
[<ffffffff81059da1>] queue_work_on+0x61/0x100
[<ffffffff81065aa1>] clock_was_set_delayed+0x21/0x30
[<ffffffff810883be>] do_timer+0x40e/0x660
[<ffffffff8108f487>] tick_do_update_jiffies64+0xf7/0x140
[<ffffffff8108fe42>] tick_check_idle+0x92/0xc0
[<ffffffff81044327>] irq_enter+0x57/0x70
[<ffffffff816a040e>] smp_apic_timer_interrupt+0x3e/0x9b
[<ffffffff8169f80a>] apic_timer_interrupt+0x6a/0x70
<EOI>  [<ffffffff8155ea1c>] ? cpuidle_enter_state+0x4c/0xc0
[<ffffffff8155eb68>] cpuidle_idle_call+0xd8/0x2d0
[<ffffffff8100b59e>] arch_cpu_idle+0xe/0x30
[<ffffffff8108585e>] cpu_startup_entry+0x19e/0x310
[<ffffffff8168efa2>] start_secondary+0x1ad/0x1b0

The clock_was_set_delayed is called in hard IRQ handler (timer interrupt), which
calls schedule_work.

Under PREEMPT_RT_FULL, schedule_work calls spinlocks which could sleep, so it's
not safe to call schedule_work in interrupt context.

Reference upstream commit b68d61c705ef02384c0538b8d9374545097899ca
(rt,ntp: Move call to schedule_delayed_work() to helper thread)
from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git, which
makes a similar change.

Signed-off-by: Yang Shi <[email protected]>
[bigeasy: use swork_queue() instead a helper thread]
Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
  • Loading branch information
Yang Shi authored and jianlong.wang committed Oct 26, 2021
1 parent d19bedc commit 20fd42f
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions kernel/time/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,29 @@ static void hrtimer_switch_to_hres(void)
retrigger_next_event(NULL);
}

#ifdef CONFIG_PREEMPT_RT_FULL

static struct swork_event clock_set_delay_work;

static void run_clock_set_delay(struct swork_event *event)
{
clock_was_set();
}

void clock_was_set_delayed(void)
{
swork_queue(&clock_set_delay_work);
}

static __init int create_clock_set_delay_thread(void)
{
WARN_ON(swork_get());
INIT_SWORK(&clock_set_delay_work, run_clock_set_delay);
return 0;
}
early_initcall(create_clock_set_delay_thread);
#else /* PREEMPT_RT_FULL */

static void clock_was_set_work(struct work_struct *work)
{
clock_was_set();
Expand All @@ -763,6 +786,7 @@ void clock_was_set_delayed(void)
{
schedule_work(&hrtimer_work);
}
#endif

#else

Expand Down

0 comments on commit 20fd42f

Please sign in to comment.