diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/Kconfig.locks | 4 | ||||
| -rw-r--r-- | kernel/futex.c | 6 | ||||
| -rw-r--r-- | kernel/locking/Makefile | 3 | ||||
| -rw-r--r-- | kernel/locking/mcs_spinlock.h | 16 | ||||
| -rw-r--r-- | kernel/locking/mutex.c | 60 | ||||
| -rw-r--r-- | kernel/locking/osq_lock.c (renamed from kernel/locking/mcs_spinlock.c) | 9 | ||||
| -rw-r--r-- | kernel/locking/rtmutex.c | 7 | ||||
| -rw-r--r-- | kernel/locking/rwsem-spinlock.c | 2 | ||||
| -rw-r--r-- | kernel/locking/rwsem-xadd.c | 3 | ||||
| -rw-r--r-- | kernel/sched/completion.c | 18 | ||||
| -rw-r--r-- | kernel/softirq.c | 6 |
11 files changed, 63 insertions, 71 deletions
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks index 76768ee812b2..08561f1acd13 100644 --- a/kernel/Kconfig.locks +++ b/kernel/Kconfig.locks | |||
| @@ -231,6 +231,10 @@ config RWSEM_SPIN_ON_OWNER | |||
| 231 | def_bool y | 231 | def_bool y |
| 232 | depends on SMP && RWSEM_XCHGADD_ALGORITHM && ARCH_SUPPORTS_ATOMIC_RMW | 232 | depends on SMP && RWSEM_XCHGADD_ALGORITHM && ARCH_SUPPORTS_ATOMIC_RMW |
| 233 | 233 | ||
| 234 | config LOCK_SPIN_ON_OWNER | ||
| 235 | def_bool y | ||
| 236 | depends on MUTEX_SPIN_ON_OWNER || RWSEM_SPIN_ON_OWNER | ||
| 237 | |||
| 234 | config ARCH_USE_QUEUE_RWLOCK | 238 | config ARCH_USE_QUEUE_RWLOCK |
| 235 | bool | 239 | bool |
| 236 | 240 | ||
diff --git a/kernel/futex.c b/kernel/futex.c index 63678b573d61..4eeb63de7e54 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -2258,7 +2258,7 @@ static long futex_wait_restart(struct restart_block *restart) | |||
| 2258 | * if there are waiters then it will block, it does PI, etc. (Due to | 2258 | * if there are waiters then it will block, it does PI, etc. (Due to |
| 2259 | * races the kernel might see a 0 value of the futex too.) | 2259 | * races the kernel might see a 0 value of the futex too.) |
| 2260 | */ | 2260 | */ |
| 2261 | static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, int detect, | 2261 | static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, |
| 2262 | ktime_t *time, int trylock) | 2262 | ktime_t *time, int trylock) |
| 2263 | { | 2263 | { |
| 2264 | struct hrtimer_sleeper timeout, *to = NULL; | 2264 | struct hrtimer_sleeper timeout, *to = NULL; |
| @@ -2953,11 +2953,11 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | |||
| 2953 | case FUTEX_WAKE_OP: | 2953 | case FUTEX_WAKE_OP: |
| 2954 | return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); | 2954 | return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); |
| 2955 | case FUTEX_LOCK_PI: | 2955 | case FUTEX_LOCK_PI: |
| 2956 | return futex_lock_pi(uaddr, flags, val, timeout, 0); | 2956 | return futex_lock_pi(uaddr, flags, timeout, 0); |
| 2957 | case FUTEX_UNLOCK_PI: | 2957 | case FUTEX_UNLOCK_PI: |
| 2958 | return futex_unlock_pi(uaddr, flags); | 2958 | return futex_unlock_pi(uaddr, flags); |
| 2959 | case FUTEX_TRYLOCK_PI: | 2959 | case FUTEX_TRYLOCK_PI: |
| 2960 | return futex_lock_pi(uaddr, flags, 0, timeout, 1); | 2960 | return futex_lock_pi(uaddr, flags, NULL, 1); |
| 2961 | case FUTEX_WAIT_REQUEUE_PI: | 2961 | case FUTEX_WAIT_REQUEUE_PI: |
| 2962 | val3 = FUTEX_BITSET_MATCH_ANY; | 2962 | val3 = FUTEX_BITSET_MATCH_ANY; |
| 2963 | return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3, | 2963 | return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3, |
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile index 8541bfdfd232..4ca8eb151975 100644 --- a/kernel/locking/Makefile +++ b/kernel/locking/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | ||
| 2 | obj-y += mutex.o semaphore.o rwsem.o mcs_spinlock.o | 2 | obj-y += mutex.o semaphore.o rwsem.o |
| 3 | 3 | ||
| 4 | ifdef CONFIG_FUNCTION_TRACER | 4 | ifdef CONFIG_FUNCTION_TRACER |
| 5 | CFLAGS_REMOVE_lockdep.o = -pg | 5 | CFLAGS_REMOVE_lockdep.o = -pg |
| @@ -14,6 +14,7 @@ ifeq ($(CONFIG_PROC_FS),y) | |||
| 14 | obj-$(CONFIG_LOCKDEP) += lockdep_proc.o | 14 | obj-$(CONFIG_LOCKDEP) += lockdep_proc.o |
| 15 | endif | 15 | endif |
| 16 | obj-$(CONFIG_SMP) += spinlock.o | 16 | obj-$(CONFIG_SMP) += spinlock.o |
| 17 | obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o | ||
| 17 | obj-$(CONFIG_SMP) += lglock.o | 18 | obj-$(CONFIG_SMP) += lglock.o |
| 18 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o | 19 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o |
| 19 | obj-$(CONFIG_RT_MUTEXES) += rtmutex.o | 20 | obj-$(CONFIG_RT_MUTEXES) += rtmutex.o |
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h index 4d60986fcbee..d1fe2ba5bac9 100644 --- a/kernel/locking/mcs_spinlock.h +++ b/kernel/locking/mcs_spinlock.h | |||
| @@ -108,20 +108,4 @@ void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node) | |||
| 108 | arch_mcs_spin_unlock_contended(&next->locked); | 108 | arch_mcs_spin_unlock_contended(&next->locked); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /* | ||
| 112 | * Cancellable version of the MCS lock above. | ||
| 113 | * | ||
| 114 | * Intended for adaptive spinning of sleeping locks: | ||
| 115 | * mutex_lock()/rwsem_down_{read,write}() etc. | ||
| 116 | */ | ||
| 117 | |||
| 118 | struct optimistic_spin_node { | ||
| 119 | struct optimistic_spin_node *next, *prev; | ||
| 120 | int locked; /* 1 if lock acquired */ | ||
| 121 | int cpu; /* encoded CPU # value */ | ||
| 122 | }; | ||
| 123 | |||
| 124 | extern bool osq_lock(struct optimistic_spin_queue *lock); | ||
| 125 | extern void osq_unlock(struct optimistic_spin_queue *lock); | ||
| 126 | |||
| 127 | #endif /* __LINUX_MCS_SPINLOCK_H */ | 111 | #endif /* __LINUX_MCS_SPINLOCK_H */ |
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 454195194d4a..57407062e209 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c | |||
| @@ -147,7 +147,7 @@ static __always_inline void ww_mutex_lock_acquired(struct ww_mutex *ww, | |||
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | /* | 149 | /* |
| 150 | * after acquiring lock with fastpath or when we lost out in contested | 150 | * After acquiring lock with fastpath or when we lost out in contested |
| 151 | * slowpath, set ctx and wake up any waiters so they can recheck. | 151 | * slowpath, set ctx and wake up any waiters so they can recheck. |
| 152 | * | 152 | * |
| 153 | * This function is never called when CONFIG_DEBUG_LOCK_ALLOC is set, | 153 | * This function is never called when CONFIG_DEBUG_LOCK_ALLOC is set, |
| @@ -191,19 +191,32 @@ ww_mutex_set_context_fastpath(struct ww_mutex *lock, | |||
| 191 | spin_unlock_mutex(&lock->base.wait_lock, flags); | 191 | spin_unlock_mutex(&lock->base.wait_lock, flags); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | |||
| 195 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | ||
| 196 | /* | 194 | /* |
| 197 | * In order to avoid a stampede of mutex spinners from acquiring the mutex | 195 | * After acquiring lock in the slowpath set ctx and wake up any |
| 198 | * more or less simultaneously, the spinners need to acquire a MCS lock | 196 | * waiters so they can recheck. |
| 199 | * first before spinning on the owner field. | ||
| 200 | * | 197 | * |
| 198 | * Callers must hold the mutex wait_lock. | ||
| 201 | */ | 199 | */ |
| 200 | static __always_inline void | ||
| 201 | ww_mutex_set_context_slowpath(struct ww_mutex *lock, | ||
| 202 | struct ww_acquire_ctx *ctx) | ||
| 203 | { | ||
| 204 | struct mutex_waiter *cur; | ||
| 202 | 205 | ||
| 203 | /* | 206 | ww_mutex_lock_acquired(lock, ctx); |
| 204 | * Mutex spinning code migrated from kernel/sched/core.c | 207 | lock->ctx = ctx; |
| 205 | */ | 208 | |
| 209 | /* | ||
| 210 | * Give any possible sleeping processes the chance to wake up, | ||
| 211 | * so they can recheck if they have to back off. | ||
| 212 | */ | ||
| 213 | list_for_each_entry(cur, &lock->base.wait_list, list) { | ||
| 214 | debug_mutex_wake_waiter(&lock->base, cur); | ||
| 215 | wake_up_process(cur->task); | ||
| 216 | } | ||
| 217 | } | ||
| 206 | 218 | ||
| 219 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | ||
| 207 | static inline bool owner_running(struct mutex *lock, struct task_struct *owner) | 220 | static inline bool owner_running(struct mutex *lock, struct task_struct *owner) |
| 208 | { | 221 | { |
| 209 | if (lock->owner != owner) | 222 | if (lock->owner != owner) |
| @@ -307,6 +320,11 @@ static bool mutex_optimistic_spin(struct mutex *lock, | |||
| 307 | if (!mutex_can_spin_on_owner(lock)) | 320 | if (!mutex_can_spin_on_owner(lock)) |
| 308 | goto done; | 321 | goto done; |
| 309 | 322 | ||
| 323 | /* | ||
| 324 | * In order to avoid a stampede of mutex spinners trying to | ||
| 325 | * acquire the mutex all at once, the spinners need to take a | ||
| 326 | * MCS (queued) lock first before spinning on the owner field. | ||
| 327 | */ | ||
| 310 | if (!osq_lock(&lock->osq)) | 328 | if (!osq_lock(&lock->osq)) |
| 311 | goto done; | 329 | goto done; |
| 312 | 330 | ||
| @@ -469,7 +487,7 @@ void __sched ww_mutex_unlock(struct ww_mutex *lock) | |||
| 469 | EXPORT_SYMBOL(ww_mutex_unlock); | 487 | EXPORT_SYMBOL(ww_mutex_unlock); |
| 470 | 488 | ||
| 471 | static inline int __sched | 489 | static inline int __sched |
| 472 | __mutex_lock_check_stamp(struct mutex *lock, struct ww_acquire_ctx *ctx) | 490 | __ww_mutex_lock_check_stamp(struct mutex *lock, struct ww_acquire_ctx *ctx) |
| 473 | { | 491 | { |
| 474 | struct ww_mutex *ww = container_of(lock, struct ww_mutex, base); | 492 | struct ww_mutex *ww = container_of(lock, struct ww_mutex, base); |
| 475 | struct ww_acquire_ctx *hold_ctx = ACCESS_ONCE(ww->ctx); | 493 | struct ww_acquire_ctx *hold_ctx = ACCESS_ONCE(ww->ctx); |
| @@ -557,7 +575,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
| 557 | } | 575 | } |
| 558 | 576 | ||
| 559 | if (use_ww_ctx && ww_ctx->acquired > 0) { | 577 | if (use_ww_ctx && ww_ctx->acquired > 0) { |
| 560 | ret = __mutex_lock_check_stamp(lock, ww_ctx); | 578 | ret = __ww_mutex_lock_check_stamp(lock, ww_ctx); |
| 561 | if (ret) | 579 | if (ret) |
| 562 | goto err; | 580 | goto err; |
| 563 | } | 581 | } |
| @@ -569,6 +587,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
| 569 | schedule_preempt_disabled(); | 587 | schedule_preempt_disabled(); |
| 570 | spin_lock_mutex(&lock->wait_lock, flags); | 588 | spin_lock_mutex(&lock->wait_lock, flags); |
| 571 | } | 589 | } |
| 590 | __set_task_state(task, TASK_RUNNING); | ||
| 591 | |||
| 572 | mutex_remove_waiter(lock, &waiter, current_thread_info()); | 592 | mutex_remove_waiter(lock, &waiter, current_thread_info()); |
| 573 | /* set it to 0 if there are no waiters left: */ | 593 | /* set it to 0 if there are no waiters left: */ |
| 574 | if (likely(list_empty(&lock->wait_list))) | 594 | if (likely(list_empty(&lock->wait_list))) |
| @@ -582,23 +602,7 @@ skip_wait: | |||
| 582 | 602 | ||
| 583 | if (use_ww_ctx) { | 603 | if (use_ww_ctx) { |
| 584 | struct ww_mutex *ww = container_of(lock, struct ww_mutex, base); | 604 | struct ww_mutex *ww = container_of(lock, struct ww_mutex, base); |
| 585 | struct mutex_waiter *cur; | 605 | ww_mutex_set_context_slowpath(ww, ww_ctx); |
| 586 | |||
| 587 | /* | ||
| 588 | * This branch gets optimized out for the common case, | ||
| 589 | * and is only important for ww_mutex_lock. | ||
| 590 | */ | ||
| 591 | ww_mutex_lock_acquired(ww, ww_ctx); | ||
| 592 | ww->ctx = ww_ctx; | ||
| 593 | |||
| 594 | /* | ||
| 595 | * Give any possible sleeping processes the chance to wake up, | ||
| 596 | * so they can recheck if they have to back off. | ||
| 597 | */ | ||
| 598 | list_for_each_entry(cur, &lock->wait_list, list) { | ||
| 599 | debug_mutex_wake_waiter(lock, cur); | ||
| 600 | wake_up_process(cur->task); | ||
| 601 | } | ||
| 602 | } | 606 | } |
| 603 | 607 | ||
| 604 | spin_unlock_mutex(&lock->wait_lock, flags); | 608 | spin_unlock_mutex(&lock->wait_lock, flags); |
diff --git a/kernel/locking/mcs_spinlock.c b/kernel/locking/osq_lock.c index 9887a905a762..c112d00341b0 100644 --- a/kernel/locking/mcs_spinlock.c +++ b/kernel/locking/osq_lock.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | #include <linux/percpu.h> | 1 | #include <linux/percpu.h> |
| 2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
| 3 | #include "mcs_spinlock.h" | 3 | #include <linux/osq_lock.h> |
| 4 | |||
| 5 | #ifdef CONFIG_SMP | ||
| 6 | 4 | ||
| 7 | /* | 5 | /* |
| 8 | * An MCS like lock especially tailored for optimistic spinning for sleeping | 6 | * An MCS like lock especially tailored for optimistic spinning for sleeping |
| @@ -111,7 +109,7 @@ bool osq_lock(struct optimistic_spin_queue *lock) | |||
| 111 | * cmpxchg in an attempt to undo our queueing. | 109 | * cmpxchg in an attempt to undo our queueing. |
| 112 | */ | 110 | */ |
| 113 | 111 | ||
| 114 | while (!smp_load_acquire(&node->locked)) { | 112 | while (!ACCESS_ONCE(node->locked)) { |
| 115 | /* | 113 | /* |
| 116 | * If we need to reschedule bail... so we can block. | 114 | * If we need to reschedule bail... so we can block. |
| 117 | */ | 115 | */ |
| @@ -203,6 +201,3 @@ void osq_unlock(struct optimistic_spin_queue *lock) | |||
| 203 | if (next) | 201 | if (next) |
| 204 | ACCESS_ONCE(next->locked) = 1; | 202 | ACCESS_ONCE(next->locked) = 1; |
| 205 | } | 203 | } |
| 206 | |||
| 207 | #endif | ||
| 208 | |||
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 7c98873a3077..3059bc2f022d 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c | |||
| @@ -1130,6 +1130,7 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state, | |||
| 1130 | set_current_state(state); | 1130 | set_current_state(state); |
| 1131 | } | 1131 | } |
| 1132 | 1132 | ||
| 1133 | __set_current_state(TASK_RUNNING); | ||
| 1133 | return ret; | 1134 | return ret; |
| 1134 | } | 1135 | } |
| 1135 | 1136 | ||
| @@ -1188,10 +1189,9 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, | |||
| 1188 | ret = task_blocks_on_rt_mutex(lock, &waiter, current, chwalk); | 1189 | ret = task_blocks_on_rt_mutex(lock, &waiter, current, chwalk); |
| 1189 | 1190 | ||
| 1190 | if (likely(!ret)) | 1191 | if (likely(!ret)) |
| 1192 | /* sleep on the mutex */ | ||
| 1191 | ret = __rt_mutex_slowlock(lock, state, timeout, &waiter); | 1193 | ret = __rt_mutex_slowlock(lock, state, timeout, &waiter); |
| 1192 | 1194 | ||
| 1193 | set_current_state(TASK_RUNNING); | ||
| 1194 | |||
| 1195 | if (unlikely(ret)) { | 1195 | if (unlikely(ret)) { |
| 1196 | remove_waiter(lock, &waiter); | 1196 | remove_waiter(lock, &waiter); |
| 1197 | rt_mutex_handle_deadlock(ret, chwalk, &waiter); | 1197 | rt_mutex_handle_deadlock(ret, chwalk, &waiter); |
| @@ -1626,10 +1626,9 @@ int rt_mutex_finish_proxy_lock(struct rt_mutex *lock, | |||
| 1626 | 1626 | ||
| 1627 | set_current_state(TASK_INTERRUPTIBLE); | 1627 | set_current_state(TASK_INTERRUPTIBLE); |
| 1628 | 1628 | ||
| 1629 | /* sleep on the mutex */ | ||
| 1629 | ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter); | 1630 | ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter); |
| 1630 | 1631 | ||
| 1631 | set_current_state(TASK_RUNNING); | ||
| 1632 | |||
| 1633 | if (unlikely(ret)) | 1632 | if (unlikely(ret)) |
| 1634 | remove_waiter(lock, waiter); | 1633 | remove_waiter(lock, waiter); |
| 1635 | 1634 | ||
diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c index 2c93571162cb..2555ae15ec14 100644 --- a/kernel/locking/rwsem-spinlock.c +++ b/kernel/locking/rwsem-spinlock.c | |||
| @@ -154,7 +154,7 @@ void __sched __down_read(struct rw_semaphore *sem) | |||
| 154 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 154 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | tsk->state = TASK_RUNNING; | 157 | __set_task_state(tsk, TASK_RUNNING); |
| 158 | out: | 158 | out: |
| 159 | ; | 159 | ; |
| 160 | } | 160 | } |
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 7628c3fc37ca..2f7cc4076f50 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c | |||
| @@ -242,8 +242,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) | |||
| 242 | schedule(); | 242 | schedule(); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | tsk->state = TASK_RUNNING; | 245 | __set_task_state(tsk, TASK_RUNNING); |
| 246 | |||
| 247 | return sem; | 246 | return sem; |
| 248 | } | 247 | } |
| 249 | EXPORT_SYMBOL(rwsem_down_read_failed); | 248 | EXPORT_SYMBOL(rwsem_down_read_failed); |
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c index 607f852b4d04..7052d3fd4e7b 100644 --- a/kernel/sched/completion.c +++ b/kernel/sched/completion.c | |||
| @@ -268,6 +268,15 @@ bool try_wait_for_completion(struct completion *x) | |||
| 268 | unsigned long flags; | 268 | unsigned long flags; |
| 269 | int ret = 1; | 269 | int ret = 1; |
| 270 | 270 | ||
| 271 | /* | ||
| 272 | * Since x->done will need to be locked only | ||
| 273 | * in the non-blocking case, we check x->done | ||
| 274 | * first without taking the lock so we can | ||
| 275 | * return early in the blocking case. | ||
| 276 | */ | ||
| 277 | if (!ACCESS_ONCE(x->done)) | ||
| 278 | return 0; | ||
| 279 | |||
| 271 | spin_lock_irqsave(&x->wait.lock, flags); | 280 | spin_lock_irqsave(&x->wait.lock, flags); |
| 272 | if (!x->done) | 281 | if (!x->done) |
| 273 | ret = 0; | 282 | ret = 0; |
| @@ -288,13 +297,6 @@ EXPORT_SYMBOL(try_wait_for_completion); | |||
| 288 | */ | 297 | */ |
| 289 | bool completion_done(struct completion *x) | 298 | bool completion_done(struct completion *x) |
| 290 | { | 299 | { |
| 291 | unsigned long flags; | 300 | return !!ACCESS_ONCE(x->done); |
| 292 | int ret = 1; | ||
| 293 | |||
| 294 | spin_lock_irqsave(&x->wait.lock, flags); | ||
| 295 | if (!x->done) | ||
| 296 | ret = 0; | ||
| 297 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
| 298 | return ret; | ||
| 299 | } | 301 | } |
| 300 | EXPORT_SYMBOL(completion_done); | 302 | EXPORT_SYMBOL(completion_done); |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 8cdb98847c7b..479e4436f787 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
| @@ -114,8 +114,12 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) | |||
| 114 | trace_softirqs_off(ip); | 114 | trace_softirqs_off(ip); |
| 115 | raw_local_irq_restore(flags); | 115 | raw_local_irq_restore(flags); |
| 116 | 116 | ||
| 117 | if (preempt_count() == cnt) | 117 | if (preempt_count() == cnt) { |
| 118 | #ifdef CONFIG_DEBUG_PREEMPT | ||
| 119 | current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1); | ||
| 120 | #endif | ||
| 118 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | 121 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); |
| 122 | } | ||
| 119 | } | 123 | } |
| 120 | EXPORT_SYMBOL(__local_bh_disable_ip); | 124 | EXPORT_SYMBOL(__local_bh_disable_ip); |
| 121 | #endif /* CONFIG_TRACE_IRQFLAGS */ | 125 | #endif /* CONFIG_TRACE_IRQFLAGS */ |
