History

BKL: That's all, folks

This removes the implementation of the big kernel lock, at last. A lot of people have worked on this in the past, I so the credit for this patch should be with everyone who participated in the hunt. The names on the Cc list are the people that were the most active in this, according to the recorded git history, in alphabetical order.

Arnd Bergmann committed 15 years ago

Commit 4ba82161 parent ae7eb897 files · +2 −232Browse files

Unified · Split

7 files
  1. include/linux/hardirq.h +1 −8
  2. include/linux/smp_lock.h +0 −65
  3. init/Kconfig +0 −5
  4. kernel/sched.c +1 −8
  5. lib/Kconfig.debug +0 −9
  6. lib/Makefile +0 −1
  7. lib/kernel_lock.c +0 −136
include/linux/hardirq.h+1−8
@@ -93,13 +93,6 @@ · 92 unmodified lines
9393 */
9494 #define in_nmi() (preempt_count() & NMI_MASK)
9595
96−#if defined(CONFIG_PREEMPT) && defined(CONFIG_BKL)
97−# include <linux/sched.h>
98−# define PREEMPT_INATOMIC_BASE (current->lock_depth >= 0)
99−#else
100−# define PREEMPT_INATOMIC_BASE 0
101−#endif
102−
10396 #if defined(CONFIG_PREEMPT)
10497 # define PREEMPT_CHECK_OFFSET 1
10598 #else
@@ -113,7 +106,7 @@ · 7 unmodified lines
113106 * used in the general case to determine whether sleeping is possible.
114107 * Do not use in_atomic() in driver code.
115108 */
116−#define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_INATOMIC_BASE)
109+#define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != 0)
117110
118111 /*
119112 * Check whether we were atomic before we did preempt_disable():
include/linux/smp_lock.h+0−65
@@ -1,65 +0,0 @@
1−#ifndef __LINUX_SMPLOCK_H
2−#define __LINUX_SMPLOCK_H
3−
4−#ifdef CONFIG_LOCK_KERNEL
5−#include <linux/sched.h>
6−
7−extern int __lockfunc __reacquire_kernel_lock(void);
8−extern void __lockfunc __release_kernel_lock(void);
9−
10−/*
11− * Release/re-acquire global kernel lock for the scheduler
12− */
13−#define release_kernel_lock(tsk) do { \
14− if (unlikely((tsk)->lock_depth >= 0)) \
15− __release_kernel_lock(); \
16−} while (0)
17−
18−static inline int reacquire_kernel_lock(struct task_struct *task)
19−{
20− if (unlikely(task->lock_depth >= 0))
21− return __reacquire_kernel_lock();
22− return 0;
23−}
24−
25−extern void __lockfunc
26−_lock_kernel(const char *func, const char *file, int line)
27−__acquires(kernel_lock);
28−
29−extern void __lockfunc
30−_unlock_kernel(const char *func, const char *file, int line)
31−__releases(kernel_lock);
32−
33−#define lock_kernel() do { \
34− _lock_kernel(__func__, __FILE__, __LINE__); \
35−} while (0)
36−
37−#define unlock_kernel() do { \
38− _unlock_kernel(__func__, __FILE__, __LINE__); \
39−} while (0)
40−
41−/*
42− * Various legacy drivers don't really need the BKL in a specific
43− * function, but they *do* need to know that the BKL became available.
44− * This function just avoids wrapping a bunch of lock/unlock pairs
45− * around code which doesn't really need it.
46− */
47−static inline void cycle_kernel_lock(void)
48−{
49− lock_kernel();
50− unlock_kernel();
51−}
52−
53−#else
54−
55−#ifdef CONFIG_BKL /* provoke build bug if not set */
56−#define lock_kernel()
57−#define unlock_kernel()
58−#define cycle_kernel_lock() do { } while(0)
59−#endif /* CONFIG_BKL */
60−
61−#define release_kernel_lock(task) do { } while(0)
62−#define reacquire_kernel_lock(task) 0
63−
64−#endif /* CONFIG_LOCK_KERNEL */
65−#endif /* __LINUX_SMPLOCK_H */
init/Kconfig+0−5
@@ -69,11 +69,6 @@ config BROKEN_ON_SMP · 68 unmodified lines
6969 depends on BROKEN || !SMP
7070 default y
7171
72−config LOCK_KERNEL
73− bool
74− depends on (SMP || PREEMPT) && BKL
75− default y
76−
7772 config INIT_ENV_ARG_LIMIT
7873 int
7974 default 32 if !UML
kernel/sched.c+1−8
@@ -32,7 +32,6 @@ · 31 unmodified lines
3232 #include <linux/init.h>
3333 #include <linux/uaccess.h>
3434 #include <linux/highmem.h>
35−#include <linux/smp_lock.h>
3635 #include <asm/mmu_context.h>
3736 #include <linux/interrupt.h>
3837 #include <linux/capability.h>
@@ -3945,9 +3944,6 @@ need_resched: · 3906 unmodified lines
39453944 rcu_note_context_switch(cpu);
39463945 prev = rq->curr;
39473946
3948− release_kernel_lock(prev);
3949−need_resched_nonpreemptible:
3950−
39513947 schedule_debug(prev);
39523948
39533949 if (sched_feat(HRTICK))
@@ -4010,9 +4006,6 @@ need_resched_nonpreemptible: · 56 unmodified lines
40104006
40114007 post_schedule(rq);
40124008
4013− if (unlikely(reacquire_kernel_lock(prev)))
4014− goto need_resched_nonpreemptible;
4015−
40164009 preempt_enable_no_resched();
40174010 if (need_resched())
40184011 goto need_resched;
@@ -8074,7 +8067,7 @@ static inline int preempt_count_equals(int preempt_offset) · 4055 unmodified lines
80748067 {
80758068 int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth();
80768069
8077− return (nested == PREEMPT_INATOMIC_BASE + preempt_offset);
8070+ return (nested == preempt_offset);
80788071 }
80798072
80808073 void __might_sleep(const char *file, int line, int preempt_offset)
lib/Kconfig.debug+0−9
@@ -470,15 +470,6 @@ config DEBUG_MUTEXES · 469 unmodified lines
470470 This feature allows mutex semantics violations to be detected and
471471 reported.
472472
473−config BKL
474− bool "Big Kernel Lock" if (SMP || PREEMPT)
475− default y
476− help
477− This is the traditional lock that is used in old code instead
478− of proper locking. All drivers that use the BKL should depend
479− on this symbol.
480− Say Y here unless you are working on removing the BKL.
481−
482473 config DEBUG_LOCK_ALLOC
483474 bool "Lock debugging: detect incorrect freeing of live locks"
484475 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
lib/Makefile+0−1
@@ -43,7 +43,6 @@ obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o · 42 unmodified lines
4343 CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
4444 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
4545
46−obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
4746 obj-$(CONFIG_BTREE) += btree.o
4847 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
4948 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
lib/kernel_lock.c+0−136
@@ -1,136 +0,0 @@
1−/*
2− * lib/kernel_lock.c
3− *
4− * This is the traditional BKL - big kernel lock. Largely
5− * relegated to obsolescence, but used by various less
6− * important (or lazy) subsystems.
7− */
8−#include <linux/module.h>
9−#include <linux/kallsyms.h>
10−#include <linux/semaphore.h>
11−#include <linux/smp_lock.h>
12−
13−/*
14− * The 'big kernel lock'
15− *
16− * This spinlock is taken and released recursively by lock_kernel()
17− * and unlock_kernel(). It is transparently dropped and reacquired
18− * over schedule(). It is used to protect legacy code that hasn't
19− * been migrated to a proper locking design yet.
20− *
21− * Don't use in new code.
22− */
23−static __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(kernel_flag);
24−
25−
26−/*
27− * Acquire/release the underlying lock from the scheduler.
28− *
29− * This is called with preemption disabled, and should
30− * return an error value if it cannot get the lock and
31− * TIF_NEED_RESCHED gets set.
32− *
33− * If it successfully gets the lock, it should increment
34− * the preemption count like any spinlock does.
35− *
36− * (This works on UP too - do_raw_spin_trylock will never
37− * return false in that case)
38− */
39−int __lockfunc __reacquire_kernel_lock(void)
40−{
41− while (!do_raw_spin_trylock(&kernel_flag)) {
42− if (need_resched())
43− return -EAGAIN;
44− cpu_relax();
45− }
46− preempt_disable();
47− return 0;
48−}
49−
50−void __lockfunc __release_kernel_lock(void)
51−{
52− do_raw_spin_unlock(&kernel_flag);
53− preempt_enable_no_resched();
54−}
55−
56−/*
57− * These are the BKL spinlocks - we try to be polite about preemption.
58− * If SMP is not on (ie UP preemption), this all goes away because the
59− * do_raw_spin_trylock() will always succeed.
60− */
61−#ifdef CONFIG_PREEMPT
62−static inline void __lock_kernel(void)
63−{
64− preempt_disable();
65− if (unlikely(!do_raw_spin_trylock(&kernel_flag))) {
66− /*
67− * If preemption was disabled even before this
68− * was called, there's nothing we can be polite
69− * about - just spin.
70− */
71− if (preempt_count() > 1) {
72− do_raw_spin_lock(&kernel_flag);
73− return;
74− }
75−
76− /*
77− * Otherwise, let's wait for the kernel lock
78− * with preemption enabled..
79− */
80− do {
81− preempt_enable();
82− while (raw_spin_is_locked(&kernel_flag))
83− cpu_relax();
84− preempt_disable();
85− } while (!do_raw_spin_trylock(&kernel_flag));
86− }
87−}
88−
89−#else
90−
91−/*
92− * Non-preemption case - just get the spinlock
93− */
94−static inline void __lock_kernel(void)
95−{
96− do_raw_spin_lock(&kernel_flag);
97−}
98−#endif
99−
100−static inline void __unlock_kernel(void)
101−{
102− /*
103− * the BKL is not covered by lockdep, so we open-code the
104− * unlocking sequence (and thus avoid the dep-chain ops):
105− */
106− do_raw_spin_unlock(&kernel_flag);
107− preempt_enable();
108−}
109−
110−/*
111− * Getting the big kernel lock.
112− *
113− * This cannot happen asynchronously, so we only need to
114− * worry about other CPU's.
115− */
116−void __lockfunc _lock_kernel(const char *func, const char *file, int line)
117−{
118− int depth = current->lock_depth + 1;
119−
120− if (likely(!depth)) {
121− might_sleep();
122− __lock_kernel();
123− }
124− current->lock_depth = depth;
125−}
126−
127−void __lockfunc _unlock_kernel(const char *func, const char *file, int line)
128−{
129− BUG_ON(current->lock_depth < 0);
130− if (likely(--current->lock_depth < 0))
131− __unlock_kernel();
132−}
133−
134−EXPORT_SYMBOL(_lock_kernel);
135−EXPORT_SYMBOL(_unlock_kernel);
136−

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t