diff options
-rw-r--r-- | fs/file_table.c | 1 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | include/linux/lglock.h | 125 | ||||
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/lglock.c | 89 |
5 files changed, 117 insertions, 102 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index 70f2a0fd6aec..f5c67c59ec10 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -34,7 +34,6 @@ struct files_stat_struct files_stat = { | |||
34 | .max_files = NR_FILE | 34 | .max_files = NR_FILE |
35 | }; | 35 | }; |
36 | 36 | ||
37 | DECLARE_LGLOCK(files_lglock); | ||
38 | DEFINE_LGLOCK(files_lglock); | 37 | DEFINE_LGLOCK(files_lglock); |
39 | 38 | ||
40 | /* SLAB cache for file structures */ | 39 | /* SLAB cache for file structures */ |
diff --git a/fs/internal.h b/fs/internal.h index 9962c59ba280..8040af489c78 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -56,7 +56,7 @@ extern int sb_prepare_remount_readonly(struct super_block *); | |||
56 | 56 | ||
57 | extern void __init mnt_init(void); | 57 | extern void __init mnt_init(void); |
58 | 58 | ||
59 | DECLARE_BRLOCK(vfsmount_lock); | 59 | extern struct lglock vfsmount_lock; |
60 | 60 | ||
61 | 61 | ||
62 | /* | 62 | /* |
diff --git a/include/linux/lglock.h b/include/linux/lglock.h index 0fdd821e77b7..f01e5f6d1f07 100644 --- a/include/linux/lglock.h +++ b/include/linux/lglock.h | |||
@@ -23,26 +23,17 @@ | |||
23 | #include <linux/lockdep.h> | 23 | #include <linux/lockdep.h> |
24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
25 | #include <linux/cpu.h> | 25 | #include <linux/cpu.h> |
26 | #include <linux/notifier.h> | ||
26 | 27 | ||
27 | /* can make br locks by using local lock for read side, global lock for write */ | 28 | /* can make br locks by using local lock for read side, global lock for write */ |
28 | #define br_lock_init(name) name##_lock_init() | 29 | #define br_lock_init(name) lg_lock_init(name, #name) |
29 | #define br_read_lock(name) name##_local_lock() | 30 | #define br_read_lock(name) lg_local_lock(name) |
30 | #define br_read_unlock(name) name##_local_unlock() | 31 | #define br_read_unlock(name) lg_local_unlock(name) |
31 | #define br_write_lock(name) name##_global_lock() | 32 | #define br_write_lock(name) lg_global_lock(name) |
32 | #define br_write_unlock(name) name##_global_unlock() | 33 | #define br_write_unlock(name) lg_global_unlock(name) |
33 | 34 | ||
34 | #define DECLARE_BRLOCK(name) DECLARE_LGLOCK(name) | ||
35 | #define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) | 35 | #define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) |
36 | 36 | ||
37 | |||
38 | #define lg_lock_init(name) name##_lock_init() | ||
39 | #define lg_local_lock(name) name##_local_lock() | ||
40 | #define lg_local_unlock(name) name##_local_unlock() | ||
41 | #define lg_local_lock_cpu(name, cpu) name##_local_lock_cpu(cpu) | ||
42 | #define lg_local_unlock_cpu(name, cpu) name##_local_unlock_cpu(cpu) | ||
43 | #define lg_global_lock(name) name##_global_lock() | ||
44 | #define lg_global_unlock(name) name##_global_unlock() | ||
45 | |||
46 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 37 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
47 | #define LOCKDEP_INIT_MAP lockdep_init_map | 38 | #define LOCKDEP_INIT_MAP lockdep_init_map |
48 | 39 | ||
@@ -57,90 +48,26 @@ | |||
57 | #define DEFINE_LGLOCK_LOCKDEP(name) | 48 | #define DEFINE_LGLOCK_LOCKDEP(name) |
58 | #endif | 49 | #endif |
59 | 50 | ||
60 | 51 | struct lglock { | |
61 | #define DECLARE_LGLOCK(name) \ | 52 | arch_spinlock_t __percpu *lock; |
62 | extern void name##_lock_init(void); \ | 53 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
63 | extern void name##_local_lock(void); \ | 54 | struct lock_class_key lock_key; |
64 | extern void name##_local_unlock(void); \ | 55 | struct lockdep_map lock_dep_map; |
65 | extern void name##_local_lock_cpu(int cpu); \ | 56 | #endif |
66 | extern void name##_local_unlock_cpu(int cpu); \ | 57 | }; |
67 | extern void name##_global_lock(void); \ | ||
68 | extern void name##_global_unlock(void); \ | ||
69 | 58 | ||
70 | #define DEFINE_LGLOCK(name) \ | 59 | #define DEFINE_LGLOCK(name) \ |
71 | \ | 60 | DEFINE_LGLOCK_LOCKDEP(name); \ |
72 | DEFINE_SPINLOCK(name##_cpu_lock); \ | 61 | DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \ |
73 | DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \ | 62 | = __ARCH_SPIN_LOCK_UNLOCKED; \ |
74 | DEFINE_LGLOCK_LOCKDEP(name); \ | 63 | struct lglock name = { .lock = &name ## _lock } |
75 | \ | 64 | |
76 | void name##_lock_init(void) { \ | 65 | void lg_lock_init(struct lglock *lg, char *name); |
77 | int i; \ | 66 | void lg_local_lock(struct lglock *lg); |
78 | LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \ | 67 | void lg_local_unlock(struct lglock *lg); |
79 | for_each_possible_cpu(i) { \ | 68 | void lg_local_lock_cpu(struct lglock *lg, int cpu); |
80 | arch_spinlock_t *lock; \ | 69 | void lg_local_unlock_cpu(struct lglock *lg, int cpu); |
81 | lock = &per_cpu(name##_lock, i); \ | 70 | void lg_global_lock(struct lglock *lg); |
82 | *lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \ | 71 | void lg_global_unlock(struct lglock *lg); |
83 | } \ | 72 | |
84 | } \ | ||
85 | EXPORT_SYMBOL(name##_lock_init); \ | ||
86 | \ | ||
87 | void name##_local_lock(void) { \ | ||
88 | arch_spinlock_t *lock; \ | ||
89 | preempt_disable(); \ | ||
90 | rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ | ||
91 | lock = &__get_cpu_var(name##_lock); \ | ||
92 | arch_spin_lock(lock); \ | ||
93 | } \ | ||
94 | EXPORT_SYMBOL(name##_local_lock); \ | ||
95 | \ | ||
96 | void name##_local_unlock(void) { \ | ||
97 | arch_spinlock_t *lock; \ | ||
98 | rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ | ||
99 | lock = &__get_cpu_var(name##_lock); \ | ||
100 | arch_spin_unlock(lock); \ | ||
101 | preempt_enable(); \ | ||
102 | } \ | ||
103 | EXPORT_SYMBOL(name##_local_unlock); \ | ||
104 | \ | ||
105 | void name##_local_lock_cpu(int cpu) { \ | ||
106 | arch_spinlock_t *lock; \ | ||
107 | preempt_disable(); \ | ||
108 | rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ | ||
109 | lock = &per_cpu(name##_lock, cpu); \ | ||
110 | arch_spin_lock(lock); \ | ||
111 | } \ | ||
112 | EXPORT_SYMBOL(name##_local_lock_cpu); \ | ||
113 | \ | ||
114 | void name##_local_unlock_cpu(int cpu) { \ | ||
115 | arch_spinlock_t *lock; \ | ||
116 | rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ | ||
117 | lock = &per_cpu(name##_lock, cpu); \ | ||
118 | arch_spin_unlock(lock); \ | ||
119 | preempt_enable(); \ | ||
120 | } \ | ||
121 | EXPORT_SYMBOL(name##_local_unlock_cpu); \ | ||
122 | \ | ||
123 | void name##_global_lock(void) { \ | ||
124 | int i; \ | ||
125 | preempt_disable(); \ | ||
126 | rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ | ||
127 | for_each_possible_cpu(i) { \ | ||
128 | arch_spinlock_t *lock; \ | ||
129 | lock = &per_cpu(name##_lock, i); \ | ||
130 | arch_spin_lock(lock); \ | ||
131 | } \ | ||
132 | } \ | ||
133 | EXPORT_SYMBOL(name##_global_lock); \ | ||
134 | \ | ||
135 | void name##_global_unlock(void) { \ | ||
136 | int i; \ | ||
137 | rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ | ||
138 | for_each_possible_cpu(i) { \ | ||
139 | arch_spinlock_t *lock; \ | ||
140 | lock = &per_cpu(name##_lock, i); \ | ||
141 | arch_spin_unlock(lock); \ | ||
142 | } \ | ||
143 | preempt_enable(); \ | ||
144 | } \ | ||
145 | EXPORT_SYMBOL(name##_global_unlock); | ||
146 | #endif | 73 | #endif |
diff --git a/kernel/Makefile b/kernel/Makefile index 6c07f30fa9b7..296132c19a57 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o printk.o \ | |||
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
12 | notifier.o ksysfs.o cred.o \ | 12 | notifier.o ksysfs.o cred.o \ |
13 | async.o range.o groups.o | 13 | async.o range.o groups.o lglock.o |
14 | 14 | ||
15 | ifdef CONFIG_FUNCTION_TRACER | 15 | ifdef CONFIG_FUNCTION_TRACER |
16 | # Do not trace debug files and internal ftrace files | 16 | # Do not trace debug files and internal ftrace files |
diff --git a/kernel/lglock.c b/kernel/lglock.c new file mode 100644 index 000000000000..6535a667a5a7 --- /dev/null +++ b/kernel/lglock.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* See include/linux/lglock.h for description */ | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/lglock.h> | ||
4 | #include <linux/cpu.h> | ||
5 | #include <linux/string.h> | ||
6 | |||
7 | /* | ||
8 | * Note there is no uninit, so lglocks cannot be defined in | ||
9 | * modules (but it's fine to use them from there) | ||
10 | * Could be added though, just undo lg_lock_init | ||
11 | */ | ||
12 | |||
13 | void lg_lock_init(struct lglock *lg, char *name) | ||
14 | { | ||
15 | LOCKDEP_INIT_MAP(&lg->lock_dep_map, name, &lg->lock_key, 0); | ||
16 | } | ||
17 | EXPORT_SYMBOL(lg_lock_init); | ||
18 | |||
19 | void lg_local_lock(struct lglock *lg) | ||
20 | { | ||
21 | arch_spinlock_t *lock; | ||
22 | |||
23 | preempt_disable(); | ||
24 | rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
25 | lock = this_cpu_ptr(lg->lock); | ||
26 | arch_spin_lock(lock); | ||
27 | } | ||
28 | EXPORT_SYMBOL(lg_local_lock); | ||
29 | |||
30 | void lg_local_unlock(struct lglock *lg) | ||
31 | { | ||
32 | arch_spinlock_t *lock; | ||
33 | |||
34 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
35 | lock = this_cpu_ptr(lg->lock); | ||
36 | arch_spin_unlock(lock); | ||
37 | preempt_enable(); | ||
38 | } | ||
39 | EXPORT_SYMBOL(lg_local_unlock); | ||
40 | |||
41 | void lg_local_lock_cpu(struct lglock *lg, int cpu) | ||
42 | { | ||
43 | arch_spinlock_t *lock; | ||
44 | |||
45 | preempt_disable(); | ||
46 | rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
47 | lock = per_cpu_ptr(lg->lock, cpu); | ||
48 | arch_spin_lock(lock); | ||
49 | } | ||
50 | EXPORT_SYMBOL(lg_local_lock_cpu); | ||
51 | |||
52 | void lg_local_unlock_cpu(struct lglock *lg, int cpu) | ||
53 | { | ||
54 | arch_spinlock_t *lock; | ||
55 | |||
56 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
57 | lock = per_cpu_ptr(lg->lock, cpu); | ||
58 | arch_spin_unlock(lock); | ||
59 | preempt_enable(); | ||
60 | } | ||
61 | EXPORT_SYMBOL(lg_local_unlock_cpu); | ||
62 | |||
63 | void lg_global_lock(struct lglock *lg) | ||
64 | { | ||
65 | int i; | ||
66 | |||
67 | preempt_disable(); | ||
68 | rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
69 | for_each_possible_cpu(i) { | ||
70 | arch_spinlock_t *lock; | ||
71 | lock = per_cpu_ptr(lg->lock, i); | ||
72 | arch_spin_lock(lock); | ||
73 | } | ||
74 | } | ||
75 | EXPORT_SYMBOL(lg_global_lock); | ||
76 | |||
77 | void lg_global_unlock(struct lglock *lg) | ||
78 | { | ||
79 | int i; | ||
80 | |||
81 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
82 | for_each_possible_cpu(i) { | ||
83 | arch_spinlock_t *lock; | ||
84 | lock = per_cpu_ptr(lg->lock, i); | ||
85 | arch_spin_unlock(lock); | ||
86 | } | ||
87 | preempt_enable(); | ||
88 | } | ||
89 | EXPORT_SYMBOL(lg_global_unlock); | ||