[rt] remove unused patches
This commit is contained in:
parent
2abddc2aa9
commit
f1a1bb5986
|
@ -1,43 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 1 Mar 2013 11:17:42 +0100
|
||||
Subject: futex: Ensure lock/unlock symetry versus pi_lock and hash bucket lock
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
In exit_pi_state_list() we have the following locking construct:
|
||||
|
||||
spin_lock(&hb->lock);
|
||||
raw_spin_lock_irq(&curr->pi_lock);
|
||||
|
||||
...
|
||||
spin_unlock(&hb->lock);
|
||||
|
||||
In !RT this works, but on RT the migrate_enable() function which is
|
||||
called from spin_unlock() sees atomic context due to the held pi_lock
|
||||
and just decrements the migrate_disable_atomic counter of the
|
||||
task. Now the next call to migrate_disable() sees the counter being
|
||||
negative and issues a warning. That check should be in
|
||||
migrate_enable() already.
|
||||
|
||||
Fix this by dropping pi_lock before unlocking hb->lock and reaquire
|
||||
pi_lock after that again. This is safe as the loop code reevaluates
|
||||
head again under the pi_lock.
|
||||
|
||||
Reported-by: Yong Zhang <yong.zhang@windriver.com>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/futex.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/kernel/futex.c
|
||||
+++ b/kernel/futex.c
|
||||
@@ -866,7 +866,9 @@ void exit_pi_state_list(struct task_stru
|
||||
* task still owns the PI-state:
|
||||
*/
|
||||
if (head->next != next) {
|
||||
+ raw_spin_unlock_irq(&curr->pi_lock);
|
||||
spin_unlock(&hb->lock);
|
||||
+ raw_spin_lock_irq(&curr->pi_lock);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 6 Apr 2016 17:30:28 +0200
|
||||
Subject: [PATCH] ARM: imx: always use TWD on IMX6Q
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
There is no reason to limit the TWD to be used on SMP kernels only if the
|
||||
hardware has it available.
|
||||
On Wandboard i.MX6SOLO, running PREEMPT-RT and cyclictest I see as max
|
||||
immediately after start in idle:
|
||||
UP : ~90us
|
||||
SMP: ~50us
|
||||
UP + TWD: ~20us.
|
||||
Based on this numbers I prefer the TWD over the slightly slower MXC
|
||||
timer.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/mach-imx/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/mach-imx/Kconfig
|
||||
+++ b/arch/arm/mach-imx/Kconfig
|
||||
@@ -526,7 +526,7 @@ config SOC_IMX6Q
|
||||
bool "i.MX6 Quad/DualLite support"
|
||||
select ARM_ERRATA_764369 if SMP
|
||||
select HAVE_ARM_SCU if SMP
|
||||
- select HAVE_ARM_TWD if SMP
|
||||
+ select HAVE_ARM_TWD
|
||||
select PCI_DOMAINS if PCI
|
||||
select PINCTRL_IMX6Q
|
||||
select SOC_IMX6
|
|
@ -1,77 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 22 Jan 2016 21:33:39 +0100
|
||||
Subject: arm+arm64: lazy-preempt: add TIF_NEED_RESCHED_LAZY to _TIF_WORK_MASK
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
_TIF_WORK_MASK is used to check for TIF_NEED_RESCHED so we need to check
|
||||
for TIF_NEED_RESCHED_LAZY here, too.
|
||||
|
||||
Reported-by: Grygorii Strashko <grygorii.strashko@ti.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/include/asm/thread_info.h | 7 ++++---
|
||||
arch/arm/kernel/entry-common.S | 9 +++++++--
|
||||
arch/arm64/include/asm/thread_info.h | 3 ++-
|
||||
3 files changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/thread_info.h
|
||||
+++ b/arch/arm/include/asm/thread_info.h
|
||||
@@ -143,8 +143,8 @@ extern int vfp_restore_user_hwstate(stru
|
||||
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
|
||||
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||
-#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
|
||||
-#define TIF_NEED_RESCHED_LAZY 8
|
||||
+#define TIF_SECCOMP 8 /* seccomp syscall filtering active */
|
||||
+#define TIF_NEED_RESCHED_LAZY 7
|
||||
|
||||
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
||||
#define TIF_USING_IWMMXT 17
|
||||
@@ -170,7 +170,8 @@ extern int vfp_restore_user_hwstate(stru
|
||||
* Change these and you break ASM code in entry-common.S
|
||||
*/
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||
- _TIF_NOTIFY_RESUME | _TIF_UPROBE)
|
||||
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
||||
+ _TIF_NEED_RESCHED_LAZY)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_ARM_THREAD_INFO_H */
|
||||
--- a/arch/arm/kernel/entry-common.S
|
||||
+++ b/arch/arm/kernel/entry-common.S
|
||||
@@ -36,7 +36,9 @@
|
||||
UNWIND(.cantunwind )
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
|
||||
+ bne fast_work_pending
|
||||
+ tst r1, #_TIF_SECCOMP
|
||||
bne fast_work_pending
|
||||
|
||||
/* perform architecture specific actions before user return */
|
||||
@@ -62,8 +64,11 @@ ENDPROC(ret_fast_syscall)
|
||||
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
|
||||
+ bne do_slower_path
|
||||
+ tst r1, #_TIF_SECCOMP
|
||||
beq no_work_pending
|
||||
+do_slower_path:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(ret_fast_syscall)
|
||||
|
||||
--- a/arch/arm64/include/asm/thread_info.h
|
||||
+++ b/arch/arm64/include/asm/thread_info.h
|
||||
@@ -135,7 +135,8 @@ static inline struct thread_info *curren
|
||||
#define _TIF_32BIT (1 << TIF_32BIT)
|
||||
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||
- _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
|
||||
+ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
|
||||
+ _TIF_NEED_RESCHED_LAZY)
|
||||
|
||||
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
|
||||
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
|
|
@ -1,32 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Tue, 24 May 2016 12:56:38 +0200
|
||||
Subject: [PATCH] arm: lazy preempt: correct resched condition
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
If we get out of preempt_schedule_irq() then we check for NEED_RESCHED
|
||||
and call the former function again if set because the preemption counter
|
||||
has be zero at this point.
|
||||
However the counter for lazy-preempt might not be zero therefore we have
|
||||
to check the counter before looking at the need_resched_lazy flag.
|
||||
|
||||
Cc: stable-rt@vger.kernel.org
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
arch/arm/kernel/entry-armv.S | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/kernel/entry-armv.S
|
||||
+++ b/arch/arm/kernel/entry-armv.S
|
||||
@@ -244,7 +244,11 @@ ENDPROC(__irq_svc)
|
||||
bne 1b
|
||||
tst r0, #_TIF_NEED_RESCHED_LAZY
|
||||
reteq r8 @ go again
|
||||
- b 1b
|
||||
+ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
|
||||
+ teq r0, #0 @ if preempt lazy count != 0
|
||||
+ beq 1b
|
||||
+ ret r8 @ go again
|
||||
+
|
||||
#endif
|
||||
|
||||
__und_fault:
|
|
@ -1,23 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 11 May 2016 11:56:18 +0200
|
||||
Subject: crypto/ccp: remove rwlocks_types.h
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Users of rwlocks should include spinlock.h instead including this
|
||||
header file. The current users of rwlocks_types.h are internal.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/crypto/ccp/ccp-dev.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/crypto/ccp/ccp-dev.c
|
||||
+++ b/drivers/crypto/ccp/ccp-dev.c
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
-#include <linux/rwlock_types.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
|
@ -1,127 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sat, 20 Jun 2009 11:36:54 +0200
|
||||
Subject: drivers/net: fix livelock issues
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Preempt-RT runs into a live lock issue with the NETDEV_TX_LOCKED micro
|
||||
optimization. The reason is that the softirq thread is rescheduling
|
||||
itself on that return value. Depending on priorities it starts to
|
||||
monoplize the CPU and livelock on UP systems.
|
||||
|
||||
Remove it.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 6 +-----
|
||||
drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 3 +--
|
||||
drivers/net/ethernet/chelsio/cxgb/sge.c | 3 +--
|
||||
drivers/net/ethernet/neterion/s2io.c | 7 +------
|
||||
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 6 ++----
|
||||
drivers/net/ethernet/tehuti/tehuti.c | 9 ++-------
|
||||
drivers/net/rionet.c | 6 +-----
|
||||
7 files changed, 9 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||||
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||||
@@ -2217,11 +2217,7 @@ static netdev_tx_t atl1c_xmit_frame(stru
|
||||
}
|
||||
|
||||
tpd_req = atl1c_cal_tpd_req(skb);
|
||||
- if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
|
||||
- if (netif_msg_pktdata(adapter))
|
||||
- dev_info(&adapter->pdev->dev, "tx locked\n");
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&adapter->tx_lock, flags);
|
||||
|
||||
if (atl1c_tpd_avail(adapter, type) < tpd_req) {
|
||||
/* no enough descriptor, just stop queue */
|
||||
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
|
||||
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
|
||||
@@ -1880,8 +1880,7 @@ static netdev_tx_t atl1e_xmit_frame(stru
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
tpd_req = atl1e_cal_tdp_req(skb);
|
||||
- if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
+ spin_lock_irqsave(&adapter->tx_lock, flags);
|
||||
|
||||
if (atl1e_tpd_avail(adapter) < tpd_req) {
|
||||
/* no enough descriptor, just stop queue */
|
||||
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
|
||||
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
|
||||
@@ -1664,8 +1664,7 @@ static int t1_sge_tx(struct sk_buff *skb
|
||||
struct cmdQ *q = &sge->cmdQ[qid];
|
||||
unsigned int credits, pidx, genbit, count, use_sched_skb = 0;
|
||||
|
||||
- if (!spin_trylock(&q->lock))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
+ spin_lock(&q->lock);
|
||||
|
||||
reclaim_completed_tx(sge, q);
|
||||
|
||||
--- a/drivers/net/ethernet/neterion/s2io.c
|
||||
+++ b/drivers/net/ethernet/neterion/s2io.c
|
||||
@@ -4084,12 +4084,7 @@ static netdev_tx_t s2io_xmit(struct sk_b
|
||||
[skb->priority & (MAX_TX_FIFOS - 1)];
|
||||
fifo = &mac_control->fifos[queue];
|
||||
|
||||
- if (do_spin_lock)
|
||||
- spin_lock_irqsave(&fifo->tx_lock, flags);
|
||||
- else {
|
||||
- if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&fifo->tx_lock, flags);
|
||||
|
||||
if (sp->config.multiq) {
|
||||
if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
|
||||
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
||||
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
||||
@@ -2137,10 +2137,8 @@ static int pch_gbe_xmit_frame(struct sk_
|
||||
struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
|
||||
unsigned long flags;
|
||||
|
||||
- if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) {
|
||||
- /* Collision - tell upper layer to requeue */
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&tx_ring->tx_lock, flags);
|
||||
+
|
||||
if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) {
|
||||
netif_stop_queue(netdev);
|
||||
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
|
||||
--- a/drivers/net/ethernet/tehuti/tehuti.c
|
||||
+++ b/drivers/net/ethernet/tehuti/tehuti.c
|
||||
@@ -1629,13 +1629,8 @@ static netdev_tx_t bdx_tx_transmit(struc
|
||||
unsigned long flags;
|
||||
|
||||
ENTER;
|
||||
- local_irq_save(flags);
|
||||
- if (!spin_trylock(&priv->tx_lock)) {
|
||||
- local_irq_restore(flags);
|
||||
- DBG("%s[%s]: TX locked, returning NETDEV_TX_LOCKED\n",
|
||||
- BDX_DRV_NAME, ndev->name);
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+
|
||||
+ spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
|
||||
/* build tx descriptor */
|
||||
BDX_ASSERT(f->m.wptr >= f->m.memsz); /* started with valid wptr */
|
||||
--- a/drivers/net/rionet.c
|
||||
+++ b/drivers/net/rionet.c
|
||||
@@ -179,11 +179,7 @@ static int rionet_start_xmit(struct sk_b
|
||||
unsigned long flags;
|
||||
int add_num = 1;
|
||||
|
||||
- local_irq_save(flags);
|
||||
- if (!spin_trylock(&rnet->tx_lock)) {
|
||||
- local_irq_restore(flags);
|
||||
- return NETDEV_TX_LOCKED;
|
||||
- }
|
||||
+ spin_lock_irqsave(&rnet->tx_lock, flags);
|
||||
|
||||
if (is_multicast_ether_addr(eth->h_dest))
|
||||
add_num = nets[rnet->mport->id].nact;
|
|
@ -1,34 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 21 Mar 2013 11:35:49 +0100
|
||||
Subject: i2c/omap: drop the lock hard irq context
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
The lock is taken while reading two registers. On RT the first lock is
|
||||
taken in hard irq where it might sleep and in the threaded irq.
|
||||
The threaded irq runs in oneshot mode so the hard irq does not run until
|
||||
the thread the completes so there is no reason to grab the lock.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/i2c/busses/i2c-omap.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/i2c/busses/i2c-omap.c
|
||||
+++ b/drivers/i2c/busses/i2c-omap.c
|
||||
@@ -995,15 +995,12 @@ omap_i2c_isr(int irq, void *dev_id)
|
||||
u16 mask;
|
||||
u16 stat;
|
||||
|
||||
- spin_lock(&omap->lock);
|
||||
- mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
|
||||
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
|
||||
+ mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
|
||||
|
||||
if (stat & mask)
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
|
||||
- spin_unlock(&omap->lock);
|
||||
-
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Tue, 14 Jul 2015 14:26:34 +0200
|
||||
Subject: gpu/i915: don't open code these things
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
The opencode part is gone in 1f83fee0 ("drm/i915: clear up wedged transitions")
|
||||
the owner check is still there.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_gem_shrinker.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
|
||||
@@ -39,7 +39,7 @@ static bool mutex_is_locked_by(struct mu
|
||||
if (!mutex_is_locked(mutex))
|
||||
return false;
|
||||
|
||||
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
|
||||
+#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)) && !defined(CONFIG_PREEMPT_RT_BASE)
|
||||
return mutex->owner == task;
|
||||
#else
|
||||
/* Since UP may be pre-empted, we cannot assume that we own the lock */
|
|
@ -1,26 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 11 May 2016 11:52:23 +0200
|
||||
Subject: infiniband/ulp/ipoib: remove pkey_mutex
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
The last user of pkey_mutex was removed in db84f8803759 ("IB/ipoib: Use
|
||||
P_Key change event instead of P_Key polling mechanism") but the lock
|
||||
remained.
|
||||
This patch removes it.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
drivers/infiniband/ulp/ipoib/ipoib_ib.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
|
||||
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
|
||||
@@ -51,8 +51,6 @@ MODULE_PARM_DESC(data_debug_level,
|
||||
"Enable data path debug tracing if > 0");
|
||||
#endif
|
||||
|
||||
-static DEFINE_MUTEX(pkey_mutex);
|
||||
-
|
||||
struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
|
||||
struct ib_pd *pd, struct ib_ah_attr *attr)
|
||||
{
|
|
@ -1,27 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Thu, 19 May 2016 17:12:34 +0200
|
||||
Subject: [PATCH] kernel/rtmutex: only warn once on a try lock from bad
|
||||
context
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
One warning should be enough to get one motivated to fix this. It is
|
||||
possible that this happens more than once and so starts flooding the
|
||||
output. Later the prints will be suppressed so we only get half of it.
|
||||
Depending on the console system used it might not be helpfull.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/locking/rtmutex.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/locking/rtmutex.c
|
||||
+++ b/kernel/locking/rtmutex.c
|
||||
@@ -1479,7 +1479,7 @@ EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
|
||||
int __sched rt_mutex_trylock(struct rt_mutex *lock)
|
||||
{
|
||||
#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
- if (WARN_ON(in_irq() || in_nmi()))
|
||||
+ if (WARN_ON_ONCE(in_irq() || in_nmi()))
|
||||
#else
|
||||
if (WARN_ON(in_irq() || in_nmi() || in_serving_softirq()))
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
Subject: locking/lglocks: Use preempt_enable/disable_nort() in lg_double_[un]lock
|
||||
From: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Date: Sat, 27 Feb 2016 08:34:43 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Let's not do that when snagging an rtmutex.
|
||||
|
||||
Signed-off-by: Mike Galbraith <umgwanakilbuti@gmail.com>
|
||||
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Cc: linux-rt-users <linux-rt-users@vger.kernel.org>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/locking/lglock.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/kernel/locking/lglock.c
|
||||
+++ b/kernel/locking/lglock.c
|
||||
@@ -86,7 +86,7 @@ void lg_double_lock(struct lglock *lg, i
|
||||
if (cpu2 < cpu1)
|
||||
swap(cpu1, cpu2);
|
||||
|
||||
- preempt_disable();
|
||||
+ preempt_disable_nort();
|
||||
lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
|
||||
lg_do_lock(per_cpu_ptr(lg->lock, cpu1));
|
||||
lg_do_lock(per_cpu_ptr(lg->lock, cpu2));
|
||||
@@ -97,7 +97,7 @@ void lg_double_unlock(struct lglock *lg,
|
||||
lock_release(&lg->lock_dep_map, 1, _RET_IP_);
|
||||
lg_do_unlock(per_cpu_ptr(lg->lock, cpu1));
|
||||
lg_do_unlock(per_cpu_ptr(lg->lock, cpu2));
|
||||
- preempt_enable();
|
||||
+ preempt_enable_nort();
|
||||
}
|
||||
|
||||
void lg_global_lock(struct lglock *lg)
|
|
@ -1,41 +0,0 @@
|
|||
Subject: mm: rt: Fix generic kmap_atomic for RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sat, 19 Sep 2015 10:15:00 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
The update to 4.1 brought in the mainline variant of the pagefault
|
||||
disable distangling from preempt count. That introduced a
|
||||
preempt_disable/enable pair in the generic kmap_atomic/kunmap_atomic
|
||||
implementations which got not converted to the _nort() variant.
|
||||
|
||||
That results in massive 'scheduling while atomic/sleeping function
|
||||
called from invalid context' splats.
|
||||
|
||||
Fix that up.
|
||||
|
||||
Reported-and-tested-by: Juergen Borleis <jbe@pengutronix.de>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
include/linux/highmem.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/highmem.h
|
||||
+++ b/include/linux/highmem.h
|
||||
@@ -65,7 +65,7 @@ static inline void kunmap(struct page *p
|
||||
|
||||
static inline void *kmap_atomic(struct page *page)
|
||||
{
|
||||
- preempt_disable();
|
||||
+ preempt_disable_nort();
|
||||
pagefault_disable();
|
||||
return page_address(page);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ static inline void *kmap_atomic(struct p
|
||||
static inline void __kunmap_atomic(void *addr)
|
||||
{
|
||||
pagefault_enable();
|
||||
- preempt_enable();
|
||||
+ preempt_enable_nort();
|
||||
}
|
||||
|
||||
#define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn))
|
|
@ -1,165 +0,0 @@
|
|||
From: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Date: Tue, 22 Mar 2016 11:16:09 +0100
|
||||
Subject: [PATCH] mm/zsmalloc: Use get/put_cpu_light in
|
||||
zs_map_object()/zs_unmap_object()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.8/older/patches-4.8.2-rt2.tar.xz
|
||||
|
||||
Otherwise, we get a ___might_sleep() splat.
|
||||
|
||||
|
||||
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
[bigeasy: replace the bitspin_lock() with a mutex]
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
mm/zsmalloc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 69 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/mm/zsmalloc.c
|
||||
+++ b/mm/zsmalloc.c
|
||||
@@ -71,7 +71,19 @@
|
||||
#define ZS_MAX_ZSPAGE_ORDER 2
|
||||
#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+
|
||||
+struct zsmalloc_handle {
|
||||
+ unsigned long addr;
|
||||
+ struct mutex lock;
|
||||
+};
|
||||
+
|
||||
+#define ZS_HANDLE_SIZE (sizeof(struct zsmalloc_handle))
|
||||
+
|
||||
+#else
|
||||
+
|
||||
#define ZS_HANDLE_SIZE (sizeof(unsigned long))
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Object location (<PFN>, <obj_idx>) is encoded as
|
||||
@@ -351,9 +363,26 @@ static void destroy_cache(struct zs_pool
|
||||
|
||||
static unsigned long cache_alloc_handle(struct zs_pool *pool, gfp_t gfp)
|
||||
{
|
||||
- return (unsigned long)kmem_cache_alloc(pool->handle_cachep,
|
||||
- gfp & ~(__GFP_HIGHMEM|__GFP_MOVABLE));
|
||||
+ void *p;
|
||||
+
|
||||
+ p = kmem_cache_alloc(pool->handle_cachep,
|
||||
+ gfp & ~(__GFP_HIGHMEM|__GFP_MOVABLE));
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ if (p) {
|
||||
+ struct zsmalloc_handle *zh = p;
|
||||
+
|
||||
+ mutex_init(&zh->lock);
|
||||
+ }
|
||||
+#endif
|
||||
+ return (unsigned long)p;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+static struct zsmalloc_handle *zs_get_pure_handle(unsigned long handle)
|
||||
+{
|
||||
+ return (void *)(handle &~((1 << OBJ_TAG_BITS) - 1));
|
||||
}
|
||||
+#endif
|
||||
|
||||
static void cache_free_handle(struct zs_pool *pool, unsigned long handle)
|
||||
{
|
||||
@@ -373,12 +402,18 @@ static void cache_free_zspage(struct zs_
|
||||
|
||||
static void record_obj(unsigned long handle, unsigned long obj)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ WRITE_ONCE(zh->addr, obj);
|
||||
+#else
|
||||
/*
|
||||
* lsb of @obj represents handle lock while other bits
|
||||
* represent object value the handle is pointing so
|
||||
* updating shouldn't do store tearing.
|
||||
*/
|
||||
WRITE_ONCE(*(unsigned long *)handle, obj);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* zpool driver */
|
||||
@@ -902,7 +937,13 @@ static unsigned long location_to_obj(str
|
||||
|
||||
static unsigned long handle_to_obj(unsigned long handle)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ return zh->addr;
|
||||
+#else
|
||||
return *(unsigned long *)handle;
|
||||
+#endif
|
||||
}
|
||||
|
||||
static unsigned long obj_to_head(struct page *page, void *obj)
|
||||
@@ -916,22 +957,46 @@ static unsigned long obj_to_head(struct
|
||||
|
||||
static inline int testpin_tag(unsigned long handle)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ return mutex_is_locked(&zh->lock);
|
||||
+#else
|
||||
return bit_spin_is_locked(HANDLE_PIN_BIT, (unsigned long *)handle);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline int trypin_tag(unsigned long handle)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ return mutex_trylock(&zh->lock);
|
||||
+#else
|
||||
return bit_spin_trylock(HANDLE_PIN_BIT, (unsigned long *)handle);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void pin_tag(unsigned long handle)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ return mutex_lock(&zh->lock);
|
||||
+#else
|
||||
bit_spin_lock(HANDLE_PIN_BIT, (unsigned long *)handle);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void unpin_tag(unsigned long handle)
|
||||
{
|
||||
+#ifdef CONFIG_PREEMPT_RT_BASE
|
||||
+ struct zsmalloc_handle *zh = zs_get_pure_handle(handle);
|
||||
+
|
||||
+ return mutex_unlock(&zh->lock);
|
||||
+#else
|
||||
bit_spin_unlock(HANDLE_PIN_BIT, (unsigned long *)handle);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void reset_page(struct page *page)
|
||||
@@ -1423,7 +1488,7 @@ void *zs_map_object(struct zs_pool *pool
|
||||
class = pool->size_class[class_idx];
|
||||
off = (class->size * obj_idx) & ~PAGE_MASK;
|
||||
|
||||
- area = &get_cpu_var(zs_map_area);
|
||||
+ area = per_cpu_ptr(&zs_map_area, get_cpu_light());
|
||||
area->vm_mm = mm;
|
||||
if (off + class->size <= PAGE_SIZE) {
|
||||
/* this object is contained entirely within a page */
|
||||
@@ -1477,7 +1542,7 @@ void zs_unmap_object(struct zs_pool *poo
|
||||
|
||||
__zs_unmap_object(area, pages, off, class->size);
|
||||
}
|
||||
- put_cpu_var(zs_map_area);
|
||||
+ put_cpu_light();
|
||||
|
||||
migrate_read_unlock(zspage);
|
||||
unpin_tag(handle);
|
|
@ -1,93 +0,0 @@
|
|||
Subject: net: Avoid livelock in net_tx_action() on RT
|
||||
From: Steven Rostedt <srostedt@redhat.com>
|
||||
Date: Thu, 06 Oct 2011 10:48:39 -0400
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
qdisc_lock is taken w/o disabling interrupts or bottom halfs. So code
|
||||
holding a qdisc_lock() can be interrupted and softirqs can run on the
|
||||
return of interrupt in !RT.
|
||||
|
||||
The spin_trylock() in net_tx_action() makes sure, that the softirq
|
||||
does not deadlock. When the lock can't be acquired q is requeued and
|
||||
the NET_TX softirq is raised. That causes the softirq to run over and
|
||||
over.
|
||||
|
||||
That works in mainline as do_softirq() has a retry loop limit and
|
||||
leaves the softirq processing in the interrupt return path and
|
||||
schedules ksoftirqd. The task which holds qdisc_lock cannot be
|
||||
preempted, so the lock is released and either ksoftirqd or the next
|
||||
softirq in the return from interrupt path can proceed. Though it's a
|
||||
bit strange to actually run MAX_SOFTIRQ_RESTART (10) loops before it
|
||||
decides to bail out even if it's clear in the first iteration :)
|
||||
|
||||
On RT all softirq processing is done in a FIFO thread and we don't
|
||||
have a loop limit, so ksoftirqd preempts the lock holder forever and
|
||||
unqueues and requeues until the reset button is hit.
|
||||
|
||||
Due to the forced threading of ksoftirqd on RT we actually cannot
|
||||
deadlock on qdisc_lock because it's a "sleeping lock". So it's safe to
|
||||
replace the spin_trylock() with a spin_lock(). When contended,
|
||||
ksoftirqd is scheduled out and the lock holder can proceed.
|
||||
|
||||
[ tglx: Massaged changelog and code comments ]
|
||||
|
||||
Solved-by: Thomas Gleixner <tglx@linuxtronix.de>
|
||||
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Tested-by: Carsten Emde <cbe@osadl.org>
|
||||
Cc: Clark Williams <williams@redhat.com>
|
||||
Cc: John Kacur <jkacur@redhat.com>
|
||||
Cc: Luis Claudio R. Goncalves <lclaudio@redhat.com>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
---
|
||||
net/core/dev.c | 32 +++++++++++++++++++++++++++++++-
|
||||
1 file changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -3848,6 +3848,36 @@ int netif_rx_ni(struct sk_buff *skb)
|
||||
}
|
||||
EXPORT_SYMBOL(netif_rx_ni);
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+/*
|
||||
+ * RT runs ksoftirqd as a real time thread and the root_lock is a
|
||||
+ * "sleeping spinlock". If the trylock fails then we can go into an
|
||||
+ * infinite loop when ksoftirqd preempted the task which actually
|
||||
+ * holds the lock, because we requeue q and raise NET_TX softirq
|
||||
+ * causing ksoftirqd to loop forever.
|
||||
+ *
|
||||
+ * It's safe to use spin_lock on RT here as softirqs run in thread
|
||||
+ * context and cannot deadlock against the thread which is holding
|
||||
+ * root_lock.
|
||||
+ *
|
||||
+ * On !RT the trylock might fail, but there we bail out from the
|
||||
+ * softirq loop after 10 attempts which we can't do on RT. And the
|
||||
+ * task holding root_lock cannot be preempted, so the only downside of
|
||||
+ * that trylock is that we need 10 loops to decide that we should have
|
||||
+ * given up in the first one :)
|
||||
+ */
|
||||
+static inline int take_root_lock(spinlock_t *lock)
|
||||
+{
|
||||
+ spin_lock(lock);
|
||||
+ return 1;
|
||||
+}
|
||||
+#else
|
||||
+static inline int take_root_lock(spinlock_t *lock)
|
||||
+{
|
||||
+ return spin_trylock(lock);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void net_tx_action(struct softirq_action *h)
|
||||
{
|
||||
struct softnet_data *sd = this_cpu_ptr(&softnet_data);
|
||||
@@ -3895,7 +3925,7 @@ static void net_tx_action(struct softirq
|
||||
head = head->next_sched;
|
||||
|
||||
root_lock = qdisc_lock(q);
|
||||
- if (spin_trylock(root_lock)) {
|
||||
+ if (take_root_lock(root_lock)) {
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(__QDISC_STATE_SCHED,
|
||||
&q->state);
|
|
@ -1,36 +0,0 @@
|
|||
Date: Tue, 27 Oct 2015 07:31:53 -0500
|
||||
From: Josh Cartwright <joshc@ni.com>
|
||||
Subject: net: Make synchronize_rcu_expedited() conditional on !RT_FULL
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
While the use of synchronize_rcu_expedited() might make
|
||||
synchronize_net() "faster", it does so at significant cost on RT
|
||||
systems, as expediting a grace period forcibly preempts any
|
||||
high-priority RT tasks (via the stop_machine() mechanism).
|
||||
|
||||
Without this change, we can observe a latency spike up to 30us with
|
||||
cyclictest by rapidly unplugging/reestablishing an ethernet link.
|
||||
|
||||
Suggested-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
|
||||
Signed-off-by: Josh Cartwright <joshc@ni.com>
|
||||
Cc: bigeasy@linutronix.de
|
||||
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Acked-by: David S. Miller <davem@davemloft.net>
|
||||
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
|
||||
Link: http://lkml.kernel.org/r/20151027123153.GG8245@jcartwri.amer.corp.natinst.com
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
net/core/dev.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -7217,7 +7217,7 @@ EXPORT_SYMBOL(free_netdev);
|
||||
void synchronize_net(void)
|
||||
{
|
||||
might_sleep();
|
||||
- if (rtnl_is_locked())
|
||||
+ if (rtnl_is_locked() && !IS_ENABLED(CONFIG_PREEMPT_RT_FULL))
|
||||
synchronize_rcu_expedited();
|
||||
else
|
||||
synchronize_rcu();
|
|
@ -1,74 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 20 Jan 2016 15:13:30 +0100
|
||||
Subject: preempt-lazy: Add the lazy-preemption check to preempt_schedule()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Probably in the rebase onto v4.1 this check got moved into less commonly used
|
||||
preempt_schedule_notrace(). This patch ensures that both functions use it.
|
||||
|
||||
Reported-by: Mike Galbraith <umgwanakikbuti@gmail.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/sched/core.c | 36 ++++++++++++++++++++++++++++--------
|
||||
1 file changed, 28 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -3500,6 +3500,30 @@ static void __sched notrace preempt_sche
|
||||
} while (need_resched());
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_LAZY
|
||||
+/*
|
||||
+ * If TIF_NEED_RESCHED is then we allow to be scheduled away since this is
|
||||
+ * set by a RT task. Oterwise we try to avoid beeing scheduled out as long as
|
||||
+ * preempt_lazy_count counter >0.
|
||||
+ */
|
||||
+static __always_inline int preemptible_lazy(void)
|
||||
+{
|
||||
+ if (test_thread_flag(TIF_NEED_RESCHED))
|
||||
+ return 1;
|
||||
+ if (current_thread_info()->preempt_lazy_count)
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+static int preemptible_lazy(void)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_PREEMPT
|
||||
/*
|
||||
* this is the entry point to schedule() from in-kernel preemption
|
||||
@@ -3514,6 +3538,8 @@ asmlinkage __visible void __sched notrac
|
||||
*/
|
||||
if (likely(!preemptible()))
|
||||
return;
|
||||
+ if (!preemptible_lazy())
|
||||
+ return;
|
||||
|
||||
preempt_schedule_common();
|
||||
}
|
||||
@@ -3540,15 +3566,9 @@ asmlinkage __visible void __sched notrac
|
||||
|
||||
if (likely(!preemptible()))
|
||||
return;
|
||||
-
|
||||
-#ifdef CONFIG_PREEMPT_LAZY
|
||||
- /*
|
||||
- * Check for lazy preemption
|
||||
- */
|
||||
- if (current_thread_info()->preempt_lazy_count &&
|
||||
- !test_thread_flag(TIF_NEED_RESCHED))
|
||||
+ if (!preemptible_lazy())
|
||||
return;
|
||||
-#endif
|
||||
+
|
||||
do {
|
||||
preempt_disable_notrace();
|
||||
/*
|
|
@ -1,64 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 10 Feb 2016 18:30:56 +0100
|
||||
Subject: rcu: disable more spots of rcu_bh
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
We don't use ru_bh on -RT but we still fork a thread for it and keep it
|
||||
as a flavour. No more.
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/rcu/tree.c | 6 ++++++
|
||||
kernel/rcu/tree.h | 2 ++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/kernel/rcu/tree.c
|
||||
+++ b/kernel/rcu/tree.c
|
||||
@@ -440,11 +440,13 @@ EXPORT_SYMBOL_GPL(rcu_batches_started_sc
|
||||
/*
|
||||
* Return the number of RCU BH batches started thus far for debug & stats.
|
||||
*/
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
unsigned long rcu_batches_started_bh(void)
|
||||
{
|
||||
return rcu_bh_state.gpnum;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_batches_started_bh);
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Return the number of RCU batches completed thus far for debug & stats.
|
||||
@@ -549,9 +551,11 @@ void rcutorture_get_gp_data(enum rcutort
|
||||
case RCU_FLAVOR:
|
||||
rsp = rcu_state_p;
|
||||
break;
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
case RCU_BH_FLAVOR:
|
||||
rsp = &rcu_bh_state;
|
||||
break;
|
||||
+#endif
|
||||
case RCU_SCHED_FLAVOR:
|
||||
rsp = &rcu_sched_state;
|
||||
break;
|
||||
@@ -4637,7 +4641,9 @@ void __init rcu_init(void)
|
||||
|
||||
rcu_bootup_announce();
|
||||
rcu_init_geometry();
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
rcu_init_one(&rcu_bh_state);
|
||||
+#endif
|
||||
rcu_init_one(&rcu_sched_state);
|
||||
if (dump_tree)
|
||||
rcu_dump_rcu_node_tree(&rcu_sched_state);
|
||||
--- a/kernel/rcu/tree.h
|
||||
+++ b/kernel/rcu/tree.h
|
||||
@@ -572,7 +572,9 @@ extern struct list_head rcu_struct_flavo
|
||||
*/
|
||||
extern struct rcu_state rcu_sched_state;
|
||||
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
extern struct rcu_state rcu_bh_state;
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_PREEMPT_RCU
|
||||
extern struct rcu_state rcu_preempt_state;
|
|
@ -1,37 +0,0 @@
|
|||
From: Clark Williams <williams@redhat.com>
|
||||
Date: Fri, 26 Feb 2016 13:19:20 -0600
|
||||
Subject: rcu/torture: Comment out rcu_bh ops on PREEMPT_RT_FULL
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
RT has dropped support of rcu_bh, comment out in rcutorture.
|
||||
|
||||
Signed-off-by: Clark Williams <williams@redhat.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/rcu/rcutorture.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/kernel/rcu/rcutorture.c
|
||||
+++ b/kernel/rcu/rcutorture.c
|
||||
@@ -409,6 +409,7 @@ static struct rcu_torture_ops rcu_ops =
|
||||
.name = "rcu"
|
||||
};
|
||||
|
||||
+#ifndef CONFIG_PREEMPT_RT_FULL
|
||||
/*
|
||||
* Definitions for rcu_bh torture testing.
|
||||
*/
|
||||
@@ -448,6 +449,12 @@ static struct rcu_torture_ops rcu_bh_ops
|
||||
.name = "rcu_bh"
|
||||
};
|
||||
|
||||
+#else
|
||||
+static struct rcu_torture_ops rcu_bh_ops = {
|
||||
+ .ttype = INVALID_RCU_FLAVOR,
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Don't even think about trying any of these in real life!!!
|
||||
* The names includes "busted", and they really means it!
|
|
@ -1,33 +0,0 @@
|
|||
Subject: rtmutex: Handle non enqueued waiters gracefully
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Fri, 06 Nov 2015 18:51:03 +0100
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4.1-rt5.tar.xz
|
||||
|
||||
Yimin debugged that in case of a PI wakeup in progress when
|
||||
rt_mutex_start_proxy_lock() calls task_blocks_on_rt_mutex() the latter
|
||||
returns -EAGAIN and in consequence the remove_waiter() call runs into
|
||||
a BUG_ON() because there is nothing to remove.
|
||||
|
||||
Guard it with rt_mutex_has_waiters(). This is a quick fix which is
|
||||
easy to backport. The proper fix is to have a central check in
|
||||
remove_waiter() so we can call it unconditionally.
|
||||
|
||||
Reported-and-debugged-by: Yimin Deng <yimin11.deng@gmail.com>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable-rt@vger.kernel.org
|
||||
|
||||
---
|
||||
kernel/locking/rtmutex.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/locking/rtmutex.c
|
||||
+++ b/kernel/locking/rtmutex.c
|
||||
@@ -1617,7 +1617,7 @@ int rt_mutex_start_proxy_lock(struct rt_
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
- if (unlikely(ret))
|
||||
+ if (ret && rt_mutex_has_waiters(lock))
|
||||
remove_waiter(lock, waiter);
|
||||
|
||||
raw_spin_unlock(&lock->wait_lock);
|
|
@ -1,28 +0,0 @@
|
|||
From: "bmouring@ni.com" <bmouring@ni.com>
|
||||
Date: Tue, 15 Dec 2015 17:07:30 -0600
|
||||
Subject: rtmutex: Use chainwalking control enum
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
In 8930ed80 (rtmutex: Cleanup deadlock detector debug logic),
|
||||
chainwalking control enums were introduced to limit the deadlock
|
||||
detection logic. One of the calls to task_blocks_on_rt_mutex was
|
||||
missed when converting to use the enums.
|
||||
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Brad Mouring <brad.mouring@ni.com>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/locking/rtmutex.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/kernel/locking/rtmutex.c
|
||||
+++ b/kernel/locking/rtmutex.c
|
||||
@@ -1017,7 +1017,7 @@ static void noinline __sched rt_spin_lo
|
||||
__set_current_state_no_track(TASK_UNINTERRUPTIBLE);
|
||||
raw_spin_unlock(&self->pi_lock);
|
||||
|
||||
- ret = task_blocks_on_rt_mutex(lock, &waiter, self, 0);
|
||||
+ ret = task_blocks_on_rt_mutex(lock, &waiter, self, RT_MUTEX_MIN_CHAINWALK);
|
||||
BUG_ON(ret);
|
||||
|
||||
for (;;) {
|
|
@ -1,272 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Fri, 5 Feb 2016 18:26:11 +0100
|
||||
Subject: rtmutex: push down migrate_disable() into rt_spin_lock()
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
No point in having the migrate disable/enable invocations in all the
|
||||
macro/inlines. That's just more code for no win as we do a function
|
||||
call anyway. Move it to the core code and save quite some text size.
|
||||
|
||||
text data bss dec filename
|
||||
11034127 3676912 14901248 29612287 vmlinux.before
|
||||
10990437 3676848 14901248 29568533 vmlinux.after
|
||||
|
||||
~-40KiB
|
||||
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/linux/locallock.h | 6 +++---
|
||||
include/linux/spinlock_rt.h | 25 +++++++------------------
|
||||
kernel/cpu.c | 4 ++--
|
||||
kernel/locking/lglock.c | 2 +-
|
||||
kernel/locking/rt.c | 2 --
|
||||
kernel/locking/rtmutex.c | 44 +++++++++++++++++++++++++++++++++++++++++---
|
||||
6 files changed, 54 insertions(+), 29 deletions(-)
|
||||
|
||||
--- a/include/linux/locallock.h
|
||||
+++ b/include/linux/locallock.h
|
||||
@@ -43,9 +43,9 @@ struct local_irq_lock {
|
||||
* for CONFIG_PREEMPT_BASE map to the normal spin_* calls.
|
||||
*/
|
||||
#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
-# define spin_lock_local(lock) rt_spin_lock(lock)
|
||||
-# define spin_trylock_local(lock) rt_spin_trylock(lock)
|
||||
-# define spin_unlock_local(lock) rt_spin_unlock(lock)
|
||||
+# define spin_lock_local(lock) rt_spin_lock__no_mg(lock)
|
||||
+# define spin_trylock_local(lock) rt_spin_trylock__no_mg(lock)
|
||||
+# define spin_unlock_local(lock) rt_spin_unlock__no_mg(lock)
|
||||
#else
|
||||
# define spin_lock_local(lock) spin_lock(lock)
|
||||
# define spin_trylock_local(lock) spin_trylock(lock)
|
||||
--- a/include/linux/spinlock_rt.h
|
||||
+++ b/include/linux/spinlock_rt.h
|
||||
@@ -18,6 +18,10 @@ do { \
|
||||
__rt_spin_lock_init(slock, #slock, &__key); \
|
||||
} while (0)
|
||||
|
||||
+void __lockfunc rt_spin_lock__no_mg(spinlock_t *lock);
|
||||
+void __lockfunc rt_spin_unlock__no_mg(spinlock_t *lock);
|
||||
+int __lockfunc rt_spin_trylock__no_mg(spinlock_t *lock);
|
||||
+
|
||||
extern void __lockfunc rt_spin_lock(spinlock_t *lock);
|
||||
extern unsigned long __lockfunc rt_spin_lock_trace_flags(spinlock_t *lock);
|
||||
extern void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass);
|
||||
@@ -32,20 +36,16 @@ extern int atomic_dec_and_spin_lock(atom
|
||||
* lockdep-less calls, for derived types like rwlock:
|
||||
* (for trylock they can use rt_mutex_trylock() directly.
|
||||
*/
|
||||
+extern void __lockfunc __rt_spin_lock__no_mg(struct rt_mutex *lock);
|
||||
extern void __lockfunc __rt_spin_lock(struct rt_mutex *lock);
|
||||
extern void __lockfunc __rt_spin_unlock(struct rt_mutex *lock);
|
||||
extern int __lockfunc __rt_spin_trylock(struct rt_mutex *lock);
|
||||
|
||||
-#define spin_lock(lock) \
|
||||
- do { \
|
||||
- migrate_disable(); \
|
||||
- rt_spin_lock(lock); \
|
||||
- } while (0)
|
||||
+#define spin_lock(lock) rt_spin_lock(lock)
|
||||
|
||||
#define spin_lock_bh(lock) \
|
||||
do { \
|
||||
local_bh_disable(); \
|
||||
- migrate_disable(); \
|
||||
rt_spin_lock(lock); \
|
||||
} while (0)
|
||||
|
||||
@@ -56,24 +56,19 @@ extern int __lockfunc __rt_spin_trylock(
|
||||
#define spin_trylock(lock) \
|
||||
({ \
|
||||
int __locked; \
|
||||
- migrate_disable(); \
|
||||
__locked = spin_do_trylock(lock); \
|
||||
- if (!__locked) \
|
||||
- migrate_enable(); \
|
||||
__locked; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
# define spin_lock_nested(lock, subclass) \
|
||||
do { \
|
||||
- migrate_disable(); \
|
||||
rt_spin_lock_nested(lock, subclass); \
|
||||
} while (0)
|
||||
|
||||
#define spin_lock_bh_nested(lock, subclass) \
|
||||
do { \
|
||||
local_bh_disable(); \
|
||||
- migrate_disable(); \
|
||||
rt_spin_lock_nested(lock, subclass); \
|
||||
} while (0)
|
||||
|
||||
@@ -81,7 +76,6 @@ extern int __lockfunc __rt_spin_trylock(
|
||||
do { \
|
||||
typecheck(unsigned long, flags); \
|
||||
flags = 0; \
|
||||
- migrate_disable(); \
|
||||
rt_spin_lock_nested(lock, subclass); \
|
||||
} while (0)
|
||||
#else
|
||||
@@ -117,16 +111,11 @@ static inline unsigned long spin_lock_tr
|
||||
/* FIXME: we need rt_spin_lock_nest_lock */
|
||||
#define spin_lock_nest_lock(lock, nest_lock) spin_lock_nested(lock, 0)
|
||||
|
||||
-#define spin_unlock(lock) \
|
||||
- do { \
|
||||
- rt_spin_unlock(lock); \
|
||||
- migrate_enable(); \
|
||||
- } while (0)
|
||||
+#define spin_unlock(lock) rt_spin_unlock(lock)
|
||||
|
||||
#define spin_unlock_bh(lock) \
|
||||
do { \
|
||||
rt_spin_unlock(lock); \
|
||||
- migrate_enable(); \
|
||||
local_bh_enable(); \
|
||||
} while (0)
|
||||
|
||||
--- a/kernel/cpu.c
|
||||
+++ b/kernel/cpu.c
|
||||
@@ -204,8 +204,8 @@ struct hotplug_pcp {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
-# define hotplug_lock(hp) rt_spin_lock(&(hp)->lock)
|
||||
-# define hotplug_unlock(hp) rt_spin_unlock(&(hp)->lock)
|
||||
+# define hotplug_lock(hp) rt_spin_lock__no_mg(&(hp)->lock)
|
||||
+# define hotplug_unlock(hp) rt_spin_unlock__no_mg(&(hp)->lock)
|
||||
#else
|
||||
# define hotplug_lock(hp) mutex_lock(&(hp)->mutex)
|
||||
# define hotplug_unlock(hp) mutex_unlock(&(hp)->mutex)
|
||||
--- a/kernel/locking/lglock.c
|
||||
+++ b/kernel/locking/lglock.c
|
||||
@@ -10,7 +10,7 @@
|
||||
# define lg_do_unlock(l) arch_spin_unlock(l)
|
||||
#else
|
||||
# define lg_lock_ptr struct rt_mutex
|
||||
-# define lg_do_lock(l) __rt_spin_lock(l)
|
||||
+# define lg_do_lock(l) __rt_spin_lock__no_mg(l)
|
||||
# define lg_do_unlock(l) __rt_spin_unlock(l)
|
||||
#endif
|
||||
/*
|
||||
--- a/kernel/locking/rt.c
|
||||
+++ b/kernel/locking/rt.c
|
||||
@@ -235,7 +235,6 @@ EXPORT_SYMBOL(rt_read_trylock);
|
||||
void __lockfunc rt_write_lock(rwlock_t *rwlock)
|
||||
{
|
||||
rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_);
|
||||
- migrate_disable();
|
||||
__rt_spin_lock(&rwlock->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rt_write_lock);
|
||||
@@ -249,7 +248,6 @@ void __lockfunc rt_read_lock(rwlock_t *r
|
||||
* recursive read locks succeed when current owns the lock
|
||||
*/
|
||||
if (rt_mutex_owner(lock) != current) {
|
||||
- migrate_disable();
|
||||
rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_);
|
||||
__rt_spin_lock(lock);
|
||||
}
|
||||
--- a/kernel/locking/rtmutex.c
|
||||
+++ b/kernel/locking/rtmutex.c
|
||||
@@ -1103,8 +1103,16 @@ static void noinline __sched rt_spin_lo
|
||||
rt_mutex_adjust_prio(current);
|
||||
}
|
||||
|
||||
+void __lockfunc rt_spin_lock__no_mg(spinlock_t *lock)
|
||||
+{
|
||||
+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock);
|
||||
+ spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
|
||||
+}
|
||||
+EXPORT_SYMBOL(rt_spin_lock__no_mg);
|
||||
+
|
||||
void __lockfunc rt_spin_lock(spinlock_t *lock)
|
||||
{
|
||||
+ migrate_disable();
|
||||
rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock);
|
||||
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
|
||||
}
|
||||
@@ -1112,24 +1120,41 @@ EXPORT_SYMBOL(rt_spin_lock);
|
||||
|
||||
void __lockfunc __rt_spin_lock(struct rt_mutex *lock)
|
||||
{
|
||||
+ migrate_disable();
|
||||
rt_spin_lock_fastlock(lock, rt_spin_lock_slowlock);
|
||||
}
|
||||
EXPORT_SYMBOL(__rt_spin_lock);
|
||||
|
||||
+void __lockfunc __rt_spin_lock__no_mg(struct rt_mutex *lock)
|
||||
+{
|
||||
+ rt_spin_lock_fastlock(lock, rt_spin_lock_slowlock);
|
||||
+}
|
||||
+EXPORT_SYMBOL(__rt_spin_lock__no_mg);
|
||||
+
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass)
|
||||
{
|
||||
+ migrate_disable();
|
||||
rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock);
|
||||
spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
|
||||
}
|
||||
EXPORT_SYMBOL(rt_spin_lock_nested);
|
||||
#endif
|
||||
|
||||
+void __lockfunc rt_spin_unlock__no_mg(spinlock_t *lock)
|
||||
+{
|
||||
+ /* NOTE: we always pass in '1' for nested, for simplicity */
|
||||
+ spin_release(&lock->dep_map, 1, _RET_IP_);
|
||||
+ rt_spin_lock_fastunlock(&lock->lock, rt_spin_lock_slowunlock);
|
||||
+}
|
||||
+EXPORT_SYMBOL(rt_spin_unlock__no_mg);
|
||||
+
|
||||
void __lockfunc rt_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
/* NOTE: we always pass in '1' for nested, for simplicity */
|
||||
spin_release(&lock->dep_map, 1, _RET_IP_);
|
||||
rt_spin_lock_fastunlock(&lock->lock, rt_spin_lock_slowunlock);
|
||||
+ migrate_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(rt_spin_unlock);
|
||||
|
||||
@@ -1156,12 +1181,27 @@ int __lockfunc __rt_spin_trylock(struct
|
||||
return rt_mutex_trylock(lock);
|
||||
}
|
||||
|
||||
+int __lockfunc rt_spin_trylock__no_mg(spinlock_t *lock)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = rt_mutex_trylock(&lock->lock);
|
||||
+ if (ret)
|
||||
+ spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(rt_spin_trylock__no_mg);
|
||||
+
|
||||
int __lockfunc rt_spin_trylock(spinlock_t *lock)
|
||||
{
|
||||
- int ret = rt_mutex_trylock(&lock->lock);
|
||||
+ int ret;
|
||||
|
||||
+ migrate_disable();
|
||||
+ ret = rt_mutex_trylock(&lock->lock);
|
||||
if (ret)
|
||||
spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
|
||||
+ else
|
||||
+ migrate_enable();
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt_spin_trylock);
|
||||
@@ -1200,12 +1240,10 @@ int atomic_dec_and_spin_lock(atomic_t *a
|
||||
/* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
|
||||
if (atomic_add_unless(atomic, -1, 1))
|
||||
return 0;
|
||||
- migrate_disable();
|
||||
rt_spin_lock(lock);
|
||||
if (atomic_dec_and_test(atomic))
|
||||
return 1;
|
||||
rt_spin_unlock(lock);
|
||||
- migrate_enable();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic_dec_and_spin_lock);
|
|
@ -1,52 +0,0 @@
|
|||
From: Peter Zijlstra <peterz@infradead.org>
|
||||
Date: Mon, 16 May 2016 15:01:11 +0200
|
||||
Subject: [PATCH] sched,preempt: Fix preempt_count manipulations
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Vikram reported that his ARM64 compiler managed to 'optimize' away the
|
||||
preempt_count manipulations in code like:
|
||||
|
||||
preempt_enable_no_resched();
|
||||
put_user();
|
||||
preempt_disable();
|
||||
|
||||
Irrespective of that fact that that is horrible code that should be
|
||||
fixed for many reasons, it does highlight a deficiency in the generic
|
||||
preempt_count manipulators. As it is never right to combine/elide
|
||||
preempt_count manipulations like this.
|
||||
|
||||
Therefore sprinkle some volatile in the two generic accessors to
|
||||
ensure the compiler is aware of the fact that the preempt_count is
|
||||
observed outside of the regular program-order view and thus cannot be
|
||||
optimized away like this.
|
||||
|
||||
x86; the only arch not using the generic code is not affected as we
|
||||
do all this in asm in order to use the segment base per-cpu stuff.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Cc: stable-rt@vger.kernel.org
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Fixes: a787870924db ("sched, arch: Create asm/preempt.h")
|
||||
Reported-by: Vikram Mulukutla <markivx@codeaurora.org>
|
||||
Tested-by: Vikram Mulukutla <markivx@codeaurora.org>
|
||||
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/asm-generic/preempt.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/asm-generic/preempt.h
|
||||
+++ b/include/asm-generic/preempt.h
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
static __always_inline int preempt_count(void)
|
||||
{
|
||||
- return current_thread_info()->preempt_count;
|
||||
+ return READ_ONCE(current_thread_info()->preempt_count);
|
||||
}
|
||||
|
||||
-static __always_inline int *preempt_count_ptr(void)
|
||||
+static __always_inline volatile int *preempt_count_ptr(void)
|
||||
{
|
||||
return ¤t_thread_info()->preempt_count;
|
||||
}
|
|
@ -1,262 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Mon, 18 Jan 2016 17:21:59 +0100
|
||||
Subject: sched: provide a tsk_nr_cpus_allowed() helper
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
tsk_nr_cpus_allowed() is an accessor for task->nr_cpus_allowed which allows
|
||||
us to change the representation of ->nr_cpus_allowed if required.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/linux/sched.h | 5 +++++
|
||||
kernel/sched/core.c | 2 +-
|
||||
kernel/sched/deadline.c | 28 ++++++++++++++--------------
|
||||
kernel/sched/rt.c | 24 ++++++++++++------------
|
||||
4 files changed, 32 insertions(+), 27 deletions(-)
|
||||
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -1871,6 +1871,11 @@ extern int arch_task_struct_size __read_
|
||||
/* Future-safe accessor for struct task_struct's cpus_allowed. */
|
||||
#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
|
||||
|
||||
+static inline int tsk_nr_cpus_allowed(struct task_struct *p)
|
||||
+{
|
||||
+ return p->nr_cpus_allowed;
|
||||
+}
|
||||
+
|
||||
#define TNF_MIGRATED 0x01
|
||||
#define TNF_NO_GROUP 0x02
|
||||
#define TNF_SHARED 0x04
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -1515,7 +1515,7 @@ int select_task_rq(struct task_struct *p
|
||||
{
|
||||
lockdep_assert_held(&p->pi_lock);
|
||||
|
||||
- if (p->nr_cpus_allowed > 1)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1)
|
||||
cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags);
|
||||
|
||||
/*
|
||||
--- a/kernel/sched/deadline.c
|
||||
+++ b/kernel/sched/deadline.c
|
||||
@@ -134,7 +134,7 @@ static void inc_dl_migration(struct sche
|
||||
{
|
||||
struct task_struct *p = dl_task_of(dl_se);
|
||||
|
||||
- if (p->nr_cpus_allowed > 1)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1)
|
||||
dl_rq->dl_nr_migratory++;
|
||||
|
||||
update_dl_migration(dl_rq);
|
||||
@@ -144,7 +144,7 @@ static void dec_dl_migration(struct sche
|
||||
{
|
||||
struct task_struct *p = dl_task_of(dl_se);
|
||||
|
||||
- if (p->nr_cpus_allowed > 1)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1)
|
||||
dl_rq->dl_nr_migratory--;
|
||||
|
||||
update_dl_migration(dl_rq);
|
||||
@@ -966,7 +966,7 @@ static void enqueue_task_dl(struct rq *r
|
||||
|
||||
enqueue_dl_entity(&p->dl, pi_se, flags);
|
||||
|
||||
- if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
|
||||
+ if (!task_current(rq, p) && tsk_nr_cpus_allowed(p) > 1)
|
||||
enqueue_pushable_dl_task(rq, p);
|
||||
}
|
||||
|
||||
@@ -1040,9 +1040,9 @@ select_task_rq_dl(struct task_struct *p,
|
||||
* try to make it stay here, it might be important.
|
||||
*/
|
||||
if (unlikely(dl_task(curr)) &&
|
||||
- (curr->nr_cpus_allowed < 2 ||
|
||||
+ (tsk_nr_cpus_allowed(curr) < 2 ||
|
||||
!dl_entity_preempt(&p->dl, &curr->dl)) &&
|
||||
- (p->nr_cpus_allowed > 1)) {
|
||||
+ (tsk_nr_cpus_allowed(p) > 1)) {
|
||||
int target = find_later_rq(p);
|
||||
|
||||
if (target != -1 &&
|
||||
@@ -1063,7 +1063,7 @@ static void check_preempt_equal_dl(struc
|
||||
* Current can't be migrated, useless to reschedule,
|
||||
* let's hope p can move out.
|
||||
*/
|
||||
- if (rq->curr->nr_cpus_allowed == 1 ||
|
||||
+ if (tsk_nr_cpus_allowed(rq->curr) == 1 ||
|
||||
cpudl_find(&rq->rd->cpudl, rq->curr, NULL) == -1)
|
||||
return;
|
||||
|
||||
@@ -1071,7 +1071,7 @@ static void check_preempt_equal_dl(struc
|
||||
* p is migratable, so let's not schedule it and
|
||||
* see if it is pushed or pulled somewhere else.
|
||||
*/
|
||||
- if (p->nr_cpus_allowed != 1 &&
|
||||
+ if (tsk_nr_cpus_allowed(p) != 1 &&
|
||||
cpudl_find(&rq->rd->cpudl, p, NULL) != -1)
|
||||
return;
|
||||
|
||||
@@ -1185,7 +1185,7 @@ static void put_prev_task_dl(struct rq *
|
||||
{
|
||||
update_curr_dl(rq);
|
||||
|
||||
- if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1)
|
||||
+ if (on_dl_rq(&p->dl) && tsk_nr_cpus_allowed(p) > 1)
|
||||
enqueue_pushable_dl_task(rq, p);
|
||||
}
|
||||
|
||||
@@ -1286,7 +1286,7 @@ static int find_later_rq(struct task_str
|
||||
if (unlikely(!later_mask))
|
||||
return -1;
|
||||
|
||||
- if (task->nr_cpus_allowed == 1)
|
||||
+ if (tsk_nr_cpus_allowed(task) == 1)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@@ -1432,7 +1432,7 @@ static struct task_struct *pick_next_pus
|
||||
|
||||
BUG_ON(rq->cpu != task_cpu(p));
|
||||
BUG_ON(task_current(rq, p));
|
||||
- BUG_ON(p->nr_cpus_allowed <= 1);
|
||||
+ BUG_ON(tsk_nr_cpus_allowed(p) <= 1);
|
||||
|
||||
BUG_ON(!task_on_rq_queued(p));
|
||||
BUG_ON(!dl_task(p));
|
||||
@@ -1471,7 +1471,7 @@ static int push_dl_task(struct rq *rq)
|
||||
*/
|
||||
if (dl_task(rq->curr) &&
|
||||
dl_time_before(next_task->dl.deadline, rq->curr->dl.deadline) &&
|
||||
- rq->curr->nr_cpus_allowed > 1) {
|
||||
+ tsk_nr_cpus_allowed(rq->curr) > 1) {
|
||||
resched_curr(rq);
|
||||
return 0;
|
||||
}
|
||||
@@ -1618,9 +1618,9 @@ static void task_woken_dl(struct rq *rq,
|
||||
{
|
||||
if (!task_running(rq, p) &&
|
||||
!test_tsk_need_resched(rq->curr) &&
|
||||
- p->nr_cpus_allowed > 1 &&
|
||||
+ tsk_nr_cpus_allowed(p) > 1 &&
|
||||
dl_task(rq->curr) &&
|
||||
- (rq->curr->nr_cpus_allowed < 2 ||
|
||||
+ (tsk_nr_cpus_allowed(rq->curr) < 2 ||
|
||||
!dl_entity_preempt(&p->dl, &rq->curr->dl))) {
|
||||
push_dl_tasks(rq);
|
||||
}
|
||||
@@ -1724,7 +1724,7 @@ static void switched_to_dl(struct rq *rq
|
||||
|
||||
if (task_on_rq_queued(p) && rq->curr != p) {
|
||||
#ifdef CONFIG_SMP
|
||||
- if (p->nr_cpus_allowed > 1 && rq->dl.overloaded)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1 && rq->dl.overloaded)
|
||||
queue_push_tasks(rq);
|
||||
#else
|
||||
if (dl_task(rq->curr))
|
||||
--- a/kernel/sched/rt.c
|
||||
+++ b/kernel/sched/rt.c
|
||||
@@ -334,7 +334,7 @@ static void inc_rt_migration(struct sche
|
||||
rt_rq = &rq_of_rt_rq(rt_rq)->rt;
|
||||
|
||||
rt_rq->rt_nr_total++;
|
||||
- if (p->nr_cpus_allowed > 1)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1)
|
||||
rt_rq->rt_nr_migratory++;
|
||||
|
||||
update_rt_migration(rt_rq);
|
||||
@@ -351,7 +351,7 @@ static void dec_rt_migration(struct sche
|
||||
rt_rq = &rq_of_rt_rq(rt_rq)->rt;
|
||||
|
||||
rt_rq->rt_nr_total--;
|
||||
- if (p->nr_cpus_allowed > 1)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1)
|
||||
rt_rq->rt_nr_migratory--;
|
||||
|
||||
update_rt_migration(rt_rq);
|
||||
@@ -1324,7 +1324,7 @@ enqueue_task_rt(struct rq *rq, struct ta
|
||||
|
||||
enqueue_rt_entity(rt_se, flags);
|
||||
|
||||
- if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
|
||||
+ if (!task_current(rq, p) && tsk_nr_cpus_allowed(p) > 1)
|
||||
enqueue_pushable_task(rq, p);
|
||||
}
|
||||
|
||||
@@ -1413,7 +1413,7 @@ select_task_rq_rt(struct task_struct *p,
|
||||
* will have to sort it out.
|
||||
*/
|
||||
if (curr && unlikely(rt_task(curr)) &&
|
||||
- (curr->nr_cpus_allowed < 2 ||
|
||||
+ (tsk_nr_cpus_allowed(curr) < 2 ||
|
||||
curr->prio <= p->prio)) {
|
||||
int target = find_lowest_rq(p);
|
||||
|
||||
@@ -1437,7 +1437,7 @@ static void check_preempt_equal_prio(str
|
||||
* Current can't be migrated, useless to reschedule,
|
||||
* let's hope p can move out.
|
||||
*/
|
||||
- if (rq->curr->nr_cpus_allowed == 1 ||
|
||||
+ if (tsk_nr_cpus_allowed(rq->curr) == 1 ||
|
||||
!cpupri_find(&rq->rd->cpupri, rq->curr, NULL))
|
||||
return;
|
||||
|
||||
@@ -1445,7 +1445,7 @@ static void check_preempt_equal_prio(str
|
||||
* p is migratable, so let's not schedule it and
|
||||
* see if it is pushed or pulled somewhere else.
|
||||
*/
|
||||
- if (p->nr_cpus_allowed != 1
|
||||
+ if (tsk_nr_cpus_allowed(p) != 1
|
||||
&& cpupri_find(&rq->rd->cpupri, p, NULL))
|
||||
return;
|
||||
|
||||
@@ -1579,7 +1579,7 @@ static void put_prev_task_rt(struct rq *
|
||||
* The previous task needs to be made eligible for pushing
|
||||
* if it is still active
|
||||
*/
|
||||
- if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1)
|
||||
+ if (on_rt_rq(&p->rt) && tsk_nr_cpus_allowed(p) > 1)
|
||||
enqueue_pushable_task(rq, p);
|
||||
}
|
||||
|
||||
@@ -1629,7 +1629,7 @@ static int find_lowest_rq(struct task_st
|
||||
if (unlikely(!lowest_mask))
|
||||
return -1;
|
||||
|
||||
- if (task->nr_cpus_allowed == 1)
|
||||
+ if (tsk_nr_cpus_allowed(task) == 1)
|
||||
return -1; /* No other targets possible */
|
||||
|
||||
if (!cpupri_find(&task_rq(task)->rd->cpupri, task, lowest_mask))
|
||||
@@ -1762,7 +1762,7 @@ static struct task_struct *pick_next_pus
|
||||
|
||||
BUG_ON(rq->cpu != task_cpu(p));
|
||||
BUG_ON(task_current(rq, p));
|
||||
- BUG_ON(p->nr_cpus_allowed <= 1);
|
||||
+ BUG_ON(tsk_nr_cpus_allowed(p) <= 1);
|
||||
|
||||
BUG_ON(!task_on_rq_queued(p));
|
||||
BUG_ON(!rt_task(p));
|
||||
@@ -2122,9 +2122,9 @@ static void task_woken_rt(struct rq *rq,
|
||||
{
|
||||
if (!task_running(rq, p) &&
|
||||
!test_tsk_need_resched(rq->curr) &&
|
||||
- p->nr_cpus_allowed > 1 &&
|
||||
+ tsk_nr_cpus_allowed(p) > 1 &&
|
||||
(dl_task(rq->curr) || rt_task(rq->curr)) &&
|
||||
- (rq->curr->nr_cpus_allowed < 2 ||
|
||||
+ (tsk_nr_cpus_allowed(rq->curr) < 2 ||
|
||||
rq->curr->prio <= p->prio))
|
||||
push_rt_tasks(rq);
|
||||
}
|
||||
@@ -2197,7 +2197,7 @@ static void switched_to_rt(struct rq *rq
|
||||
*/
|
||||
if (task_on_rq_queued(p) && rq->curr != p) {
|
||||
#ifdef CONFIG_SMP
|
||||
- if (p->nr_cpus_allowed > 1 && rq->rt.overloaded)
|
||||
+ if (tsk_nr_cpus_allowed(p) > 1 && rq->rt.overloaded)
|
||||
queue_push_tasks(rq);
|
||||
#else
|
||||
if (p->prio < rq->curr->prio)
|
|
@ -1,58 +0,0 @@
|
|||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Mon, 18 Jan 2016 17:10:39 +0100
|
||||
Subject: sched: use tsk_cpus_allowed() instead of accessing
|
||||
->cpus_allowed
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Use the future-safe accessor for struct task_struct's.
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
kernel/sched/cpudeadline.c | 4 ++--
|
||||
kernel/sched/cpupri.c | 4 ++--
|
||||
kernel/sched/deadline.c | 2 +-
|
||||
3 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/kernel/sched/cpudeadline.c
|
||||
+++ b/kernel/sched/cpudeadline.c
|
||||
@@ -103,10 +103,10 @@ int cpudl_find(struct cpudl *cp, struct
|
||||
const struct sched_dl_entity *dl_se = &p->dl;
|
||||
|
||||
if (later_mask &&
|
||||
- cpumask_and(later_mask, cp->free_cpus, &p->cpus_allowed)) {
|
||||
+ cpumask_and(later_mask, cp->free_cpus, tsk_cpus_allowed(p))) {
|
||||
best_cpu = cpumask_any(later_mask);
|
||||
goto out;
|
||||
- } else if (cpumask_test_cpu(cpudl_maximum(cp), &p->cpus_allowed) &&
|
||||
+ } else if (cpumask_test_cpu(cpudl_maximum(cp), tsk_cpus_allowed(p)) &&
|
||||
dl_time_before(dl_se->deadline, cp->elements[0].dl)) {
|
||||
best_cpu = cpudl_maximum(cp);
|
||||
if (later_mask)
|
||||
--- a/kernel/sched/cpupri.c
|
||||
+++ b/kernel/sched/cpupri.c
|
||||
@@ -103,11 +103,11 @@ int cpupri_find(struct cpupri *cp, struc
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
- if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids)
|
||||
+ if (cpumask_any_and(tsk_cpus_allowed(p), vec->mask) >= nr_cpu_ids)
|
||||
continue;
|
||||
|
||||
if (lowest_mask) {
|
||||
- cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask);
|
||||
+ cpumask_and(lowest_mask, tsk_cpus_allowed(p), vec->mask);
|
||||
|
||||
/*
|
||||
* We have to ensure that we have at least one bit
|
||||
--- a/kernel/sched/deadline.c
|
||||
+++ b/kernel/sched/deadline.c
|
||||
@@ -1392,7 +1392,7 @@ static struct rq *find_lock_later_rq(str
|
||||
if (double_lock_balance(rq, later_rq)) {
|
||||
if (unlikely(task_rq(task) != rq ||
|
||||
!cpumask_test_cpu(later_rq->cpu,
|
||||
- &task->cpus_allowed) ||
|
||||
+ tsk_cpus_allowed(task)) ||
|
||||
task_running(rq, task) ||
|
||||
!dl_task(task) ||
|
||||
!task_on_rq_queued(task))) {
|
|
@ -1,74 +0,0 @@
|
|||
Subject: timers: Avoid the switch timers base set to NULL trick on RT
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Thu, 21 Jul 2011 15:23:39 +0200
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
On RT that code is preemptible, so we cannot assign NULL to timers
|
||||
base as a preempter would spin forever in lock_timer_base().
|
||||
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/time/timer.c | 45 +++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 35 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/kernel/time/timer.c
|
||||
+++ b/kernel/time/timer.c
|
||||
@@ -780,6 +780,39 @@ static struct tvec_base *lock_timer_base
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+static inline struct tvec_base *switch_timer_base(struct timer_list *timer,
|
||||
+ struct tvec_base *old,
|
||||
+ struct tvec_base *new)
|
||||
+{
|
||||
+ /*
|
||||
+ * We cannot do the below because we might be preempted and
|
||||
+ * then the preempter would see NULL and loop forever.
|
||||
+ */
|
||||
+ if (spin_trylock(&new->lock)) {
|
||||
+ WRITE_ONCE(timer->flags,
|
||||
+ (timer->flags & ~TIMER_BASEMASK) | new->cpu);
|
||||
+ spin_unlock(&old->lock);
|
||||
+ return new;
|
||||
+ }
|
||||
+ return old;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+static inline struct tvec_base *switch_timer_base(struct timer_list *timer,
|
||||
+ struct tvec_base *old,
|
||||
+ struct tvec_base *new)
|
||||
+{
|
||||
+ /* See the comment in lock_timer_base() */
|
||||
+ timer->flags |= TIMER_MIGRATING;
|
||||
+
|
||||
+ spin_unlock(&old->lock);
|
||||
+ spin_lock(&new->lock);
|
||||
+ WRITE_ONCE(timer->flags,
|
||||
+ (timer->flags & ~TIMER_BASEMASK) | new->cpu);
|
||||
+ return new;
|
||||
+}
|
||||
+#endif
|
||||
|
||||
static inline int
|
||||
__mod_timer(struct timer_list *timer, unsigned long expires,
|
||||
@@ -810,16 +843,8 @@ static inline int
|
||||
* handler yet has not finished. This also guarantees that
|
||||
* the timer is serialized wrt itself.
|
||||
*/
|
||||
- if (likely(base->running_timer != timer)) {
|
||||
- /* See the comment in lock_timer_base() */
|
||||
- timer->flags |= TIMER_MIGRATING;
|
||||
-
|
||||
- spin_unlock(&base->lock);
|
||||
- base = new_base;
|
||||
- spin_lock(&base->lock);
|
||||
- WRITE_ONCE(timer->flags,
|
||||
- (timer->flags & ~TIMER_BASEMASK) | base->cpu);
|
||||
- }
|
||||
+ if (likely(base->running_timer != timer))
|
||||
+ base = switch_timer_base(timer, base, new_base);
|
||||
}
|
||||
|
||||
timer->expires = expires;
|
|
@ -1,55 +0,0 @@
|
|||
From: Ingo Molnar <mingo@elte.hu>
|
||||
Date: Fri, 3 Jul 2009 08:30:20 -0500
|
||||
Subject: timers: Preempt-rt support
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
The base->lock is a sleeping lock. Try not to workaround with a
|
||||
spin_trylock(). The rt-mutex lock is not irq save even the try-lock
|
||||
due to way how the inner lock accessed. Even with this fixed have the
|
||||
problem that the owner is not the current process on the CPU but his
|
||||
pid is used while taking the lock. Therefore we go with ext jiffy for
|
||||
the wakeup. Also drop preempt_disable() usage since we need just to
|
||||
ensure not to switch CPUs (the data structures have own locks).
|
||||
|
||||
[bigeasy: dropped that spin try lock]
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
kernel/time/timer.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/kernel/time/timer.c
|
||||
+++ b/kernel/time/timer.c
|
||||
@@ -1422,6 +1422,14 @@ u64 get_next_timer_interrupt(unsigned lo
|
||||
if (cpu_is_offline(smp_processor_id()))
|
||||
return expires;
|
||||
|
||||
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||||
+ /*
|
||||
+ * On PREEMPT_RT we cannot sleep here. As a result we can't take
|
||||
+ * the base lock to check when the next timer is pending and so
|
||||
+ * we assume the next jiffy.
|
||||
+ */
|
||||
+ return basem + TICK_NSEC;
|
||||
+#endif
|
||||
spin_lock(&base->lock);
|
||||
if (base->active_timers) {
|
||||
if (time_before_eq(base->next_timer, base->timer_jiffies))
|
||||
@@ -1632,7 +1640,7 @@ static void migrate_timers(int cpu)
|
||||
|
||||
BUG_ON(cpu_online(cpu));
|
||||
old_base = per_cpu_ptr(&tvec_bases, cpu);
|
||||
- new_base = get_cpu_ptr(&tvec_bases);
|
||||
+ new_base = get_local_ptr(&tvec_bases);
|
||||
/*
|
||||
* The caller is globally serialized and nobody else
|
||||
* takes two locks at once, deadlock is not possible.
|
||||
@@ -1656,7 +1664,7 @@ static void migrate_timers(int cpu)
|
||||
|
||||
spin_unlock(&old_base->lock);
|
||||
spin_unlock_irq(&new_base->lock);
|
||||
- put_cpu_ptr(&tvec_bases);
|
||||
+ put_local_ptr(&tvec_bases);
|
||||
}
|
||||
|
||||
static int timer_cpu_notify(struct notifier_block *self,
|
|
@ -1,50 +0,0 @@
|
|||
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Date: Wed, 25 May 2016 14:03:50 +0200
|
||||
Subject: [PATCH] trace: correct off by one while recording the trace-event
|
||||
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.6/older/patches-4.6.2-rt5.tar.xz
|
||||
|
||||
Trace events like raw_syscalls show always a preempt code of one. The
|
||||
reason is that on PREEMPT kernels rcu_read_lock_sched_notrace()
|
||||
increases the preemption counter and the function recording the counter
|
||||
is caller within the RCU section.
|
||||
|
||||
Cc: stable-rt@vger.kernel.org
|
||||
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
---
|
||||
include/linux/tracepoint.h | 13 +++++++++++++
|
||||
kernel/trace/trace_events.c | 2 +-
|
||||
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/tracepoint.h
|
||||
+++ b/include/linux/tracepoint.h
|
||||
@@ -33,6 +33,19 @@ struct trace_enum_map {
|
||||
|
||||
#define TRACEPOINT_DEFAULT_PRIO 10
|
||||
|
||||
+/*
|
||||
+ * The preempt count recorded in trace_event_raw_event_# are off by one due to
|
||||
+ * rcu_read_lock_sched_notrace() in __DO_TRACE. This is corrected here.
|
||||
+ */
|
||||
+static inline int event_preempt_count(void)
|
||||
+{
|
||||
+#ifdef CONFIG_PREEMPT
|
||||
+ return preempt_count() - 1;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
extern int
|
||||
tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
|
||||
extern int
|
||||
--- a/kernel/trace/trace_events.c
|
||||
+++ b/kernel/trace/trace_events.c
|
||||
@@ -243,7 +243,7 @@ void *trace_event_buffer_reserve(struct
|
||||
return NULL;
|
||||
|
||||
local_save_flags(fbuffer->flags);
|
||||
- fbuffer->pc = preempt_count();
|
||||
+ fbuffer->pc = event_preempt_count();
|
||||
fbuffer->trace_file = trace_file;
|
||||
|
||||
fbuffer->event =
|
Loading…
Reference in New Issue