diff options
Diffstat (limited to 'tools/lib')
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 | |||
