diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h index fc53e0ad56d9..448bbef47456 100644 --- a/include/linux/bottom_half.h +++ b/include/linux/bottom_half.h @@ -35,8 +35,10 @@ static inline void local_bh_enable(void) #ifdef CONFIG_PREEMPT_RT extern bool local_bh_blocked(void); +extern void softirq_preempt(void); #else static inline bool local_bh_blocked(void) { return false; } +static inline void softirq_preempt(void) { } #endif #endif /* _LINUX_BH_H */ diff --git a/kernel/softirq.c b/kernel/softirq.c index c2474cc4fa51..cae0ae2e2b0b 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -247,6 +247,19 @@ out: } EXPORT_SYMBOL(__local_bh_enable_ip); +void softirq_preempt(void) +{ + if (WARN_ON_ONCE(!preemptible())) + return; + + if (WARN_ON_ONCE(__this_cpu_read(softirq_ctrl.cnt) != SOFTIRQ_OFFSET)) + return; + + __local_bh_enable(SOFTIRQ_OFFSET, true); + /* preemption point */ + __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); +} + /* * Invoked from ksoftirqd_run() outside of the interrupt disabled section * to acquire the per CPU local lock for reentrancy protection.