diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 13:23:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 13:23:08 -0500 |
commit | 6ffbe7d1fabddc768724656f159759cae7818cd9 (patch) | |
tree | ece184db0c35bcd9606968303984b430c24b847f /tools | |
parent | 897aea303fec0c24b2a21b8e29f45dc73a234555 (diff) | |
parent | 63b1a81699c2a45c9f737419b1ec1da0ecf92812 (diff) |
Merge branch 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core locking changes from Ingo Molnar:
- futex performance increases: larger hashes, smarter wakeups
- mutex debugging improvements
- lots of SMP ordering documentation updates
- introduce the smp_load_acquire(), smp_store_release() primitives.
(There are WIP patches that make use of them - not yet merged)
- lockdep micro-optimizations
- lockdep improvement: better cover IRQ contexts
- liblockdep at last. We'll continue to monitor how useful this is
* 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits)
futexes: Fix futex_hashsize initialization
arch: Re-sort some Kbuild files to hopefully help avoid some conflicts
futexes: Avoid taking the hb->lock if there's nothing to wake up
futexes: Document multiprocessor ordering guarantees
futexes: Increase hash table size for better performance
futexes: Clean up various details
arch: Introduce smp_load_acquire(), smp_store_release()
arch: Clean up asm/barrier.h implementations using asm-generic/barrier.h
arch: Move smp_mb__{before,after}_atomic_{inc,dec}.h into asm/atomic.h
locking/doc: Rename LOCK/UNLOCK to ACQUIRE/RELEASE
mutexes: Give more informative mutex warning in the !lock->owner case
powerpc: Full barrier for smp_mb__after_unlock_lock()
rcu: Apply smp_mb__after_unlock_lock() to preserve grace periods
Documentation/memory-barriers.txt: Downgrade UNLOCK+BLOCK
locking: Add an smp_mb__after_unlock_lock() for UNLOCK+BLOCK barrier
Documentation/memory-barriers.txt: Document ACCESS_ONCE()
Documentation/memory-barriers.txt: Prohibit speculative writes
Documentation/memory-barriers.txt: Add long atomic examples to memory-barriers.txt
Documentation/memory-barriers.txt: Add needed ACCESS_ONCE() calls to memory-barriers.txt
Revert "smp/cpumask: Make CONFIG_CPUMASK_OFFSTACK=y usable without debug dependency"
...
Diffstat (limited to 'tools')
56 files changed, 1547 insertions, 0 deletions
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile new file mode 100644 index 000000000000..da8b7aa3d351 --- /dev/null +++ b/tools/lib/lockdep/Makefile | |||
@@ -0,0 +1,251 @@ | |||
1 | # liblockdep version | ||
2 | LL_VERSION = 0 | ||
3 | LL_PATCHLEVEL = 0 | ||
4 | LL_EXTRAVERSION = 1 | ||
5 | |||
6 | # file format version | ||
7 | FILE_VERSION = 1 | ||
8 | |||
9 | MAKEFLAGS += --no-print-directory | ||
10 | |||
11 | |||
12 | # Makefiles suck: This macro sets a default value of $(2) for the | ||
13 | # variable named by $(1), unless the variable has been set by | ||
14 | # environment or command line. This is necessary for CC and AR | ||
15 | # because make sets default values, so the simpler ?= approach | ||
16 | # won't work as expected. | ||
17 | define allow-override | ||
18 | $(if $(or $(findstring environment,$(origin $(1))),\ | ||
19 | $(findstring command line,$(origin $(1)))),,\ | ||
20 | $(eval $(1) = $(2))) | ||
21 | endef | ||
22 | |||
23 | # Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. | ||
24 | $(call allow-override,CC,$(CROSS_COMPILE)gcc) | ||
25 | $(call allow-override,AR,$(CROSS_COMPILE)ar) | ||
26 | |||
27 | INSTALL = install | ||
28 | |||
29 | # Use DESTDIR for installing into a different root directory. | ||
30 | # This is useful for building a package. The program will be | ||
31 | # installed in this directory as if it was the root directory. | ||
32 | # Then the build tool can move it later. | ||
33 | DESTDIR ?= | ||
34 | DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' | ||
35 | |||
36 | prefix ?= /usr/local | ||
37 | libdir_relative = lib | ||
38 | libdir = $(prefix)/$(libdir_relative) | ||
39 | bindir_relative = bin | ||
40 | bindir = $(prefix)/$(bindir_relative) | ||
41 | |||
42 | export DESTDIR DESTDIR_SQ INSTALL | ||
43 | |||
44 | # copy a bit from Linux kbuild | ||
45 | |||
46 | ifeq ("$(origin V)", "command line") | ||
47 | VERBOSE = $(V) | ||
48 | endif | ||
49 | ifndef VERBOSE | ||
50 | VERBOSE = 0 | ||
51 | endif | ||
52 | |||
53 | ifeq ("$(origin O)", "command line") | ||
54 | BUILD_OUTPUT := $(O) | ||
55 | endif | ||
56 | |||
57 | ifeq ($(BUILD_SRC),) | ||
58 | ifneq ($(BUILD_OUTPUT),) | ||
59 | |||
60 | define build_output | ||
61 | $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \ | ||
62 | BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 | ||
63 | endef | ||
64 | |||
65 | saved-output := $(BUILD_OUTPUT) | ||
66 | BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd) | ||
67 | $(if $(BUILD_OUTPUT),, \ | ||
68 | $(error output directory "$(saved-output)" does not exist)) | ||
69 | |||
70 | all: sub-make | ||
71 | |||
72 | gui: force | ||
73 | $(call build_output, all_cmd) | ||
74 | |||
75 | $(filter-out gui,$(MAKECMDGOALS)): sub-make | ||
76 | |||
77 | sub-make: force | ||
78 | $(call build_output, $(MAKECMDGOALS)) | ||
79 | |||
80 | |||
81 | # Leave processing to above invocation of make | ||
82 | skip-makefile := 1 | ||
83 | |||
84 | endif # BUILD_OUTPUT | ||
85 | endif # BUILD_SRC | ||
86 | |||
87 | # We process the rest of the Makefile if this is the final invocation of make | ||
88 | ifeq ($(skip-makefile),) | ||
89 | |||
90 | srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)) | ||
91 | objtree := $(CURDIR) | ||
92 | src := $(srctree) | ||
93 | obj := $(objtree) | ||
94 | |||
95 | export prefix libdir bindir src obj | ||
96 | |||
97 | # Shell quotes | ||
98 | libdir_SQ = $(subst ','\'',$(libdir)) | ||
99 | bindir_SQ = $(subst ','\'',$(bindir)) | ||
100 | |||
101 | LIB_FILE = liblockdep.a liblockdep.so | ||
102 | BIN_FILE = lockdep | ||
103 | |||
104 | CONFIG_INCLUDES = | ||
105 | CONFIG_LIBS = | ||
106 | CONFIG_FLAGS = | ||
107 | |||
108 | OBJ = $@ | ||
109 | N = | ||
110 | |||
111 | export Q VERBOSE | ||
112 | |||
113 | LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION) | ||
114 | |||
115 | INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES) | ||
116 | |||
117 | # Set compile option CFLAGS if not set elsewhere | ||
118 | CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g | ||
119 | |||
120 | override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) | ||
121 | |||
122 | ifeq ($(VERBOSE),1) | ||
123 | Q = | ||
124 | print_compile = | ||
125 | print_app_build = | ||
126 | print_fpic_compile = | ||
127 | print_shared_lib_compile = | ||
128 | print_install = | ||
129 | else | ||
130 | Q = @ | ||
131 | print_compile = echo ' CC '$(OBJ); | ||
132 | print_app_build = echo ' BUILD '$(OBJ); | ||
133 | print_fpic_compile = echo ' CC FPIC '$(OBJ); | ||
134 | print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); | ||
135 | print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); | ||
136 | print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; | ||
137 | endif | ||
138 | |||
139 | do_fpic_compile = \ | ||
140 | ($(print_fpic_compile) \ | ||
141 | $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) | ||
142 | |||
143 | do_app_build = \ | ||
144 | ($(print_app_build) \ | ||
145 | $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)) | ||
146 | |||
147 | do_compile_shared_library = \ | ||
148 | ($(print_shared_lib_compile) \ | ||
149 | $(CC) --shared $^ -o $@ -lpthread -ldl) | ||
150 | |||
151 | do_build_static_lib = \ | ||
152 | ($(print_static_lib_build) \ | ||
153 | $(RM) $@; $(AR) rcs $@ $^) | ||
154 | |||
155 | |||
156 | define do_compile | ||
157 | $(print_compile) \ | ||
158 | $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; | ||
159 | endef | ||
160 | |||
161 | $(obj)/%.o: $(src)/%.c | ||
162 | $(Q)$(call do_compile) | ||
163 | |||
164 | %.o: $(src)/%.c | ||
165 | $(Q)$(call do_compile) | ||
166 | |||
167 | PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o | ||
168 | |||
169 | ALL_OBJS = $(PEVENT_LIB_OBJS) | ||
170 | |||
171 | CMD_TARGETS = $(LIB_FILE) | ||
172 | |||
173 | TARGETS = $(CMD_TARGETS) | ||
174 | |||
175 | |||
176 | all: all_cmd | ||
177 | |||
178 | all_cmd: $(CMD_TARGETS) | ||
179 | |||
180 | liblockdep.so: $(PEVENT_LIB_OBJS) | ||
181 | $(Q)$(do_compile_shared_library) | ||
182 | |||
183 | liblockdep.a: $(PEVENT_LIB_OBJS) | ||
184 | $(Q)$(do_build_static_lib) | ||
185 | |||
186 | $(PEVENT_LIB_OBJS): %.o: $(src)/%.c | ||
187 | $(Q)$(do_fpic_compile) | ||
188 | |||
189 | ## make deps | ||
190 | |||
191 | all_objs := $(sort $(ALL_OBJS)) | ||
192 | all_deps := $(all_objs:%.o=.%.d) | ||
193 | |||
194 | # let .d file also depends on the source and header files | ||
195 | define check_deps | ||
196 | @set -e; $(RM) $@; \ | ||
197 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ | ||
198 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | ||
199 | $(RM) $@.$$$$ | ||
200 | endef | ||
201 | |||
202 | $(all_deps): .%.d: $(src)/%.c | ||
203 | $(Q)$(call check_deps) | ||
204 | |||
205 | $(all_objs) : %.o : .%.d | ||
206 | |||
207 | dep_includes := $(wildcard $(all_deps)) | ||
208 | |||
209 | ifneq ($(dep_includes),) | ||
210 | include $(dep_includes) | ||
211 | endif | ||
212 | |||
213 | ### Detect environment changes | ||
214 | TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE) | ||
215 | |||
216 | tags: force | ||
217 | $(RM) tags | ||
218 | find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ | ||
219 | --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' | ||
220 | |||
221 | TAGS: force | ||
222 | $(RM) TAGS | ||
223 | find . -name '*.[ch]' | xargs etags \ | ||
224 | --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' | ||
225 | |||
226 | define do_install | ||
227 | $(print_install) \ | ||
228 | if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ | ||
229 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ | ||
230 | fi; \ | ||
231 | $(INSTALL) $1 '$(DESTDIR_SQ)$2' | ||
232 | endef | ||
233 | |||
234 | install_lib: all_cmd | ||
235 | $(Q)$(call do_install,$(LIB_FILE),$(libdir_SQ)) | ||
236 | $(Q)$(call do_install,$(BIN_FILE),$(bindir_SQ)) | ||
237 | |||
238 | install: install_lib | ||
239 | |||
240 | clean: | ||
241 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d | ||
242 | $(RM) tags TAGS | ||
243 | |||
244 | endif # skip-makefile | ||
245 | |||
246 | PHONY += force | ||
247 | force: | ||
248 | |||
249 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
250 | # information in a variable so we can use it in if_changed and friends. | ||
251 | .PHONY: $(PHONY) | ||
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c new file mode 100644 index 000000000000..8ef602f18a32 --- /dev/null +++ b/tools/lib/lockdep/common.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <stddef.h> | ||
2 | #include <stdbool.h> | ||
3 | #include <linux/compiler.h> | ||
4 | #include <linux/lockdep.h> | ||
5 | #include <unistd.h> | ||
6 | #include <sys/syscall.h> | ||
7 | |||
8 | static __thread struct task_struct current_obj; | ||
9 | |||
10 | /* lockdep wants these */ | ||
11 | bool debug_locks = true; | ||
12 | bool debug_locks_silent; | ||
13 | |||
14 | __attribute__((constructor)) static void liblockdep_init(void) | ||
15 | { | ||
16 | lockdep_init(); | ||
17 | } | ||
18 | |||
19 | __attribute__((destructor)) static void liblockdep_exit(void) | ||
20 | { | ||
21 | debug_check_no_locks_held(¤t_obj); | ||
22 | } | ||
23 | |||
24 | struct task_struct *__curr(void) | ||
25 | { | ||
26 | if (current_obj.pid == 0) { | ||
27 | /* Makes lockdep output pretty */ | ||
28 | prctl(PR_GET_NAME, current_obj.comm); | ||
29 | current_obj.pid = syscall(__NR_gettid); | ||
30 | } | ||
31 | |||
32 | return ¤t_obj; | ||
33 | } | ||
diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h new file mode 100644 index 000000000000..0bda630027c3 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/common.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef _LIBLOCKDEP_COMMON_H | ||
2 | #define _LIBLOCKDEP_COMMON_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | |||
6 | #define NR_LOCKDEP_CACHING_CLASSES 2 | ||
7 | #define MAX_LOCKDEP_SUBCLASSES 8UL | ||
8 | |||
9 | #ifndef CALLER_ADDR0 | ||
10 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | ||
11 | #endif | ||
12 | |||
13 | #ifndef _RET_IP_ | ||
14 | #define _RET_IP_ CALLER_ADDR0 | ||
15 | #endif | ||
16 | |||
17 | #ifndef _THIS_IP_ | ||
18 | #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) | ||
19 | #endif | ||
20 | |||
21 | struct lockdep_subclass_key { | ||
22 | char __one_byte; | ||
23 | }; | ||
24 | |||
25 | struct lock_class_key { | ||
26 | struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; | ||
27 | }; | ||
28 | |||
29 | struct lockdep_map { | ||
30 | struct lock_class_key *key; | ||
31 | struct lock_class *class_cache[NR_LOCKDEP_CACHING_CLASSES]; | ||
32 | const char *name; | ||
33 | #ifdef CONFIG_LOCK_STAT | ||
34 | int cpu; | ||
35 | unsigned long ip; | ||
36 | #endif | ||
37 | }; | ||
38 | |||
39 | void lockdep_init_map(struct lockdep_map *lock, const char *name, | ||
40 | struct lock_class_key *key, int subclass); | ||
41 | void lock_acquire(struct lockdep_map *lock, unsigned int subclass, | ||
42 | int trylock, int read, int check, | ||
43 | struct lockdep_map *nest_lock, unsigned long ip); | ||
44 | void lock_release(struct lockdep_map *lock, int nested, | ||
45 | unsigned long ip); | ||
46 | |||
47 | #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \ | ||
48 | { .name = (_name), .key = (void *)(_key), } | ||
49 | |||
50 | #endif | ||
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h new file mode 100644 index 000000000000..c342f7087147 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/mutex.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef _LIBLOCKDEP_MUTEX_H | ||
2 | #define _LIBLOCKDEP_MUTEX_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include "common.h" | ||
6 | |||
7 | struct liblockdep_pthread_mutex { | ||
8 | pthread_mutex_t mutex; | ||
9 | struct lockdep_map dep_map; | ||
10 | }; | ||
11 | |||
12 | typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t; | ||
13 | |||
14 | #define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx) \ | ||
15 | (const struct liblockdep_pthread_mutex) { \ | ||
16 | .mutex = PTHREAD_MUTEX_INITIALIZER, \ | ||
17 | .dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)), \ | ||
18 | } | ||
19 | |||
20 | static inline int __mutex_init(liblockdep_pthread_mutex_t *lock, | ||
21 | const char *name, | ||
22 | struct lock_class_key *key, | ||
23 | const pthread_mutexattr_t *__mutexattr) | ||
24 | { | ||
25 | lockdep_init_map(&lock->dep_map, name, key, 0); | ||
26 | return pthread_mutex_init(&lock->mutex, __mutexattr); | ||
27 | } | ||
28 | |||
29 | #define liblockdep_pthread_mutex_init(mutex, mutexattr) \ | ||
30 | ({ \ | ||
31 | static struct lock_class_key __key; \ | ||
32 | \ | ||
33 | __mutex_init((mutex), #mutex, &__key, (mutexattr)); \ | ||
34 | }) | ||
35 | |||
36 | static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock) | ||
37 | { | ||
38 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
39 | return pthread_mutex_lock(&lock->mutex); | ||
40 | } | ||
41 | |||
42 | static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock) | ||
43 | { | ||
44 | lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_); | ||
45 | return pthread_mutex_unlock(&lock->mutex); | ||
46 | } | ||
47 | |||
48 | static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock) | ||
49 | { | ||
50 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
51 | return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0; | ||
52 | } | ||
53 | |||
54 | static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock) | ||
55 | { | ||
56 | return pthread_mutex_destroy(&lock->mutex); | ||
57 | } | ||
58 | |||
59 | #ifdef __USE_LIBLOCKDEP | ||
60 | |||
61 | #define pthread_mutex_t liblockdep_pthread_mutex_t | ||
62 | #define pthread_mutex_init liblockdep_pthread_mutex_init | ||
63 | #define pthread_mutex_lock liblockdep_pthread_mutex_lock | ||
64 | #define pthread_mutex_unlock liblockdep_pthread_mutex_unlock | ||
65 | #define pthread_mutex_trylock liblockdep_pthread_mutex_trylock | ||
66 | #define pthread_mutex_destroy liblockdep_pthread_mutex_destroy | ||
67 | |||
68 | #endif | ||
69 | |||
70 | #endif | ||
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h new file mode 100644 index 000000000000..a680ab8c2e36 --- /dev/null +++ b/tools/lib/lockdep/include/liblockdep/rwlock.h | |||
@@ -0,0 +1,86 @@ | |||
1 | #ifndef _LIBLOCKDEP_RWLOCK_H | ||
2 | #define _LIBLOCKDEP_RWLOCK_H | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include "common.h" | ||
6 | |||
7 | struct liblockdep_pthread_rwlock { | ||
8 | pthread_rwlock_t rwlock; | ||
9 | struct lockdep_map dep_map; | ||
10 | }; | ||
11 | |||
12 | typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t; | ||
13 | |||
14 | #define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl) \ | ||
15 | (struct liblockdep_pthread_rwlock) { \ | ||
16 | .rwlock = PTHREAD_RWLOCK_INITIALIZER, \ | ||
17 | .dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)), \ | ||
18 | } | ||
19 | |||
20 | static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock, | ||
21 | const char *name, | ||
22 | struct lock_class_key *key, | ||
23 | const pthread_rwlockattr_t *attr) | ||
24 | { | ||
25 | lockdep_init_map(&lock->dep_map, name, key, 0); | ||
26 | |||
27 | return pthread_rwlock_init(&lock->rwlock, attr); | ||
28 | } | ||
29 | |||
30 | #define liblockdep_pthread_rwlock_init(lock, attr) \ | ||
31 | ({ \ | ||
32 | static struct lock_class_key __key; \ | ||
33 | \ | ||
34 | __rwlock_init((lock), #lock, &__key, (attr)); \ | ||
35 | }) | ||
36 | |||
37 | static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock) | ||
38 | { | ||
39 | lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
40 | return pthread_rwlock_rdlock(&lock->rwlock); | ||
41 | |||
42 | } | ||
43 | |||
44 | static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock) | ||
45 | { | ||
46 | lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_); | ||
47 | return pthread_rwlock_unlock(&lock->rwlock); | ||
48 | } | ||
49 | |||
50 | static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock) | ||
51 | { | ||
52 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
53 | return pthread_rwlock_wrlock(&lock->rwlock); | ||
54 | } | ||
55 | |||
56 | static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock) | ||
57 | { | ||
58 | lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
59 | return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0; | ||
60 | } | ||
61 | |||
62 | static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock) | ||
63 | { | ||
64 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
65 | return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0; | ||
66 | } | ||
67 | |||
68 | static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock) | ||
69 | { | ||
70 | return pthread_rwlock_destroy(&lock->rwlock); | ||
71 | } | ||
72 | |||
73 | #ifdef __USE_LIBLOCKDEP | ||
74 | |||
75 | #define pthread_rwlock_t liblockdep_pthread_rwlock_t | ||
76 | #define pthread_rwlock_init liblockdep_pthread_rwlock_init | ||
77 | #define pthread_rwlock_rdlock liblockdep_pthread_rwlock_rdlock | ||
78 | #define pthread_rwlock_unlock liblockdep_pthread_rwlock_unlock | ||
79 | #define pthread_rwlock_wrlock liblockdep_pthread_rwlock_wrlock | ||
80 | #define pthread_rwlock_tryrdlock liblockdep_pthread_rwlock_tryrdlock | ||
81 | #define pthread_rwlock_trywlock liblockdep_pthread_rwlock_trywlock | ||
82 | #define pthread_rwlock_destroy liblockdep_rwlock_destroy | ||
83 | |||
84 | #endif | ||
85 | |||
86 | #endif | ||
diff --git a/tools/lib/lockdep/lockdep b/tools/lib/lockdep/lockdep new file mode 100755 index 000000000000..49af9fe19f5b --- /dev/null +++ b/tools/lib/lockdep/lockdep | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | LD_PRELOAD="./liblockdep.so $LD_PRELOAD" "$@" | ||
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c new file mode 100644 index 000000000000..f42b7e9aa48f --- /dev/null +++ b/tools/lib/lockdep/lockdep.c | |||
@@ -0,0 +1,2 @@ | |||
1 | #include <linux/lockdep.h> | ||
2 | #include "../../../kernel/locking/lockdep.c" | ||
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h new file mode 100644 index 000000000000..29d0c954cc24 --- /dev/null +++ b/tools/lib/lockdep/lockdep_internals.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../kernel/locking/lockdep_internals.h" | |||
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h new file mode 100644 index 000000000000..248d235efda9 --- /dev/null +++ b/tools/lib/lockdep/lockdep_states.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../kernel/locking/lockdep_states.h" | |||
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c new file mode 100644 index 000000000000..f8465a811aa5 --- /dev/null +++ b/tools/lib/lockdep/preload.c | |||
@@ -0,0 +1,447 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include <pthread.h> | ||
3 | #include <stdio.h> | ||
4 | #include <dlfcn.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <sysexits.h> | ||
7 | #include "include/liblockdep/mutex.h" | ||
8 | #include "../../../include/linux/rbtree.h" | ||
9 | |||
10 | /** | ||
11 | * struct lock_lookup - liblockdep's view of a single unique lock | ||
12 | * @orig: pointer to the original pthread lock, used for lookups | ||
13 | * @dep_map: lockdep's dep_map structure | ||
14 | * @key: lockdep's key structure | ||
15 | * @node: rb-tree node used to store the lock in a global tree | ||
16 | * @name: a unique name for the lock | ||
17 | */ | ||
18 | struct lock_lookup { | ||
19 | void *orig; /* Original pthread lock, used for lookups */ | ||
20 | struct lockdep_map dep_map; /* Since all locks are dynamic, we need | ||
21 | * a dep_map and a key for each lock */ | ||
22 | /* | ||
23 | * Wait, there's no support for key classes? Yup :( | ||
24 | * Most big projects wrap the pthread api with their own calls to | ||
25 | * be compatible with different locking methods. This means that | ||
26 | * "classes" will be brokes since the function that creates all | ||
27 | * locks will point to a generic locking function instead of the | ||
28 | * actual code that wants to do the locking. | ||
29 | */ | ||
30 | struct lock_class_key key; | ||
31 | struct rb_node node; | ||
32 | #define LIBLOCKDEP_MAX_LOCK_NAME 22 | ||
33 | char name[LIBLOCKDEP_MAX_LOCK_NAME]; | ||
34 | }; | ||
35 | |||
36 | /* This is where we store our locks */ | ||
37 | static struct rb_root locks = RB_ROOT; | ||
38 | static pthread_rwlock_t locks_rwlock = PTHREAD_RWLOCK_INITIALIZER; | ||
39 | |||
40 | /* pthread mutex API */ | ||
41 | |||
42 | #ifdef __GLIBC__ | ||
43 | extern int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); | ||
44 | extern int __pthread_mutex_lock(pthread_mutex_t *mutex); | ||
45 | extern int __pthread_mutex_trylock(pthread_mutex_t *mutex); | ||
46 | extern int __pthread_mutex_unlock(pthread_mutex_t *mutex); | ||
47 | extern int __pthread_mutex_destroy(pthread_mutex_t *mutex); | ||
48 | #else | ||
49 | #define __pthread_mutex_init NULL | ||
50 | #define __pthread_mutex_lock NULL | ||
51 | #define __pthread_mutex_trylock NULL | ||
52 | #define __pthread_mutex_unlock NULL | ||
53 | #define __pthread_mutex_destroy NULL | ||
54 | #endif | ||
55 | static int (*ll_pthread_mutex_init)(pthread_mutex_t *mutex, | ||
56 | const pthread_mutexattr_t *attr) = __pthread_mutex_init; | ||
57 | static int (*ll_pthread_mutex_lock)(pthread_mutex_t *mutex) = __pthread_mutex_lock; | ||
58 | static int (*ll_pthread_mutex_trylock)(pthread_mutex_t *mutex) = __pthread_mutex_trylock; | ||
59 | static int (*ll_pthread_mutex_unlock)(pthread_mutex_t *mutex) = __pthread_mutex_unlock; | ||
60 | static int (*ll_pthread_mutex_destroy)(pthread_mutex_t *mutex) = __pthread_mutex_destroy; | ||
61 | |||
62 | /* pthread rwlock API */ | ||
63 | |||
64 | #ifdef __GLIBC__ | ||
65 | extern int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); | ||
66 | extern int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock); | ||
67 | extern int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); | ||
68 | extern int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); | ||
69 | extern int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); | ||
70 | extern int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); | ||
71 | extern int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock); | ||
72 | #else | ||
73 | #define __pthread_rwlock_init NULL | ||
74 | #define __pthread_rwlock_destroy NULL | ||
75 | #define __pthread_rwlock_wrlock NULL | ||
76 | #define __pthread_rwlock_trywrlock NULL | ||
77 | #define __pthread_rwlock_rdlock NULL | ||
78 | #define __pthread_rwlock_tryrdlock NULL | ||
79 | #define __pthread_rwlock_unlock NULL | ||
80 | #endif | ||
81 | |||
82 | static int (*ll_pthread_rwlock_init)(pthread_rwlock_t *rwlock, | ||
83 | const pthread_rwlockattr_t *attr) = __pthread_rwlock_init; | ||
84 | static int (*ll_pthread_rwlock_destroy)(pthread_rwlock_t *rwlock) = __pthread_rwlock_destroy; | ||
85 | static int (*ll_pthread_rwlock_rdlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_rdlock; | ||
86 | static int (*ll_pthread_rwlock_tryrdlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_tryrdlock; | ||
87 | static int (*ll_pthread_rwlock_trywrlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_trywrlock; | ||
88 | static int (*ll_pthread_rwlock_wrlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_wrlock; | ||
89 | static int (*ll_pthread_rwlock_unlock)(pthread_rwlock_t *rwlock) = __pthread_rwlock_unlock; | ||
90 | |||
91 | enum { none, prepare, done, } __init_state; | ||
92 | static void init_preload(void); | ||
93 | static void try_init_preload(void) | ||
94 | { | ||
95 | if (!__init_state != done) | ||
96 | init_preload(); | ||
97 | } | ||
98 | |||
99 | static struct rb_node **__get_lock_node(void *lock, struct rb_node **parent) | ||
100 | { | ||
101 | struct rb_node **node = &locks.rb_node; | ||
102 | struct lock_lookup *l; | ||
103 | |||
104 | *parent = NULL; | ||
105 | |||
106 | while (*node) { | ||
107 | l = rb_entry(*node, struct lock_lookup, node); | ||
108 | |||
109 | *parent = *node; | ||
110 | if (lock < l->orig) | ||
111 | node = &l->node.rb_left; | ||
112 | else if (lock > l->orig) | ||
113 | node = &l->node.rb_right; | ||
114 | else | ||
115 | return node; | ||
116 | } | ||
117 | |||
118 | return node; | ||
119 | } | ||
120 | |||
121 | #ifndef LIBLOCKDEP_STATIC_ENTRIES | ||
122 | #define LIBLOCKDEP_STATIC_ENTRIES 1024 | ||
123 | #endif | ||
124 | |||
125 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
126 | |||
127 | static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES]; | ||
128 | static int __locks_nr; | ||
129 | |||
130 | static inline bool is_static_lock(struct lock_lookup *lock) | ||
131 | { | ||
132 | return lock >= __locks && lock < __locks + ARRAY_SIZE(__locks); | ||
133 | } | ||
134 | |||
135 | static struct lock_lookup *alloc_lock(void) | ||
136 | { | ||
137 | if (__init_state != done) { | ||
138 | /* | ||
139 | * Some programs attempt to initialize and use locks in their | ||
140 | * allocation path. This means that a call to malloc() would | ||
141 | * result in locks being initialized and locked. | ||
142 | * | ||
143 | * Why is it an issue for us? dlsym() below will try allocating | ||
144 | * to give us the original function. Since this allocation will | ||
145 | * result in a locking operations, we have to let pthread deal | ||
146 | * with it, but we can't! we don't have the pointer to the | ||
147 | * original API since we're inside dlsym() trying to get it | ||
148 | */ | ||
149 | |||
150 | int idx = __locks_nr++; | ||
151 | if (idx >= ARRAY_SIZE(__locks)) { | ||
152 | fprintf(stderr, | ||
153 | "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n"); | ||
154 | exit(EX_UNAVAILABLE); | ||
155 | } | ||
156 | return __locks + idx; | ||
157 | } | ||
158 | |||
159 | return malloc(sizeof(struct lock_lookup)); | ||
160 | } | ||
161 | |||
162 | static inline void free_lock(struct lock_lookup *lock) | ||
163 | { | ||
164 | if (likely(!is_static_lock(lock))) | ||
165 | free(lock); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * __get_lock - find or create a lock instance | ||
170 | * @lock: pointer to a pthread lock function | ||
171 | * | ||
172 | * Try to find an existing lock in the rbtree using the provided pointer. If | ||
173 | * one wasn't found - create it. | ||
174 | */ | ||
175 | static struct lock_lookup *__get_lock(void *lock) | ||
176 | { | ||
177 | struct rb_node **node, *parent; | ||
178 | struct lock_lookup *l; | ||
179 | |||
180 | ll_pthread_rwlock_rdlock(&locks_rwlock); | ||
181 | node = __get_lock_node(lock, &parent); | ||
182 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
183 | if (*node) { | ||
184 | return rb_entry(*node, struct lock_lookup, node); | ||
185 | } | ||
186 | |||
187 | /* We didn't find the lock, let's create it */ | ||
188 | l = alloc_lock(); | ||
189 | if (l == NULL) | ||
190 | return NULL; | ||
191 | |||
192 | l->orig = lock; | ||
193 | /* | ||
194 | * Currently the name of the lock is the ptr value of the pthread lock, | ||
195 | * while not optimal, it makes debugging a bit easier. | ||
196 | * | ||
197 | * TODO: Get the real name of the lock using libdwarf | ||
198 | */ | ||
199 | sprintf(l->name, "%p", lock); | ||
200 | lockdep_init_map(&l->dep_map, l->name, &l->key, 0); | ||
201 | |||
202 | ll_pthread_rwlock_wrlock(&locks_rwlock); | ||
203 | /* This might have changed since the last time we fetched it */ | ||
204 | node = __get_lock_node(lock, &parent); | ||
205 | rb_link_node(&l->node, parent, node); | ||
206 | rb_insert_color(&l->node, &locks); | ||
207 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
208 | |||
209 | return l; | ||
210 | } | ||
211 | |||
212 | static void __del_lock(struct lock_lookup *lock) | ||
213 | { | ||
214 | ll_pthread_rwlock_wrlock(&locks_rwlock); | ||
215 | rb_erase(&lock->node, &locks); | ||
216 | ll_pthread_rwlock_unlock(&locks_rwlock); | ||
217 | free_lock(lock); | ||
218 | } | ||
219 | |||
220 | int pthread_mutex_init(pthread_mutex_t *mutex, | ||
221 | const pthread_mutexattr_t *attr) | ||
222 | { | ||
223 | int r; | ||
224 | |||
225 | /* | ||
226 | * We keep trying to init our preload module because there might be | ||
227 | * code in init sections that tries to touch locks before we are | ||
228 | * initialized, in that case we'll need to manually call preload | ||
229 | * to get us going. | ||
230 | * | ||
231 | * Funny enough, kernel's lockdep had the same issue, and used | ||
232 | * (almost) the same solution. See look_up_lock_class() in | ||
233 | * kernel/locking/lockdep.c for details. | ||
234 | */ | ||
235 | try_init_preload(); | ||
236 | |||
237 | r = ll_pthread_mutex_init(mutex, attr); | ||
238 | if (r == 0) | ||
239 | /* | ||
240 | * We do a dummy initialization here so that lockdep could | ||
241 | * warn us if something fishy is going on - such as | ||
242 | * initializing a held lock. | ||
243 | */ | ||
244 | __get_lock(mutex); | ||
245 | |||
246 | return r; | ||
247 | } | ||
248 | |||
249 | int pthread_mutex_lock(pthread_mutex_t *mutex) | ||
250 | { | ||
251 | int r; | ||
252 | |||
253 | try_init_preload(); | ||
254 | |||
255 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, | ||
256 | (unsigned long)_RET_IP_); | ||
257 | /* | ||
258 | * Here's the thing with pthread mutexes: unlike the kernel variant, | ||
259 | * they can fail. | ||
260 | * | ||
261 | * This means that the behaviour here is a bit different from what's | ||
262 | * going on in the kernel: there we just tell lockdep that we took the | ||
263 | * lock before actually taking it, but here we must deal with the case | ||
264 | * that locking failed. | ||
265 | * | ||
266 | * To do that we'll "release" the lock if locking failed - this way | ||
267 | * we'll get lockdep doing the correct checks when we try to take | ||
268 | * the lock, and if that fails - we'll be back to the correct | ||
269 | * state by releasing it. | ||
270 | */ | ||
271 | r = ll_pthread_mutex_lock(mutex); | ||
272 | if (r) | ||
273 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
274 | |||
275 | return r; | ||
276 | } | ||
277 | |||
278 | int pthread_mutex_trylock(pthread_mutex_t *mutex) | ||
279 | { | ||
280 | int r; | ||
281 | |||
282 | try_init_preload(); | ||
283 | |||
284 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
285 | r = ll_pthread_mutex_trylock(mutex); | ||
286 | if (r) | ||
287 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
288 | |||
289 | return r; | ||
290 | } | ||
291 | |||
292 | int pthread_mutex_unlock(pthread_mutex_t *mutex) | ||
293 | { | ||
294 | int r; | ||
295 | |||
296 | try_init_preload(); | ||
297 | |||
298 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | ||
299 | /* | ||
300 | * Just like taking a lock, only in reverse! | ||
301 | * | ||
302 | * If we fail releasing the lock, tell lockdep we're holding it again. | ||
303 | */ | ||
304 | r = ll_pthread_mutex_unlock(mutex); | ||
305 | if (r) | ||
306 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
307 | |||
308 | return r; | ||
309 | } | ||
310 | |||
311 | int pthread_mutex_destroy(pthread_mutex_t *mutex) | ||
312 | { | ||
313 | try_init_preload(); | ||
314 | |||
315 | /* | ||
316 | * Let's see if we're releasing a lock that's held. | ||
317 | * | ||
318 | * TODO: Hook into free() and add that check there as well. | ||
319 | */ | ||
320 | debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex)); | ||
321 | __del_lock(__get_lock(mutex)); | ||
322 | return ll_pthread_mutex_destroy(mutex); | ||
323 | } | ||
324 | |||
325 | /* This is the rwlock part, very similar to what happened with mutex above */ | ||
326 | int pthread_rwlock_init(pthread_rwlock_t *rwlock, | ||
327 | const pthread_rwlockattr_t *attr) | ||
328 | { | ||
329 | int r; | ||
330 | |||
331 | try_init_preload(); | ||
332 | |||
333 | r = ll_pthread_rwlock_init(rwlock, attr); | ||
334 | if (r == 0) | ||
335 | __get_lock(rwlock); | ||
336 | |||
337 | return r; | ||
338 | } | ||
339 | |||
340 | int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) | ||
341 | { | ||
342 | try_init_preload(); | ||
343 | |||
344 | debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock)); | ||
345 | __del_lock(__get_lock(rwlock)); | ||
346 | return ll_pthread_rwlock_destroy(rwlock); | ||
347 | } | ||
348 | |||
349 | int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) | ||
350 | { | ||
351 | int r; | ||
352 | |||
353 | init_preload(); | ||
354 | |||
355 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
356 | r = ll_pthread_rwlock_rdlock(rwlock); | ||
357 | if (r) | ||
358 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
359 | |||
360 | return r; | ||
361 | } | ||
362 | |||
363 | int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) | ||
364 | { | ||
365 | int r; | ||
366 | |||
367 | init_preload(); | ||
368 | |||
369 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | ||
370 | r = ll_pthread_rwlock_tryrdlock(rwlock); | ||
371 | if (r) | ||
372 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
373 | |||
374 | return r; | ||
375 | } | ||
376 | |||
377 | int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) | ||
378 | { | ||
379 | int r; | ||
380 | |||
381 | init_preload(); | ||
382 | |||
383 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
384 | r = ll_pthread_rwlock_trywrlock(rwlock); | ||
385 | if (r) | ||
386 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
387 | |||
388 | return r; | ||
389 | } | ||
390 | |||
391 | int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) | ||
392 | { | ||
393 | int r; | ||
394 | |||
395 | init_preload(); | ||
396 | |||
397 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
398 | r = ll_pthread_rwlock_wrlock(rwlock); | ||
399 | if (r) | ||
400 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
401 | |||
402 | return r; | ||
403 | } | ||
404 | |||
405 | int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) | ||
406 | { | ||
407 | int r; | ||
408 | |||
409 | init_preload(); | ||
410 | |||
411 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | ||
412 | r = ll_pthread_rwlock_unlock(rwlock); | ||
413 | if (r) | ||
414 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | ||
415 | |||
416 | return r; | ||
417 | } | ||
418 | |||
419 | __attribute__((constructor)) static void init_preload(void) | ||
420 | { | ||
421 | if (__init_state != done) | ||
422 | return; | ||
423 | |||
424 | #ifndef __GLIBC__ | ||
425 | __init_state = prepare; | ||
426 | |||
427 | ll_pthread_mutex_init = dlsym(RTLD_NEXT, "pthread_mutex_init"); | ||
428 | ll_pthread_mutex_lock = dlsym(RTLD_NEXT, "pthread_mutex_lock"); | ||
429 | ll_pthread_mutex_trylock = dlsym(RTLD_NEXT, "pthread_mutex_trylock"); | ||
430 | ll_pthread_mutex_unlock = dlsym(RTLD_NEXT, "pthread_mutex_unlock"); | ||
431 | ll_pthread_mutex_destroy = dlsym(RTLD_NEXT, "pthread_mutex_destroy"); | ||
432 | |||
433 | ll_pthread_rwlock_init = dlsym(RTLD_NEXT, "pthread_rwlock_init"); | ||
434 | ll_pthread_rwlock_destroy = dlsym(RTLD_NEXT, "pthread_rwlock_destroy"); | ||
435 | ll_pthread_rwlock_rdlock = dlsym(RTLD_NEXT, "pthread_rwlock_rdlock"); | ||
436 | ll_pthread_rwlock_tryrdlock = dlsym(RTLD_NEXT, "pthread_rwlock_tryrdlock"); | ||
437 | ll_pthread_rwlock_wrlock = dlsym(RTLD_NEXT, "pthread_rwlock_wrlock"); | ||
438 | ll_pthread_rwlock_trywrlock = dlsym(RTLD_NEXT, "pthread_rwlock_trywrlock"); | ||
439 | ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock"); | ||
440 | #endif | ||
441 | |||
442 | printf("%p\n", ll_pthread_mutex_trylock);fflush(stdout); | ||
443 | |||
444 | lockdep_init(); | ||
445 | |||
446 | __init_state = done; | ||
447 | } | ||
diff --git a/tools/lib/lockdep/rbtree.c b/tools/lib/lockdep/rbtree.c new file mode 100644 index 000000000000..f7f43033c8b7 --- /dev/null +++ b/tools/lib/lockdep/rbtree.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../lib/rbtree.c" | |||
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh new file mode 100644 index 000000000000..5334ad9d39b7 --- /dev/null +++ b/tools/lib/lockdep/run_tests.sh | |||
@@ -0,0 +1,27 @@ | |||
1 | #! /bin/bash | ||
2 | |||
3 | make &> /dev/null | ||
4 | |||
5 | for i in `ls tests/*.c`; do | ||
6 | testname=$(basename -s .c "$i") | ||
7 | gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null | ||
8 | echo -ne "$testname... " | ||
9 | if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then | ||
10 | echo "PASSED!" | ||
11 | else | ||
12 | echo "FAILED!" | ||
13 | fi | ||
14 | rm tests/$testname | ||
15 | done | ||
16 | |||
17 | for i in `ls tests/*.c`; do | ||
18 | testname=$(basename -s .c "$i") | ||
19 | gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null | ||
20 | echo -ne "(PRELOAD) $testname... " | ||
21 | if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then | ||
22 | echo "PASSED!" | ||
23 | else | ||
24 | echo "FAILED!" | ||
25 | fi | ||
26 | rm tests/$testname | ||
27 | done | ||
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c new file mode 100644 index 000000000000..0f782ff404ac --- /dev/null +++ b/tools/lib/lockdep/tests/AA.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_mutex_t a, b; | ||
6 | |||
7 | pthread_mutex_init(&a, NULL); | ||
8 | pthread_mutex_init(&b, NULL); | ||
9 | |||
10 | pthread_mutex_lock(&a); | ||
11 | pthread_mutex_lock(&b); | ||
12 | pthread_mutex_lock(&a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c new file mode 100644 index 000000000000..07f0e29d5485 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBA.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | |||
11 | LOCK_UNLOCK_2(a, b); | ||
12 | LOCK_UNLOCK_2(b, a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c new file mode 100644 index 000000000000..843db09ac666 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBCCA.c | |||
@@ -0,0 +1,15 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | |||
12 | LOCK_UNLOCK_2(a, b); | ||
13 | LOCK_UNLOCK_2(b, c); | ||
14 | LOCK_UNLOCK_2(c, a); | ||
15 | } | ||
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c new file mode 100644 index 000000000000..33620e268f85 --- /dev/null +++ b/tools/lib/lockdep/tests/ABBCCDDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(b, c); | ||
15 | LOCK_UNLOCK_2(c, d); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c new file mode 100644 index 000000000000..3fee51e3a68a --- /dev/null +++ b/tools/lib/lockdep/tests/ABCABC.c | |||
@@ -0,0 +1,15 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | |||
12 | LOCK_UNLOCK_2(a, b); | ||
13 | LOCK_UNLOCK_2(c, a); | ||
14 | LOCK_UNLOCK_2(b, c); | ||
15 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c new file mode 100644 index 000000000000..427ba562c75b --- /dev/null +++ b/tools/lib/lockdep/tests/ABCDBCDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(c, d); | ||
15 | LOCK_UNLOCK_2(b, c); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c new file mode 100644 index 000000000000..680c6cf3e919 --- /dev/null +++ b/tools/lib/lockdep/tests/ABCDBDDA.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | #include "common.h" | ||
3 | |||
4 | void main(void) | ||
5 | { | ||
6 | pthread_mutex_t a, b, c, d; | ||
7 | |||
8 | pthread_mutex_init(&a, NULL); | ||
9 | pthread_mutex_init(&b, NULL); | ||
10 | pthread_mutex_init(&c, NULL); | ||
11 | pthread_mutex_init(&d, NULL); | ||
12 | |||
13 | LOCK_UNLOCK_2(a, b); | ||
14 | LOCK_UNLOCK_2(c, d); | ||
15 | LOCK_UNLOCK_2(b, d); | ||
16 | LOCK_UNLOCK_2(d, a); | ||
17 | } | ||
diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c new file mode 100644 index 000000000000..d44f77d71029 --- /dev/null +++ b/tools/lib/lockdep/tests/WW.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <liblockdep/rwlock.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_rwlock_t a, b; | ||
6 | |||
7 | pthread_rwlock_init(&a, NULL); | ||
8 | pthread_rwlock_init(&b, NULL); | ||
9 | |||
10 | pthread_rwlock_wrlock(&a); | ||
11 | pthread_rwlock_rdlock(&b); | ||
12 | pthread_rwlock_wrlock(&a); | ||
13 | } | ||
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h new file mode 100644 index 000000000000..d89e94d47d86 --- /dev/null +++ b/tools/lib/lockdep/tests/common.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _LIBLOCKDEP_TEST_COMMON_H | ||
2 | #define _LIBLOCKDEP_TEST_COMMON_H | ||
3 | |||
4 | #define LOCK_UNLOCK_2(a, b) \ | ||
5 | do { \ | ||
6 | pthread_mutex_lock(&(a)); \ | ||
7 | pthread_mutex_lock(&(b)); \ | ||
8 | pthread_mutex_unlock(&(b)); \ | ||
9 | pthread_mutex_unlock(&(a)); \ | ||
10 | } while(0) | ||
11 | |||
12 | #endif | ||
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c new file mode 100644 index 000000000000..0bc62de686f7 --- /dev/null +++ b/tools/lib/lockdep/tests/unlock_balance.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <liblockdep/mutex.h> | ||
2 | |||
3 | void main(void) | ||
4 | { | ||
5 | pthread_mutex_t a; | ||
6 | |||
7 | pthread_mutex_init(&a, NULL); | ||
8 | |||
9 | pthread_mutex_lock(&a); | ||
10 | pthread_mutex_unlock(&a); | ||
11 | pthread_mutex_unlock(&a); | ||
12 | } | ||
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/asm/hweight.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/asm/sections.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/bitops.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h new file mode 100644 index 000000000000..7ac838a1f196 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/compiler.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_COMPILER_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_COMPILER_H_ | ||
3 | |||
4 | #define __used __attribute__((__unused__)) | ||
5 | #define unlikely | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/debug_locks.h b/tools/lib/lockdep/uinclude/linux/debug_locks.h new file mode 100644 index 000000000000..f38eb64df794 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/debug_locks.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_ | ||
2 | #define _LIBLOCKDEP_DEBUG_LOCKS_H_ | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <linux/compiler.h> | ||
6 | |||
7 | #define DEBUG_LOCKS_WARN_ON(x) (x) | ||
8 | |||
9 | extern bool debug_locks; | ||
10 | extern bool debug_locks_silent; | ||
11 | |||
12 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/delay.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h new file mode 100644 index 000000000000..6bdf3492c535 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/export.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_EXPORT_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_EXPORT_H_ | ||
3 | |||
4 | #define EXPORT_SYMBOL(sym) | ||
5 | #define EXPORT_SYMBOL_GPL(sym) | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/ftrace.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/gfp.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h new file mode 100644 index 000000000000..c8f3f8f58729 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/hardirq.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_HARDIRQ_H_ | ||
3 | |||
4 | #define SOFTIRQ_BITS 0UL | ||
5 | #define HARDIRQ_BITS 0UL | ||
6 | #define SOFTIRQ_SHIFT 0UL | ||
7 | #define HARDIRQ_SHIFT 0UL | ||
8 | #define hardirq_count() 0UL | ||
9 | #define softirq_count() 0UL | ||
10 | |||
11 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h new file mode 100644 index 000000000000..0f8479858dc0 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/hash.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/hash.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/interrupt.h b/tools/lib/lockdep/uinclude/linux/interrupt.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/interrupt.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h new file mode 100644 index 000000000000..6cc296f0fad0 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/irqflags.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | ||
3 | |||
4 | # define trace_hardirq_context(p) 0 | ||
5 | # define trace_softirq_context(p) 0 | ||
6 | # define trace_hardirqs_enabled(p) 0 | ||
7 | # define trace_softirqs_enabled(p) 0 | ||
8 | # define trace_hardirq_enter() do { } while (0) | ||
9 | # define trace_hardirq_exit() do { } while (0) | ||
10 | # define lockdep_softirq_enter() do { } while (0) | ||
11 | # define lockdep_softirq_exit() do { } while (0) | ||
12 | # define INIT_TRACE_IRQFLAGS | ||
13 | |||
14 | # define stop_critical_timings() do { } while (0) | ||
15 | # define start_critical_timings() do { } while (0) | ||
16 | |||
17 | #define raw_local_irq_disable() do { } while (0) | ||
18 | #define raw_local_irq_enable() do { } while (0) | ||
19 | #define raw_local_irq_save(flags) ((flags) = 0) | ||
20 | #define raw_local_irq_restore(flags) do { } while (0) | ||
21 | #define raw_local_save_flags(flags) ((flags) = 0) | ||
22 | #define raw_irqs_disabled_flags(flags) do { } while (0) | ||
23 | #define raw_irqs_disabled() 0 | ||
24 | #define raw_safe_halt() | ||
25 | |||
26 | #define local_irq_enable() do { } while (0) | ||
27 | #define local_irq_disable() do { } while (0) | ||
28 | #define local_irq_save(flags) ((flags) = 0) | ||
29 | #define local_irq_restore(flags) do { } while (0) | ||
30 | #define local_save_flags(flags) ((flags) = 0) | ||
31 | #define irqs_disabled() (1) | ||
32 | #define irqs_disabled_flags(flags) (0) | ||
33 | #define safe_halt() do { } while (0) | ||
34 | |||
35 | #define trace_lock_release(x, y) | ||
36 | #define trace_lock_acquire(a, b, c, d, e, f, g) | ||
37 | |||
38 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h new file mode 100644 index 000000000000..b0f2dbdf1a15 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kallsyms.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KALLSYMS_H_ | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | #define KSYM_NAME_LEN 128 | ||
8 | |||
9 | struct module; | ||
10 | |||
11 | static inline const char *kallsyms_lookup(unsigned long addr, | ||
12 | unsigned long *symbolsize, | ||
13 | unsigned long *offset, | ||
14 | char **modname, char *namebuf) | ||
15 | { | ||
16 | return NULL; | ||
17 | } | ||
18 | |||
19 | #include <execinfo.h> | ||
20 | #include <stdlib.h> | ||
21 | static inline void print_ip_sym(unsigned long ip) | ||
22 | { | ||
23 | char **name; | ||
24 | |||
25 | name = backtrace_symbols((void **)&ip, 1); | ||
26 | |||
27 | printf("%s\n", *name); | ||
28 | |||
29 | free(name); | ||
30 | } | ||
31 | |||
32 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kern_levels.h b/tools/lib/lockdep/uinclude/linux/kern_levels.h new file mode 100644 index 000000000000..3b9bade28698 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kern_levels.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __KERN_LEVELS_H__ | ||
2 | #define __KERN_LEVELS_H__ | ||
3 | |||
4 | #define KERN_SOH "" /* ASCII Start Of Header */ | ||
5 | #define KERN_SOH_ASCII '' | ||
6 | |||
7 | #define KERN_EMERG KERN_SOH "" /* system is unusable */ | ||
8 | #define KERN_ALERT KERN_SOH "" /* action must be taken immediately */ | ||
9 | #define KERN_CRIT KERN_SOH "" /* critical conditions */ | ||
10 | #define KERN_ERR KERN_SOH "" /* error conditions */ | ||
11 | #define KERN_WARNING KERN_SOH "" /* warning conditions */ | ||
12 | #define KERN_NOTICE KERN_SOH "" /* normal but significant condition */ | ||
13 | #define KERN_INFO KERN_SOH "" /* informational */ | ||
14 | #define KERN_DEBUG KERN_SOH "" /* debug-level messages */ | ||
15 | |||
16 | #define KERN_DEFAULT KERN_SOH "" /* the default kernel loglevel */ | ||
17 | |||
18 | /* | ||
19 | * Annotation for a "continued" line of log printout (only done after a | ||
20 | * line that had no enclosing \n). Only to be used by core/arch code | ||
21 | * during early bootup (a continued line is not SMP-safe otherwise). | ||
22 | */ | ||
23 | #define KERN_CONT "" | ||
24 | |||
25 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h new file mode 100644 index 000000000000..a11e3c357be7 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kernel.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KERNEL_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KERNEL_H_ | ||
3 | |||
4 | #include <linux/export.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/rcu.h> | ||
7 | #include <linux/hardirq.h> | ||
8 | #include <linux/kern_levels.h> | ||
9 | |||
10 | #ifndef container_of | ||
11 | #define container_of(ptr, type, member) ({ \ | ||
12 | const typeof(((type *)0)->member) * __mptr = (ptr); \ | ||
13 | (type *)((char *)__mptr - offsetof(type, member)); }) | ||
14 | #endif | ||
15 | |||
16 | #define max(x, y) ({ \ | ||
17 | typeof(x) _max1 = (x); \ | ||
18 | typeof(y) _max2 = (y); \ | ||
19 | (void) (&_max1 == &_max2); \ | ||
20 | _max1 > _max2 ? _max1 : _max2; }) | ||
21 | |||
22 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | ||
23 | #define WARN_ON(x) (x) | ||
24 | #define WARN_ON_ONCE(x) (x) | ||
25 | #define likely(x) (x) | ||
26 | #define WARN(x, y, z) (x) | ||
27 | #define uninitialized_var(x) x | ||
28 | #define __init | ||
29 | #define noinline | ||
30 | #define list_add_tail_rcu list_add_tail | ||
31 | |||
32 | #ifndef CALLER_ADDR0 | ||
33 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | ||
34 | #endif | ||
35 | |||
36 | #ifndef _RET_IP_ | ||
37 | #define _RET_IP_ CALLER_ADDR0 | ||
38 | #endif | ||
39 | |||
40 | #ifndef _THIS_IP_ | ||
41 | #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) | ||
42 | #endif | ||
43 | |||
44 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h new file mode 100644 index 000000000000..94d598bc6abe --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/kmemcheck.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_KMEMCHECK_H_ | ||
3 | |||
4 | static inline void kmemcheck_mark_initialized(void *address, unsigned int n) | ||
5 | { | ||
6 | } | ||
7 | |||
8 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/linkage.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h new file mode 100644 index 000000000000..6e9ef31ed82e --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/list.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/list.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h new file mode 100644 index 000000000000..d0f5d6e50214 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/lockdep.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef _LIBLOCKDEP_LOCKDEP_H_ | ||
2 | #define _LIBLOCKDEP_LOCKDEP_H_ | ||
3 | |||
4 | #include <sys/prctl.h> | ||
5 | #include <sys/syscall.h> | ||
6 | #include <string.h> | ||
7 | #include <limits.h> | ||
8 | #include <linux/utsname.h> | ||
9 | |||
10 | |||
11 | #define MAX_LOCK_DEPTH 2000UL | ||
12 | |||
13 | #include "../../../include/linux/lockdep.h" | ||
14 | |||
15 | struct task_struct { | ||
16 | u64 curr_chain_key; | ||
17 | int lockdep_depth; | ||
18 | unsigned int lockdep_recursion; | ||
19 | struct held_lock held_locks[MAX_LOCK_DEPTH]; | ||
20 | gfp_t lockdep_reclaim_gfp; | ||
21 | int pid; | ||
22 | char comm[17]; | ||
23 | }; | ||
24 | |||
25 | extern struct task_struct *__curr(void); | ||
26 | |||
27 | #define current (__curr()) | ||
28 | |||
29 | #define debug_locks_off() 1 | ||
30 | #define task_pid_nr(tsk) ((tsk)->pid) | ||
31 | |||
32 | #define KSYM_NAME_LEN 128 | ||
33 | #define printk printf | ||
34 | |||
35 | #define list_del_rcu list_del | ||
36 | |||
37 | #define atomic_t unsigned long | ||
38 | #define atomic_inc(x) ((*(x))++) | ||
39 | |||
40 | static struct new_utsname *init_utsname(void) | ||
41 | { | ||
42 | static struct new_utsname n = (struct new_utsname) { | ||
43 | .release = "liblockdep", | ||
44 | .version = LIBLOCKDEP_VERSION, | ||
45 | }; | ||
46 | |||
47 | return &n; | ||
48 | } | ||
49 | |||
50 | #define print_tainted() "" | ||
51 | #define static_obj(x) 1 | ||
52 | |||
53 | #define debug_show_all_locks() | ||
54 | |||
55 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h new file mode 100644 index 000000000000..09c7a7be8ccc --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/module.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_MODULE_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_MODULE_H_ | ||
3 | |||
4 | #define module_param(name, type, perm) | ||
5 | |||
6 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/mutex.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h new file mode 100644 index 000000000000..0c27bdf14233 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/poison.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/poison.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/prefetch.h b/tools/lib/lockdep/uinclude/linux/prefetch.h new file mode 100644 index 000000000000..d73fe6f850ac --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/prefetch.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_PREFETCH_H | ||
3 | |||
4 | static inline void prefetch(void *a __attribute__((unused))) { } | ||
5 | |||
6 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/proc_fs.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/proc_fs.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree.h b/tools/lib/lockdep/uinclude/linux/rbtree.h new file mode 100644 index 000000000000..965901db4862 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rbtree.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../include/linux/rbtree.h" | |||
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h new file mode 100644 index 000000000000..c3759477379c --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h | |||
@@ -0,0 +1,2 @@ | |||
1 | #define __always_inline | ||
2 | #include "../../../include/linux/rbtree_augmented.h" | ||
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h new file mode 100644 index 000000000000..4c99fcb5da27 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/rcu.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _LIBLOCKDEP_RCU_H_ | ||
2 | #define _LIBLOCKDEP_RCU_H_ | ||
3 | |||
4 | int rcu_scheduler_active; | ||
5 | |||
6 | static inline int rcu_lockdep_current_cpu_online(void) | ||
7 | { | ||
8 | return 1; | ||
9 | } | ||
10 | |||
11 | static inline int rcu_is_cpu_idle(void) | ||
12 | { | ||
13 | return 1; | ||
14 | } | ||
15 | |||
16 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/seq_file.h b/tools/lib/lockdep/uinclude/linux/seq_file.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/seq_file.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h new file mode 100644 index 000000000000..68c1aa2bcba5 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/spinlock.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _LIBLOCKDEP_SPINLOCK_H_ | ||
2 | #define _LIBLOCKDEP_SPINLOCK_H_ | ||
3 | |||
4 | #include <pthread.h> | ||
5 | #include <stdbool.h> | ||
6 | |||
7 | #define arch_spinlock_t pthread_mutex_t | ||
8 | #define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER | ||
9 | |||
10 | static inline void arch_spin_lock(arch_spinlock_t *mutex) | ||
11 | { | ||
12 | pthread_mutex_lock(mutex); | ||
13 | } | ||
14 | |||
15 | static inline void arch_spin_unlock(arch_spinlock_t *mutex) | ||
16 | { | ||
17 | pthread_mutex_unlock(mutex); | ||
18 | } | ||
19 | |||
20 | static inline bool arch_spin_is_locked(arch_spinlock_t *mutex) | ||
21 | { | ||
22 | return true; | ||
23 | } | ||
24 | |||
25 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h new file mode 100644 index 000000000000..39aecc6b19d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/stacktrace.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_STACKTRACE_H_ | ||
3 | |||
4 | #include <execinfo.h> | ||
5 | |||
6 | struct stack_trace { | ||
7 | unsigned int nr_entries, max_entries; | ||
8 | unsigned long *entries; | ||
9 | int skip; | ||
10 | }; | ||
11 | |||
12 | static inline void print_stack_trace(struct stack_trace *trace, int spaces) | ||
13 | { | ||
14 | backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1); | ||
15 | } | ||
16 | |||
17 | #define save_stack_trace(trace) \ | ||
18 | ((trace)->nr_entries = \ | ||
19 | backtrace((void **)(trace)->entries, (trace)->max_entries)) | ||
20 | |||
21 | static inline int dump_stack(void) | ||
22 | { | ||
23 | void *array[64]; | ||
24 | size_t size; | ||
25 | |||
26 | size = backtrace(array, 64); | ||
27 | backtrace_symbols_fd(array, size, 1); | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h new file mode 100644 index 000000000000..05dfcd1ac118 --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/stringify.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_STRINGIFY_H_ | ||
3 | |||
4 | #define __stringify_1(x...) #x | ||
5 | #define __stringify(x...) __stringify_1(x) | ||
6 | |||
7 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h new file mode 100644 index 000000000000..929938f426de --- /dev/null +++ b/tools/lib/lockdep/uinclude/linux/types.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef _LIBLOCKDEP_LINUX_TYPES_H_ | ||
2 | #define _LIBLOCKDEP_LINUX_TYPES_H_ | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <stddef.h> | ||
6 | |||
7 | #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ | ||
8 | #include <asm/types.h> | ||
9 | |||
10 | struct page; | ||
11 | struct kmem_cache; | ||
12 | |||
13 | typedef unsigned gfp_t; | ||
14 | |||
15 | typedef __u64 u64; | ||
16 | typedef __s64 s64; | ||
17 | |||
18 | typedef __u32 u32; | ||
19 | typedef __s32 s32; | ||
20 | |||
21 | typedef __u16 u16; | ||
22 | typedef __s16 s16; | ||
23 | |||
24 | typedef __u8 u8; | ||
25 | typedef __s8 s8; | ||
26 | |||
27 | #ifdef __CHECKER__ | ||
28 | #define __bitwise__ __attribute__((bitwise)) | ||
29 | #else | ||
30 | #define __bitwise__ | ||
31 | #endif | ||
32 | #ifdef __CHECK_ENDIAN__ | ||
33 | #define __bitwise __bitwise__ | ||
34 | #else | ||
35 | #define __bitwise | ||
36 | #endif | ||
37 | |||
38 | |||
39 | typedef __u16 __bitwise __le16; | ||
40 | typedef __u16 __bitwise __be16; | ||
41 | typedef __u32 __bitwise __le32; | ||
42 | typedef __u32 __bitwise __be32; | ||
43 | typedef __u64 __bitwise __le64; | ||
44 | typedef __u64 __bitwise __be64; | ||
45 | |||
46 | struct list_head { | ||
47 | struct list_head *next, *prev; | ||
48 | }; | ||
49 | |||
50 | struct hlist_head { | ||
51 | struct hlist_node *first; | ||
52 | }; | ||
53 | |||
54 | struct hlist_node { | ||
55 | struct hlist_node *next, **pprev; | ||
56 | }; | ||
57 | |||
58 | #endif | ||
diff --git a/tools/lib/lockdep/uinclude/trace/events/lock.h b/tools/lib/lockdep/uinclude/trace/events/lock.h new file mode 100644 index 000000000000..fab00ff936d1 --- /dev/null +++ b/tools/lib/lockdep/uinclude/trace/events/lock.h | |||
@@ -0,0 +1,3 @@ | |||
1 | |||
2 | /* empty file */ | ||
3 | |||