Skip to content

Commit 1566b30

Browse files
rostedtjnettlet
authored andcommitted
rt,ntp: Move call to schedule_delayed_work() to helper thread
The ntp code for notify_cmos_timer() is called from a hard interrupt context. schedule_delayed_work() under PREEMPT_RT_FULL calls spinlocks that have been converted to mutexes, thus calling schedule_delayed_work() from interrupt is not safe. Add a helper thread that does the call to schedule_delayed_work and wake up that thread instead of calling schedule_delayed_work() directly. This is only for CONFIG_PREEMPT_RT_FULL, otherwise the code still calls schedule_delayed_work() directly in irq context. Note: There's a few places in the kernel that do this. Perhaps the RT code should have a dedicated thread that does the checks. Just register a notifier on boot up for your check and wake up the thread when needed. This will be a todo. Signed-off-by: Steven Rostedt <[email protected]> [bigeasy: use swork_queue() instead a helper thread] Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
1 parent f75f4d6 commit 1566b30

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

kernel/time/ntp.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/module.h>
1818
#include <linux/rtc.h>
1919
#include <linux/math64.h>
20+
#include <linux/swork.h>
2021

2122
#include "ntp_internal.h"
2223
#include "timekeeping_internal.h"
@@ -568,10 +569,35 @@ static void sync_cmos_clock(struct work_struct *work)
568569
&sync_cmos_work, timespec64_to_jiffies(&next));
569570
}
570571

572+
#ifdef CONFIG_PREEMPT_RT_FULL
573+
574+
static void run_clock_set_delay(struct swork_event *event)
575+
{
576+
queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
577+
}
578+
579+
static struct swork_event ntp_cmos_swork;
580+
581+
void ntp_notify_cmos_timer(void)
582+
{
583+
swork_queue(&ntp_cmos_swork);
584+
}
585+
586+
static __init int create_cmos_delay_thread(void)
587+
{
588+
WARN_ON(swork_get());
589+
INIT_SWORK(&ntp_cmos_swork, run_clock_set_delay);
590+
return 0;
591+
}
592+
early_initcall(create_cmos_delay_thread);
593+
594+
#else
595+
571596
void ntp_notify_cmos_timer(void)
572597
{
573598
queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
574599
}
600+
#endif /* CONFIG_PREEMPT_RT_FULL */
575601

576602
#else
577603
void ntp_notify_cmos_timer(void) { }

0 commit comments

Comments
 (0)