linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace
@ 2013-02-04  1:50 Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 2/7] liblockdep: public headers for mutex implementation Sasha Levin
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

kernel/lockdep.c deals with validating locking scenarios for various
architectures supported by the kernel. There isn't anything kernel
specific going on in lockdep, and when we compare userspace to other
architectures that don't have to deal with irqs such as s390, they
become all too similar.

We wrap kernel/lockdep.c and include/linux/lockdep.h with several
headers which allow us to build and use lockdep from userspace. We don't
touch the kernel code itself which means that any work done on lockdep
in the kernel will automatically benefit userspace lockdep as well!

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/lib/lockdep/Makefile                     | 247 +++++++++++++++++++++++++
 tools/lib/lockdep/common.c                     |  22 +++
 tools/lib/lockdep/lockdep.c                    |   2 +
 tools/lib/lockdep/lockdep_internals.h          |   1 +
 tools/lib/lockdep/lockdep_states.h             |   1 +
 tools/lib/lockdep/uinclude/asm/hweight.h       |   0
 tools/lib/lockdep/uinclude/asm/sections.h      |   0
 tools/lib/lockdep/uinclude/linux/bitops.h      |   0
 tools/lib/lockdep/uinclude/linux/compiler.h    |   7 +
 tools/lib/lockdep/uinclude/linux/debug_locks.h |  12 ++
 tools/lib/lockdep/uinclude/linux/delay.h       |   0
 tools/lib/lockdep/uinclude/linux/export.h      |   7 +
 tools/lib/lockdep/uinclude/linux/ftrace.h      |   0
 tools/lib/lockdep/uinclude/linux/gfp.h         |   0
 tools/lib/lockdep/uinclude/linux/hardirq.h     |  11 ++
 tools/lib/lockdep/uinclude/linux/hash.h        |   1 +
 tools/lib/lockdep/uinclude/linux/interrupt.h   |   0
 tools/lib/lockdep/uinclude/linux/irqflags.h    |  38 ++++
 tools/lib/lockdep/uinclude/linux/kallsyms.h    |  32 ++++
 tools/lib/lockdep/uinclude/linux/kernel.h      |  34 ++++
 tools/lib/lockdep/uinclude/linux/kmemcheck.h   |   8 +
 tools/lib/lockdep/uinclude/linux/linkage.h     |   0
 tools/lib/lockdep/uinclude/linux/list.h        |   1 +
 tools/lib/lockdep/uinclude/linux/lockdep.h     |  58 ++++++
 tools/lib/lockdep/uinclude/linux/mm_types.h    |   0
 tools/lib/lockdep/uinclude/linux/module.h      |   6 +
 tools/lib/lockdep/uinclude/linux/mutex.h       |   0
 tools/lib/lockdep/uinclude/linux/poison.h      |   1 +
 tools/lib/lockdep/uinclude/linux/prefetch.h    |   6 +
 tools/lib/lockdep/uinclude/linux/proc_fs.h     |   0
 tools/lib/lockdep/uinclude/linux/rcu.h         |  16 ++
 tools/lib/lockdep/uinclude/linux/seq_file.h    |   0
 tools/lib/lockdep/uinclude/linux/spinlock.h    |  25 +++
 tools/lib/lockdep/uinclude/linux/stacktrace.h  |  32 ++++
 tools/lib/lockdep/uinclude/linux/stringify.h   |   7 +
 tools/lib/lockdep/uinclude/linux/system.h      |   0
 tools/lib/lockdep/uinclude/linux/types.h       |  58 ++++++
 tools/lib/lockdep/uinclude/linux/util.h        |   0
 tools/lib/lockdep/uinclude/trace/events/lock.h |   0
 39 files changed, 633 insertions(+)
 create mode 100644 tools/lib/lockdep/Makefile
 create mode 100644 tools/lib/lockdep/common.c
 create mode 100644 tools/lib/lockdep/lockdep.c
 create mode 100644 tools/lib/lockdep/lockdep_internals.h
 create mode 100644 tools/lib/lockdep/lockdep_states.h
 create mode 100644 tools/lib/lockdep/uinclude/asm/hweight.h
 create mode 100644 tools/lib/lockdep/uinclude/asm/sections.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/bitops.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/compiler.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/debug_locks.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/delay.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/export.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/ftrace.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/gfp.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/hardirq.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/hash.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/interrupt.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/irqflags.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/kallsyms.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/kernel.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/kmemcheck.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/linkage.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/list.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/lockdep.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/mm_types.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/module.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/mutex.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/poison.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/prefetch.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/proc_fs.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/rcu.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/seq_file.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/spinlock.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/stacktrace.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/stringify.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/system.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/types.h
 create mode 100644 tools/lib/lockdep/uinclude/linux/util.h
 create mode 100644 tools/lib/lockdep/uinclude/trace/events/lock.h

diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
new file mode 100644
index 0000000..e82ffe9
--- /dev/null
+++ b/tools/lib/lockdep/Makefile
@@ -0,0 +1,247 @@
+# liblockdep version
+LL_VERSION = 0
+LL_PATCHLEVEL = 0
+LL_EXTRAVERSION = 1
+
+# file format version
+FILE_VERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+prefix ?= /usr/local
+bindir_relative = lib
+bindir = $(prefix)/$(bindir_relative)
+
+export DESTDIR DESTDIR_SQ INSTALL
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+  VERBOSE = $(V)
+endif
+ifndef VERBOSE
+  VERBOSE = 0
+endif
+
+ifeq ("$(origin O)", "command line")
+  BUILD_OUTPUT := $(O)
+endif
+
+ifeq ($(BUILD_SRC),)
+ifneq ($(BUILD_OUTPUT),)
+
+define build_output
+	$(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) 	\
+	BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+endef
+
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(BUILD_OUTPUT),, \
+     $(error output directory "$(saved-output)" does not exist))
+
+all: sub-make
+
+gui: force
+	$(call build_output, all_cmd)
+
+$(filter-out gui,$(MAKECMDGOALS)): sub-make
+
+sub-make: force
+	$(call build_output, $(MAKECMDGOALS))
+
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+
+endif # BUILD_OUTPUT
+endif # BUILD_SRC
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+srctree		:= $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
+objtree		:= $(CURDIR)
+src		:= $(srctree)
+obj		:= $(objtree)
+
+export prefix bindir src obj
+
+# Shell quotes
+bindir_SQ = $(subst ','\'',$(bindir))
+bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
+
+LIB_FILE = liblockdep.a liblockdep.so
+
+CONFIG_INCLUDES =
+CONFIG_LIBS	=
+CONFIG_FLAGS	=
+
+OBJ		= $@
+N		=
+
+export Q VERBOSE
+
+LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
+
+INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES)
+
+# Set compile option CFLAGS if not set elsewhere
+CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=64 -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic
+
+override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
+
+ifeq ($(VERBOSE),1)
+  Q =
+  print_compile =
+  print_app_build =
+  print_fpic_compile =
+  print_shared_lib_compile =
+  print_install =
+else
+  Q = @
+  print_compile =		echo '  CC                 '$(OBJ);
+  print_app_build =		echo '  BUILD              '$(OBJ);
+  print_fpic_compile =		echo '  CC FPIC            '$(OBJ);
+  print_shared_lib_compile =	echo '  BUILD SHARED LIB   '$(OBJ);
+  print_static_lib_build =	echo '  BUILD STATIC LIB   '$(OBJ);
+  print_install =		echo '  INSTALL     '$1'	to	$(DESTDIR_SQ)$2';
+endif
+
+do_fpic_compile =					\
+	($(print_fpic_compile)				\
+	$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
+
+do_app_build =						\
+	($(print_app_build)				\
+	$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+
+do_compile_shared_library =			\
+	($(print_shared_lib_compile)		\
+	$(CC) --shared $^ -o $@)
+
+do_build_static_lib =				\
+	($(print_static_lib_build)		\
+	$(RM) $@;  $(AR) rcs $@ $^)
+
+
+define do_compile
+	$(print_compile)						\
+	$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+endef
+
+$(obj)/%.o: $(src)/%.c
+	$(Q)$(call do_compile)
+
+%.o: $(src)/%.c
+	$(Q)$(call do_compile)
+
+PEVENT_LIB_OBJS = common.o lockdep.o
+
+ALL_OBJS = $(PEVENT_LIB_OBJS)
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+
+all: all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+liblockdep.so: $(PEVENT_LIB_OBJS)
+	$(Q)$(do_compile_shared_library)
+
+liblockdep.a: $(PEVENT_LIB_OBJS)
+	$(Q)$(do_build_static_lib)
+
+$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
+	$(Q)$(do_fpic_compile)
+
+## make deps
+
+all_objs := $(sort $(ALL_OBJS))
+all_deps := $(all_objs:%.o=.%.d)
+
+# let .d file also depends on the source and header files
+define check_deps
+		@set -e; $(RM) $@; \
+		$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+		sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+		$(RM) $@.$$$$
+endef
+
+$(all_deps): .%.d: $(src)/%.c
+	$(Q)$(call check_deps)
+
+$(all_objs) : %.o : .%.d
+
+dep_includes := $(wildcard $(all_deps))
+
+ifneq ($(dep_includes),)
+ include $(dep_includes)
+endif
+
+### Detect environment changes
+TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
+
+tags:	force
+	$(RM) tags
+	find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+	--regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+
+TAGS:	force
+	$(RM) TAGS
+	find . -name '*.[ch]' | xargs etags \
+	--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+
+define do_install
+	$(print_install)				\
+	if [ ! -d '$(DESTDIR_SQ)$2' ]; then		\
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2';	\
+	fi;						\
+	$(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd
+	$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
+
+install: install_lib
+
+clean:
+	$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
+	$(RM) tags TAGS
+
+endif # skip-makefile
+
+PHONY += force
+force:
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
new file mode 100644
index 0000000..99d3b4b
--- /dev/null
+++ b/tools/lib/lockdep/common.c
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <linux/compiler.h>
+#include <linux/lockdep.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+__thread struct task_struct current_obj;
+
+bool debug_locks = true;
+bool debug_locks_silent;
+
+void liblockdep_init(void)
+{
+	lockdep_init();
+}
+
+void liblockdep_set_thread(void)
+{
+	prctl(PR_GET_NAME, current->comm);
+	current->pid = syscall(__NR_gettid);
+}
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
new file mode 100644
index 0000000..8ddd0ff
--- /dev/null
+++ b/tools/lib/lockdep/lockdep.c
@@ -0,0 +1,2 @@
+#include <linux/lockdep.h>
+#include "../../../kernel/lockdep.c"
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h
new file mode 100644
index 0000000..109e96f
--- /dev/null
+++ b/tools/lib/lockdep/lockdep_internals.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_internals.h"
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h
new file mode 100644
index 0000000..6b75423
--- /dev/null
+++ b/tools/lib/lockdep/lockdep_states.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_states.h"
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h
new file mode 100644
index 0000000..7ac838a
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/compiler.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_COMPILER_H_
+#define _LIBLOCKDEP_LINUX_COMPILER_H_
+
+#define __used		__attribute__((__unused__))
+#define unlikely
+
+#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 0000000..f38eb64
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/debug_locks.h
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_
+#define _LIBLOCKDEP_DEBUG_LOCKS_H_
+
+#include <stddef.h>
+#include <linux/compiler.h>
+
+#define DEBUG_LOCKS_WARN_ON(x) (x)
+
+extern bool debug_locks;
+extern bool debug_locks_silent;
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h
new file mode 100644
index 0000000..6bdf349
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/export.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_EXPORT_H_
+#define _LIBLOCKDEP_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h
new file mode 100644
index 0000000..c8f3f8f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/hardirq.h
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_
+#define _LIBLOCKDEP_LINUX_HARDIRQ_H_
+
+#define SOFTIRQ_BITS	0UL
+#define HARDIRQ_BITS	0UL
+#define SOFTIRQ_SHIFT	0UL
+#define HARDIRQ_SHIFT	0UL
+#define hardirq_count()	0UL
+#define softirq_count()	0UL
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h
new file mode 100644
index 0000000..0f84798
--- /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 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h
new file mode 100644
index 0000000..6cc296f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/irqflags.h
@@ -0,0 +1,38 @@
+#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+
+# define trace_hardirq_context(p)	0
+# define trace_softirq_context(p)	0
+# define trace_hardirqs_enabled(p)	0
+# define trace_softirqs_enabled(p)	0
+# define trace_hardirq_enter()		do { } while (0)
+# define trace_hardirq_exit()		do { } while (0)
+# define lockdep_softirq_enter()	do { } while (0)
+# define lockdep_softirq_exit()		do { } while (0)
+# define INIT_TRACE_IRQFLAGS
+
+# define stop_critical_timings() do { } while (0)
+# define start_critical_timings() do { } while (0)
+
+#define raw_local_irq_disable() do { } while (0)
+#define raw_local_irq_enable() do { } while (0)
+#define raw_local_irq_save(flags) ((flags) = 0)
+#define raw_local_irq_restore(flags) do { } while (0)
+#define raw_local_save_flags(flags) ((flags) = 0)
+#define raw_irqs_disabled_flags(flags) do { } while (0)
+#define raw_irqs_disabled() 0
+#define raw_safe_halt()
+
+#define local_irq_enable() do { } while (0)
+#define local_irq_disable() do { } while (0)
+#define local_irq_save(flags) ((flags) = 0)
+#define local_irq_restore(flags) do { } while (0)
+#define local_save_flags(flags)	((flags) = 0)
+#define irqs_disabled() (1)
+#define irqs_disabled_flags(flags) (0)
+#define safe_halt() do { } while (0)
+
+#define trace_lock_release(x, y)
+#define trace_lock_acquire(a, b, c, d, e, f, g)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h
new file mode 100644
index 0000000..b0f2dbd
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kallsyms.h
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_
+#define _LIBLOCKDEP_LINUX_KALLSYMS_H_
+
+#include <linux/kernel.h>
+#include <stdio.h>
+
+#define KSYM_NAME_LEN 128
+
+struct module;
+
+static inline const char *kallsyms_lookup(unsigned long addr,
+					  unsigned long *symbolsize,
+					  unsigned long *offset,
+					  char **modname, char *namebuf)
+{
+	return NULL;
+}
+
+#include <execinfo.h>
+#include <stdlib.h>
+static inline void print_ip_sym(unsigned long ip)
+{
+	char **name;
+
+	name = backtrace_symbols((void **)&ip, 1);
+
+	printf("%s\n", *name);
+
+	free(name);
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h
new file mode 100644
index 0000000..da97ce8
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kernel.h
@@ -0,0 +1,34 @@
+#ifndef _LIBLOCKDEP_LINUX_KERNEL_H_
+#define _LIBLOCKDEP_LINUX_KERNEL_H_
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/rcu.h>
+#include <linux/hardirq.h>
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({			\
+	const typeof(((type *)0)->member) * __mptr = (ptr);	\
+	(type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define WARN_ON(x) (x)
+#define WARN_ON_ONCE(x) (x)
+#define likely(x) (x)
+#define WARN(x, y, z) (x)
+#define uninitialized_var(x) x
+#define __init
+#define noinline
+#define list_add_tail_rcu list_add_tail
+
+#define _THIS_IP_ CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
new file mode 100644
index 0000000..94d598b
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
@@ -0,0 +1,8 @@
+#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+
+static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h
new file mode 100644
index 0000000..6e9ef31
--- /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 0000000..1ed83a5
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LOCKDEP_H_
+#define _LIBLOCKDEP_LOCKDEP_H_
+
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <limits.h>
+#include <linux/utsname.h>
+
+
+#define MAX_LOCK_DEPTH 200UL
+
+#include "../../../include/linux/lockdep.h"
+
+struct task_struct {
+	u64 curr_chain_key;
+	int lockdep_depth;
+	unsigned int lockdep_recursion;
+	struct held_lock held_locks[MAX_LOCK_DEPTH];
+	gfp_t lockdep_reclaim_gfp;
+	int pid;
+	char comm[17];
+};
+
+extern __thread struct task_struct current_obj;
+#define current (&current_obj)
+
+void liblockdep_init(void);
+void liblockdep_set_thread(void);
+
+#define debug_locks_off() 1
+#define task_pid_nr(tsk) ((tsk)->pid)
+
+#define KSYM_NAME_LEN 128
+#define printk printf
+
+#define KERN_ERR
+#define KERN_CONT
+
+#define list_del_rcu list_del
+
+#define atomic_t unsigned long
+#define atomic_inc(x) ((*(x))++)
+
+static struct new_utsname *init_utsname(void)
+{
+	static struct new_utsname n = (struct new_utsname) {
+		.release = "liblockdep",
+		.version = LIBLOCKDEP_VERSION,
+	};
+
+	return &n;
+}
+
+#define print_tainted() ""
+#define static_obj(x) 1
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/mm_types.h b/tools/lib/lockdep/uinclude/linux/mm_types.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h
new file mode 100644
index 0000000..09c7a7b
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/module.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_MODULE_H_
+#define _LIBLOCKDEP_LINUX_MODULE_H_
+
+#define module_param(name, type, perm)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h
new file mode 100644
index 0000000..0c27bdf
--- /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 0000000..d73fe6f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/prefetch.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_
+#define _LIBLOCKDEP_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#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 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h
new file mode 100644
index 0000000..4c99fcb
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/rcu.h
@@ -0,0 +1,16 @@
+#ifndef _LIBLOCKDEP_RCU_H_
+#define _LIBLOCKDEP_RCU_H_
+
+int rcu_scheduler_active;
+
+static inline int rcu_lockdep_current_cpu_online(void)
+{
+	return 1;
+}
+
+static inline int rcu_is_cpu_idle(void)
+{
+	return 1;
+}
+
+#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 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h
new file mode 100644
index 0000000..68c1aa2
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/spinlock.h
@@ -0,0 +1,25 @@
+#ifndef _LIBLOCKDEP_SPINLOCK_H_
+#define _LIBLOCKDEP_SPINLOCK_H_
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#define arch_spinlock_t pthread_mutex_t
+#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
+
+static inline void arch_spin_lock(arch_spinlock_t *mutex)
+{
+	pthread_mutex_lock(mutex);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *mutex)
+{
+	pthread_mutex_unlock(mutex);
+}
+
+static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
+{
+	return true;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h
new file mode 100644
index 0000000..39aecc6
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/stacktrace.h
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_
+#define _LIBLOCKDEP_LINUX_STACKTRACE_H_
+
+#include <execinfo.h>
+
+struct stack_trace {
+	unsigned int nr_entries, max_entries;
+	unsigned long *entries;
+	int skip;
+};
+
+static inline void print_stack_trace(struct stack_trace *trace, int spaces)
+{
+	backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1);
+}
+
+#define save_stack_trace(trace)	\
+	((trace)->nr_entries =	\
+		backtrace((void **)(trace)->entries, (trace)->max_entries))
+
+static inline int dump_stack(void)
+{
+	void *array[64];
+	size_t size;
+
+	size = backtrace(array, 64);
+	backtrace_symbols_fd(array, size, 1);
+
+	return 0;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h
new file mode 100644
index 0000000..05dfcd1
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/stringify.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_
+#define _LIBLOCKDEP_LINUX_STRINGIFY_H_
+
+#define __stringify_1(x...)	#x
+#define __stringify(x...)	__stringify_1(x)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/system.h b/tools/lib/lockdep/uinclude/linux/system.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h
new file mode 100644
index 0000000..929938f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/types.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LINUX_TYPES_H_
+#define _LIBLOCKDEP_LINUX_TYPES_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+struct page;
+struct kmem_cache;
+
+typedef unsigned gfp_t;
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/util.h b/tools/lib/lockdep/uinclude/linux/util.h
new file mode 100644
index 0000000..e69de29
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 0000000..e69de29
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 2/7] liblockdep: public headers for mutex implementation
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:51   ` [tip:core/locking] liblockdep: Add public headers for pthread_mutex_t implementation tip-bot for Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 3/7] liblockdep: mutex test suite Sasha Levin
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

These headers provide the same API as their pthread mutex counterparts.

The design here is to allow to easily switch to liblockdep lock validation
just by adding a "liblockdep_" to pthread_mutex_*() calls, which means that
it's easy to integrate liblockdep into existing codebases.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/lib/lockdep/include/liblockdep/common.h | 42 +++++++++++++++
 tools/lib/lockdep/include/liblockdep/mutex.h  | 73 +++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 tools/lib/lockdep/include/liblockdep/common.h
 create mode 100644 tools/lib/lockdep/include/liblockdep/mutex.h

diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h
new file mode 100644
index 0000000..b72f9c1
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/common.h
@@ -0,0 +1,42 @@
+#ifndef _LIBLOCKDEP_COMMON_H
+#define _LIBLOCKDEP_COMMON_H
+
+#include <pthread.h>
+
+#define CALLER_ADDR0 (__builtin_return_address(0))
+#define _THIS_IP_ CALLER_ADDR0
+#define NR_LOCKDEP_CACHING_CLASSES 2
+#define MAX_LOCKDEP_SUBCLASSES 8UL
+
+struct lockdep_subclass_key {
+	char __one_byte;
+};
+
+struct lock_class_key {
+	struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
+};
+
+struct lockdep_map {
+	struct lock_class_key	*key;
+	struct lock_class	*class_cache[NR_LOCKDEP_CACHING_CLASSES];
+	const char		*name;
+#ifdef CONFIG_LOCK_STAT
+	int			cpu;
+	unsigned long		ip;
+#endif
+};
+
+void liblockdep_init(void);
+void liblockdep_set_thread(void);
+void lockdep_init_map(struct lockdep_map *lock, const char *name,
+			struct lock_class_key *key, int subclass);
+void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+			int trylock, int read, int check,
+			struct lockdep_map *nest_lock, unsigned long ip);
+void lock_release(struct lockdep_map *lock, int nested,
+			unsigned long ip);
+
+#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
+	{ .name = (_name), .key = (void *)(_key), }
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h
new file mode 100644
index 0000000..5154a9d
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/mutex.h
@@ -0,0 +1,73 @@
+#ifndef _LIBLOCKDEP_MUTEX_H
+#define _LIBLOCKDEP_MUTEX_H
+
+#ifdef __USE_LIBLOCKDEP
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_mutex {
+	pthread_mutex_t mutex;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t;
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx)			\
+		(const struct liblockdep_pthread_mutex) {		\
+	.mutex = PTHREAD_MUTEX_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)),	\
+}
+
+static inline int __mutex_init(liblockdep_pthread_mutex_t *lock,
+				const char *name,
+				struct lock_class_key *key,
+				const pthread_mutexattr_t *__mutexattr)
+{
+	lockdep_init_map(&lock->dep_map, name, key, 0);
+	return pthread_mutex_init(&lock->mutex, __mutexattr);
+}
+
+#define liblockdep_pthread_mutex_init(mutex, mutexattr)		\
+({								\
+	static struct lock_class_key __key;			\
+								\
+	__mutex_init((mutex), #mutex, &__key, (mutexattr));	\
+})
+
+static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)ip);
+	return pthread_mutex_lock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_release(&lock->dep_map, 0, (unsigned long)ip);
+	return pthread_mutex_unlock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)ip);
+	return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
+{
+	return pthread_mutex_destroy(&lock->mutex);
+}
+
+#define pthread_mutex_t         liblockdep_pthread_mutex_t
+#define pthread_mutex_init      liblockdep_pthread_mutex_init
+#define pthread_mutex_lock      liblockdep_pthread_mutex_lock
+#define pthread_mutex_unlock    liblockdep_pthread_mutex_unlock
+#define pthread_mutex_trylock   liblockdep_pthread_mutex_trylock
+#define pthread_mutex_destroy   liblockdep_pthread_mutex_destroy
+
+#endif
+
+#endif
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 3/7] liblockdep: mutex test suite
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 2/7] liblockdep: public headers for mutex implementation Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:52   ` [tip:core/locking] liblockdep: Add pthread_mutex_t " tip-bot for Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 4/7] liblockdep: public headers for rwlock implementation Sasha Levin
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

This is a rather simple and basic test suite to test common locking
issues.

Beyond tests, it also shows how to use the library.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/lib/lockdep/run_tests.sh           | 15 +++++++++++++++
 tools/lib/lockdep/tests/AA.c             | 16 ++++++++++++++++
 tools/lib/lockdep/tests/ABBA.c           | 16 ++++++++++++++++
 tools/lib/lockdep/tests/ABBCCA.c         | 18 ++++++++++++++++++
 tools/lib/lockdep/tests/ABBCCDDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/ABCABC.c         | 18 ++++++++++++++++++
 tools/lib/lockdep/tests/ABCDBCDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/ABCDBDDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/common.h         | 12 ++++++++++++
 tools/lib/lockdep/tests/unlock_balance.c | 15 +++++++++++++++
 10 files changed, 170 insertions(+)
 create mode 100755 tools/lib/lockdep/run_tests.sh
 create mode 100644 tools/lib/lockdep/tests/AA.c
 create mode 100644 tools/lib/lockdep/tests/ABBA.c
 create mode 100644 tools/lib/lockdep/tests/ABBCCA.c
 create mode 100644 tools/lib/lockdep/tests/ABBCCDDA.c
 create mode 100644 tools/lib/lockdep/tests/ABCABC.c
 create mode 100644 tools/lib/lockdep/tests/ABCDBCDA.c
 create mode 100644 tools/lib/lockdep/tests/ABCDBDDA.c
 create mode 100644 tools/lib/lockdep/tests/common.h
 create mode 100644 tools/lib/lockdep/tests/unlock_balance.c

diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
new file mode 100755
index 0000000..4dd32d1
--- /dev/null
+++ b/tools/lib/lockdep/run_tests.sh
@@ -0,0 +1,15 @@
+#! /bin/bash
+
+make &> /dev/null
+
+for i in `ls tests/*.c`; do
+	testname=$(basename -s .c "$i")
+	gcc -o tests/$testname -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
+	echo -ne "$testname... "
+	if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then
+		echo "PASSED!"
+	else
+		echo "FAILED!"
+	fi
+	rm tests/$testname
+done
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c
new file mode 100644
index 0000000..933d32f
--- /dev/null
+++ b/tools/lib/lockdep/tests/AA.c
@@ -0,0 +1,16 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+	pthread_mutex_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+
+	pthread_mutex_lock(&a);
+	pthread_mutex_unlock(&b);
+	pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c
new file mode 100644
index 0000000..9f5146b
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBA.c
@@ -0,0 +1,16 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c
new file mode 100644
index 0000000..b7435d7
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBCCA.c
@@ -0,0 +1,18 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(c, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c
new file mode 100644
index 0000000..2425330
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBCCDDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+	pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c
new file mode 100644
index 0000000..2ee30fe
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCABC.c
@@ -0,0 +1,18 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, a);
+	LOCK_UNLOCK_2(b, c);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c
new file mode 100644
index 0000000..32d19d6
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCDBCDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblockdep_pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	liblockdep_pthread_mutex_init(&a, NULL);
+	liblockdep_pthread_mutex_init(&b, NULL);
+	liblockdep_pthread_mutex_init(&c, NULL);
+	liblockdep_pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c
new file mode 100644
index 0000000..850eaca
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCDBDDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+	pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(b, d);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h
new file mode 100644
index 0000000..d89e94d
--- /dev/null
+++ b/tools/lib/lockdep/tests/common.h
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_TEST_COMMON_H
+#define _LIBLOCKDEP_TEST_COMMON_H
+
+#define LOCK_UNLOCK_2(a, b)			\
+	do {					\
+		pthread_mutex_lock(&(a));	\
+		pthread_mutex_lock(&(b));	\
+		pthread_mutex_unlock(&(b));	\
+		pthread_mutex_unlock(&(a));	\
+	} while(0)
+
+#endif
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c
new file mode 100644
index 0000000..9dfaf97
--- /dev/null
+++ b/tools/lib/lockdep/tests/unlock_balance.c
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+	pthread_mutex_t a;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+
+	pthread_mutex_lock(&a);
+	pthread_mutex_unlock(&a);
+	pthread_mutex_unlock(&a);
+}
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 4/7] liblockdep: public headers for rwlock implementation
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 2/7] liblockdep: public headers for mutex implementation Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 3/7] liblockdep: mutex test suite Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:53   ` [tip:core/locking] liblockdep: Add public headers for pthread_rwlock_t implementation tip-bot for Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 5/7] liblockdep: rwlock test suite Sasha Levin
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

Both pthreads and lockdep support dealing with rwlocks, so here's the
liblockdep implementation for those.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/lib/lockdep/include/liblockdep/rwlock.h | 91 +++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 tools/lib/lockdep/include/liblockdep/rwlock.h

diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h
new file mode 100644
index 0000000..26f9a68
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/rwlock.h
@@ -0,0 +1,91 @@
+#ifndef _LIBLOCKDEP_RWLOCK_H
+#define _LIBLOCKDEP_RWLOCK_H
+
+#ifdef __USE_LIBLOCKDEP
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_rwlock {
+	pthread_rwlock_t rwlock;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t;
+
+#define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl)			\
+		(struct liblockdep_pthread_rwlock) {			\
+	.rwlock = PTHREAD_RWLOCK_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)),	\
+}
+
+static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock,
+				const char *name,
+				struct lock_class_key *key,
+				const pthread_rwlockattr_t *attr)
+{
+	lockdep_init_map(&lock->dep_map, name, key, 0);
+
+	return pthread_rwlock_init(&lock->rwlock, attr);
+}
+
+#define liblockdep_pthread_rwlock_init(lock, attr)		\
+({							\
+	static struct lock_class_key __key;		\
+							\
+	__rwlock_init((lock), #lock, &__key, (attr));	\
+})
+
+static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_rdlock(&lock->rwlock);
+
+}
+
+static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_release(&lock->dep_map, 0, (unsigned long)ip);
+	return pthread_rwlock_unlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_wrlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
+{
+	return pthread_rwlock_destroy(&lock->rwlock);
+}
+
+#define pthread_rwlock_t		liblockdep_pthread_rwlock_t
+#define pthread_rwlock_init		liblockdep_pthread_rwlock_init
+#define pthread_rwlock_rdlock		liblockdep_pthread_rwlock_rdlock
+#define pthread_rwlock_unlock		liblockdep_pthread_rwlock_unlock
+#define pthread_rwlock_wrlock		liblockdep_pthread_rwlock_wrlock
+#define pthread_rwlock_tryrdlock	liblockdep_pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywlock		liblockdep_pthread_rwlock_trywlock
+#define pthread_rwlock_destroy		liblockdep_rwlock_destroy
+
+#endif
+
+#endif
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 5/7] liblockdep: rwlock test suite
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (2 preceding siblings ...)
  2013-02-04  1:50 ` [PATCH v3 4/7] liblockdep: public headers for rwlock implementation Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:55   ` [tip:core/locking] liblockdep: Add pthread_rwlock_t " tip-bot for Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 6/7] liblockdep: add a MAINTAINERS entry Sasha Levin
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

A simple test to make sure we handle rwlocks correctly.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/lib/lockdep/tests/WW.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 tools/lib/lockdep/tests/WW.c

diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c
new file mode 100644
index 0000000..4b1be0f
--- /dev/null
+++ b/tools/lib/lockdep/tests/WW.c
@@ -0,0 +1,16 @@
+#include <liblockdep/rwlock.h>
+
+void main(void)
+{
+	pthread_rwlock_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_rwlock_init(&a, NULL);
+	pthread_rwlock_init(&b, NULL);
+
+	pthread_rwlock_wrlock(&a);
+	pthread_rwlock_rdlock(&b);
+	pthread_rwlock_wrlock(&a);
+}
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 6/7] liblockdep: add a MAINTAINERS entry
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (3 preceding siblings ...)
  2013-02-04  1:50 ` [PATCH v3 5/7] liblockdep: rwlock test suite Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:56   ` [tip:core/locking] liblockdep: Add " tip-bot for Sasha Levin
  2013-02-04  1:50 ` [PATCH v3 7/7] perf: integrate liblockdep support into perf Sasha Levin
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 212c255..a64abfb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4637,6 +4637,11 @@ F:	drivers/lguest/
 F:	include/linux/lguest*.h
 F:	tools/lguest/
 
+LIBLOCK
+M:	Sasha Levin <sasha.levin@oracle.com>
+S:	Maintained
+F:	tools/lib/lockdep/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:	Paul Mackerras <paulus@au.ibm.com>
 W:	http://www.ibm.com/linux/ltc/projects/ppc
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 7/7] perf: integrate liblockdep support into perf
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (4 preceding siblings ...)
  2013-02-04  1:50 ` [PATCH v3 6/7] liblockdep: add a MAINTAINERS entry Sasha Levin
@ 2013-02-04  1:50 ` Sasha Levin
  2013-02-04 13:57   ` [tip:core/locking] perf: Integrate " tip-bot for Sasha Levin
  2013-02-21 17:16   ` [PATCH] perf: define LIBLOCKDEP_LIBS to fix linker errors Dongsu Park
  2013-02-04 10:48 ` [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Ingo Molnar
  2013-02-04 13:48 ` [tip:core/locking] liblockdep: Wrap kernel/ lockdep.c " tip-bot for Sasha Levin
  7 siblings, 2 replies; 16+ messages in thread
From: Sasha Levin @ 2013-02-04  1:50 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

liblockdep is simply userspace lockdep. We can use that to analyze and
verify the locking in perf.

Usage is simple, to compile perf with liblockdep all that's needed it:

	make LOCKDEP=1

Once liblockdep support is compiled in, perf will yell if locking goes
wrong for any reason:

=============================================
[ INFO: possible recursive locking detected ]
liblockdep 0.0.1
---------------------------------------------
perf/23237 is trying to acquire lock:
 (sched.start_work_mutex){......}, at: ./perf() [0x419793]

but task is already holding lock:
 (sched.start_work_mutex){......}, at: ./perf() [0x419793]

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(sched.start_work_mutex);
  lock(sched.start_work_mutex);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by perf/23237:
 #0:  (sched.start_work_mutex){......}, at: ./perf() [0x419793]
 #1:  (sched.work_done_wait_mutex){......}, at: ./perf() [0x419793]

stack backtrace:
/usr/lib64/liblockdep.so(+0x1ba0)[0x7fa067f99ba0]
/usr/lib64/liblockdep.so(+0x37bf)[0x7fa067f9b7bf]
/usr/lib64/liblockdep.so(+0x3899)[0x7fa067f9b899]
/usr/lib64/liblockdep.so(+0x429a)[0x7fa067f9c29a]
/usr/lib64/liblockdep.so(+0x4db1)[0x7fa067f9cdb1]
/usr/lib64/liblockdep.so(lock_acquire+0x97)[0x7fa067f9d8b4]
./perf(cmd_sched+0xb166)[0x42d976]
./perf[0x419793]
./perf(main+0x529)[0x418f59]
/lib64/libc.so.6(__libc_start_main+0xed)[0x7fa063ae591d]
./perf[0x4190d9]

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
 tools/perf/Makefile                 | 22 ++++++++++++++++++++++
 tools/perf/builtin-sched.c          |  6 ++++--
 tools/perf/builtin-top.c            |  4 ++++
 tools/perf/config/feature-tests.mak | 12 ++++++++++++
 tools/perf/perf.c                   |  3 +++
 tools/perf/ui/setup.c               |  5 ++++-
 tools/perf/util/hist.h              |  1 +
 tools/perf/util/liblockdep.h        | 11 +++++++++++
 tools/perf/util/util.h              |  1 +
 9 files changed, 62 insertions(+), 3 deletions(-)
 create mode 100644 tools/perf/util/liblockdep.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8ab05e5..785cd51 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -572,6 +572,21 @@ ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
 endif # Libunwind support
 endif # NO_LIBUNWIND
 
+ifndef NO_LIBLOCKDEP
+# for linking with liblockdep library, run like:
+# make LIBLOCKDEP=1
+ifeq ($(LOCKDEP),1)
+	LIBLOCKDEP_CFLAGS  := -I../lib/lockdep/include -D__USE_LIBLOCKDEP
+	LIBLOCKDEP_LDFLAGS := -L../lib/lockdep/ -llockdep
+endif
+
+FLAGS_LIBLOCKDEP=$(LIBLOCKDEP_CFLAGS) $(ALL_CFLAGS) $(LIBLOCKDEP_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
+ifneq ($(call try-cc,$(SOURCE_LIBLOCKDEP),$(FLAGS_LIBLOCKDEP),liblockdep),y)
+	msg := $(warning No liblockdep support.);
+	NO_LIBLOCKDEP := 1
+endif # liblockdep support
+endif # NO_LIBLOCKDEP
+
 -include arch/$(ARCH)/Makefile
 
 ifneq ($(OUTPUT),)
@@ -621,6 +636,13 @@ ifndef NO_LIBUNWIND
 	LIB_OBJS += $(OUTPUT)util/unwind.o
 endif
 
+ifndef NO_LIBLOCKDEP
+	BASIC_CFLAGS += -D__USE_LIBLOCKDEP
+	EXTLIBS += $(LIBLOCKDEP_LIBS)
+	BASIC_CFLAGS := $(LIBLOCKDEP_CFLAGS) $(BASIC_CFLAGS)
+	BASIC_LDFLAGS := $(LIBLOCKDEP_LDFLAGS) $(BASIC_LDFLAGS)
+endif
+
 ifndef NO_LIBAUDIT
 	FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
 	ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index cc28b85..53d9225 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -468,6 +468,8 @@ static void *thread_func(void *ctx)
 	char comm2[22];
 	int fd;
 
+	liblockdep_set_thread();
+
 	free(parms);
 
 	sprintf(comm2, ":%s", this_task->comm);
@@ -1677,8 +1679,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
 		},
 		.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
 		.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
-		.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
-		.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.start_work_mutex     = LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(sched.start_work_mutex),
+		.work_done_wait_mutex = LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(sched.work_done_wait_mutex),
 		.curr_pid	      = { [0 ... MAX_CPUS - 1] = -1 },
 		.sort_order	      = default_sort_order,
 		.replay_repeat	      = 10,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff395..c9b99ef 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -588,6 +588,8 @@ static void *display_thread_tui(void *arg)
 		.refresh	= top->delay_secs,
 	};
 
+	liblockdep_set_thread();
+
 	perf_top__sort_new_samples(top);
 
 	/*
@@ -613,6 +615,8 @@ static void *display_thread(void *arg)
 	struct perf_top *top = arg;
 	int delay_msecs, c;
 
+	liblockdep_set_thread();
+
 	tcgetattr(0, &save);
 	tc = save;
 	tc.c_lflag &= ~(ICANON | ECHO);
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index f5ac774..1f5a37e 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -217,6 +217,18 @@ int main(void)
 endef
 endif
 
+ifndef NO_LIBLOCKDEP
+define SOURCE_LIBLOCKDEP
+#include <liblockdep/mutex.h>
+
+int main(void)
+{
+	liblockdep_init();
+	return 0;
+}
+endef
+endif
+
 define SOURCE_ON_EXIT
 #include <stdio.h>
 
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 0f661fb..ddbd315 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -446,6 +446,9 @@ int main(int argc, const char **argv)
 {
 	const char *cmd;
 
+	liblockdep_init();
+	liblockdep_set_thread();
+
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ebb4cc1..5c0cdeb 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -3,14 +3,17 @@
 #include "../util/cache.h"
 #include "../util/debug.h"
 #include "../util/hist.h"
+#include "../util/liblockdep.h"
 
-pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t ui__lock;
 
 void setup_browser(bool fallback_to_pager)
 {
 	if (!isatty(1) || dump_trace)
 		use_browser = 0;
 
+	pthread_mutex_init(&ui__lock, NULL);
+
 	/* default to TUI */
 	if (use_browser < 0)
 		use_browser = 1;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8b091a5..328afe0 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -5,6 +5,7 @@
 #include <pthread.h>
 #include "callchain.h"
 #include "header.h"
+#include "liblockdep.h"
 
 extern struct callchain_param callchain_param;
 
diff --git a/tools/perf/util/liblockdep.h b/tools/perf/util/liblockdep.h
new file mode 100644
index 0000000..628a2f5
--- /dev/null
+++ b/tools/perf/util/liblockdep.h
@@ -0,0 +1,11 @@
+#ifdef __USE_LIBLOCKDEP
+
+#include <liblockdep/mutex.h>
+
+#else
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx) PTHREAD_MUTEX_INITIALIZER
+#define liblockdep_init()
+#define liblockdep_set_thread()
+
+#endif
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c233091..06e6244 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -73,6 +73,7 @@
 #include <linux/magic.h>
 #include "types.h"
 #include <sys/ttydefaults.h>
+#include "liblockdep.h"
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (5 preceding siblings ...)
  2013-02-04  1:50 ` [PATCH v3 7/7] perf: integrate liblockdep support into perf Sasha Levin
@ 2013-02-04 10:48 ` Ingo Molnar
  2013-02-04 13:48 ` [tip:core/locking] liblockdep: Wrap kernel/ lockdep.c " tip-bot for Sasha Levin
  7 siblings, 0 replies; 16+ messages in thread
From: Ingo Molnar @ 2013-02-04 10:48 UTC (permalink / raw)
  To: Sasha Levin, Arnaldo Carvalho de Melo
  Cc: mingo, peterz, paulus, acme, penberg, linux-kernel


Ok, these liblockdep bits look really good and clean, and the 
perf integration is obviously useful. It does not conflict with 
any pending tools/perf work either.

Arnaldo, are you fine with:

  b2e7c77a3790 perf: Integrate liblockdep support into perf

?

We could keep it separate in tip:core/locking, no merge into 
tip:perf/core appears to be necessary for the time being.

A couple of suggestions:

1) One thing that is I think is missing is a fun to read 
tools/lib/lockdep/README that explains how to use it all for 
pthread_mutex_t and pthread_rwlock_t checking, and what the 
limitations are (if any).

2) Explicitly mentioning that the code and library is licensed 
under the kernel's GPL would be nice as well, for additional 
clarity - should anyone decide to package it up in distros.

3) Advanced: providing a shell environment variable (LOCKDEP=1?) 
as a way to enable it might be useful as well: that way tools 
could be built with lockdep built in but turned off by default - 
which can be turned on again on demand. It would only constitute 
some data structure overhead, a runtime check in the locking 
wrappers and a bit of an initialization overhead.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Wrap kernel/ lockdep.c to allow usage from userspace
  2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (6 preceding siblings ...)
  2013-02-04 10:48 ` [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Ingo Molnar
@ 2013-02-04 13:48 ` tip-bot for Sasha Levin
  7 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:48 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  d8685a659c9ed8c23af0bb69289d51ad9a05bf84
Gitweb:     http://git.kernel.org/tip/d8685a659c9ed8c23af0bb69289d51ad9a05bf84
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:38 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:04 +0100

liblockdep: Wrap kernel/lockdep.c to allow usage from userspace

kernel/lockdep.c deals with validating locking scenarios for
various architectures supported by the kernel. There isn't
anything kernel specific going on in lockdep, and when we
compare userspace to other architectures that don't have to deal
with irqs such as s390, they become all too similar.

We wrap kernel/lockdep.c and include/linux/lockdep.h with
several headers which allow us to build and use lockdep from
userspace. We don't touch the kernel code itself which means
that any work done on lockdep in the kernel will automatically
benefit userspace lockdep as well!

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-1-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/lib/lockdep/Makefile                         | 247 +++++++++++++++++++++
 tools/lib/lockdep/common.c                         |  22 ++
 tools/lib/lockdep/lockdep.c                        |   2 +
 tools/lib/lockdep/lockdep_internals.h              |   1 +
 tools/lib/lockdep/lockdep_states.h                 |   1 +
 .../lockdep/uinclude/asm/hweight.h}                |   0
 .../lockdep/uinclude/asm/sections.h}               |   0
 .../lockdep/uinclude/linux/bitops.h}               |   0
 tools/lib/lockdep/uinclude/linux/compiler.h        |   7 +
 tools/lib/lockdep/uinclude/linux/debug_locks.h     |  12 +
 .../lockdep/uinclude/linux/delay.h}                |   0
 tools/lib/lockdep/uinclude/linux/export.h          |   7 +
 .../lockdep/uinclude/linux/ftrace.h}               |   0
 .../hrtimer.h => lib/lockdep/uinclude/linux/gfp.h} |   0
 tools/lib/lockdep/uinclude/linux/hardirq.h         |  11 +
 tools/lib/lockdep/uinclude/linux/hash.h            |   1 +
 .../lockdep/uinclude/linux/interrupt.h}            |   0
 tools/lib/lockdep/uinclude/linux/irqflags.h        |  38 ++++
 tools/lib/lockdep/uinclude/linux/kallsyms.h        |  32 +++
 tools/lib/lockdep/uinclude/linux/kernel.h          |  34 +++
 tools/lib/lockdep/uinclude/linux/kmemcheck.h       |   8 +
 .../lockdep/uinclude/linux/linkage.h}              |   0
 tools/lib/lockdep/uinclude/linux/list.h            |   1 +
 tools/lib/lockdep/uinclude/linux/lockdep.h         |  58 +++++
 .../lockdep/uinclude/linux/mm_types.h}             |   0
 tools/lib/lockdep/uinclude/linux/module.h          |   6 +
 .../lockdep/uinclude/linux/mutex.h}                |   0
 tools/lib/lockdep/uinclude/linux/poison.h          |   1 +
 tools/lib/lockdep/uinclude/linux/prefetch.h        |   6 +
 .../lockdep/uinclude/linux/proc_fs.h}              |   0
 tools/lib/lockdep/uinclude/linux/rcu.h             |  16 ++
 .../lockdep/uinclude/linux/seq_file.h}             |   0
 tools/lib/lockdep/uinclude/linux/spinlock.h        |  25 +++
 tools/lib/lockdep/uinclude/linux/stacktrace.h      |  32 +++
 tools/lib/lockdep/uinclude/linux/stringify.h       |   7 +
 .../lockdep/uinclude/linux/system.h}               |   0
 tools/lib/lockdep/uinclude/linux/types.h           |  58 +++++
 .../lockdep/uinclude/linux/util.h}                 |   0
 .../lockdep/uinclude/trace/events/lock.h}          |   0
 39 files changed, 633 insertions(+)

diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
new file mode 100644
index 0000000..e82ffe9
--- /dev/null
+++ b/tools/lib/lockdep/Makefile
@@ -0,0 +1,247 @@
+# liblockdep version
+LL_VERSION = 0
+LL_PATCHLEVEL = 0
+LL_EXTRAVERSION = 1
+
+# file format version
+FILE_VERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+prefix ?= /usr/local
+bindir_relative = lib
+bindir = $(prefix)/$(bindir_relative)
+
+export DESTDIR DESTDIR_SQ INSTALL
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+  VERBOSE = $(V)
+endif
+ifndef VERBOSE
+  VERBOSE = 0
+endif
+
+ifeq ("$(origin O)", "command line")
+  BUILD_OUTPUT := $(O)
+endif
+
+ifeq ($(BUILD_SRC),)
+ifneq ($(BUILD_OUTPUT),)
+
+define build_output
+	$(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) 	\
+	BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+endef
+
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(BUILD_OUTPUT),, \
+     $(error output directory "$(saved-output)" does not exist))
+
+all: sub-make
+
+gui: force
+	$(call build_output, all_cmd)
+
+$(filter-out gui,$(MAKECMDGOALS)): sub-make
+
+sub-make: force
+	$(call build_output, $(MAKECMDGOALS))
+
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+
+endif # BUILD_OUTPUT
+endif # BUILD_SRC
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+srctree		:= $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
+objtree		:= $(CURDIR)
+src		:= $(srctree)
+obj		:= $(objtree)
+
+export prefix bindir src obj
+
+# Shell quotes
+bindir_SQ = $(subst ','\'',$(bindir))
+bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
+
+LIB_FILE = liblockdep.a liblockdep.so
+
+CONFIG_INCLUDES =
+CONFIG_LIBS	=
+CONFIG_FLAGS	=
+
+OBJ		= $@
+N		=
+
+export Q VERBOSE
+
+LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
+
+INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES)
+
+# Set compile option CFLAGS if not set elsewhere
+CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=64 -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic
+
+override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
+
+ifeq ($(VERBOSE),1)
+  Q =
+  print_compile =
+  print_app_build =
+  print_fpic_compile =
+  print_shared_lib_compile =
+  print_install =
+else
+  Q = @
+  print_compile =		echo '  CC                 '$(OBJ);
+  print_app_build =		echo '  BUILD              '$(OBJ);
+  print_fpic_compile =		echo '  CC FPIC            '$(OBJ);
+  print_shared_lib_compile =	echo '  BUILD SHARED LIB   '$(OBJ);
+  print_static_lib_build =	echo '  BUILD STATIC LIB   '$(OBJ);
+  print_install =		echo '  INSTALL     '$1'	to	$(DESTDIR_SQ)$2';
+endif
+
+do_fpic_compile =					\
+	($(print_fpic_compile)				\
+	$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
+
+do_app_build =						\
+	($(print_app_build)				\
+	$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+
+do_compile_shared_library =			\
+	($(print_shared_lib_compile)		\
+	$(CC) --shared $^ -o $@)
+
+do_build_static_lib =				\
+	($(print_static_lib_build)		\
+	$(RM) $@;  $(AR) rcs $@ $^)
+
+
+define do_compile
+	$(print_compile)						\
+	$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+endef
+
+$(obj)/%.o: $(src)/%.c
+	$(Q)$(call do_compile)
+
+%.o: $(src)/%.c
+	$(Q)$(call do_compile)
+
+PEVENT_LIB_OBJS = common.o lockdep.o
+
+ALL_OBJS = $(PEVENT_LIB_OBJS)
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+
+all: all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+liblockdep.so: $(PEVENT_LIB_OBJS)
+	$(Q)$(do_compile_shared_library)
+
+liblockdep.a: $(PEVENT_LIB_OBJS)
+	$(Q)$(do_build_static_lib)
+
+$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
+	$(Q)$(do_fpic_compile)
+
+## make deps
+
+all_objs := $(sort $(ALL_OBJS))
+all_deps := $(all_objs:%.o=.%.d)
+
+# let .d file also depends on the source and header files
+define check_deps
+		@set -e; $(RM) $@; \
+		$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+		sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+		$(RM) $@.$$$$
+endef
+
+$(all_deps): .%.d: $(src)/%.c
+	$(Q)$(call check_deps)
+
+$(all_objs) : %.o : .%.d
+
+dep_includes := $(wildcard $(all_deps))
+
+ifneq ($(dep_includes),)
+ include $(dep_includes)
+endif
+
+### Detect environment changes
+TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
+
+tags:	force
+	$(RM) tags
+	find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+	--regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+
+TAGS:	force
+	$(RM) TAGS
+	find . -name '*.[ch]' | xargs etags \
+	--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+
+define do_install
+	$(print_install)				\
+	if [ ! -d '$(DESTDIR_SQ)$2' ]; then		\
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2';	\
+	fi;						\
+	$(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd
+	$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
+
+install: install_lib
+
+clean:
+	$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
+	$(RM) tags TAGS
+
+endif # skip-makefile
+
+PHONY += force
+force:
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
new file mode 100644
index 0000000..99d3b4b
--- /dev/null
+++ b/tools/lib/lockdep/common.c
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <linux/compiler.h>
+#include <linux/lockdep.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+__thread struct task_struct current_obj;
+
+bool debug_locks = true;
+bool debug_locks_silent;
+
+void liblockdep_init(void)
+{
+	lockdep_init();
+}
+
+void liblockdep_set_thread(void)
+{
+	prctl(PR_GET_NAME, current->comm);
+	current->pid = syscall(__NR_gettid);
+}
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
new file mode 100644
index 0000000..8ddd0ff
--- /dev/null
+++ b/tools/lib/lockdep/lockdep.c
@@ -0,0 +1,2 @@
+#include <linux/lockdep.h>
+#include "../../../kernel/lockdep.c"
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h
new file mode 100644
index 0000000..109e96f
--- /dev/null
+++ b/tools/lib/lockdep/lockdep_internals.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_internals.h"
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h
new file mode 100644
index 0000000..6b75423
--- /dev/null
+++ b/tools/lib/lockdep/lockdep_states.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_states.h"
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/asm/hweight.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/asm/hweight.h
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/asm/sections.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/asm/sections.h
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/bitops.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/bitops.h
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h
new file mode 100644
index 0000000..7ac838a
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/compiler.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_COMPILER_H_
+#define _LIBLOCKDEP_LINUX_COMPILER_H_
+
+#define __used		__attribute__((__unused__))
+#define unlikely
+
+#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 0000000..f38eb64
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/debug_locks.h
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_
+#define _LIBLOCKDEP_DEBUG_LOCKS_H_
+
+#include <stddef.h>
+#include <linux/compiler.h>
+
+#define DEBUG_LOCKS_WARN_ON(x) (x)
+
+extern bool debug_locks;
+extern bool debug_locks_silent;
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/delay.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/delay.h
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h
new file mode 100644
index 0000000..6bdf349
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/export.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_EXPORT_H_
+#define _LIBLOCKDEP_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/ftrace.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/ftrace.h
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/gfp.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/gfp.h
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h
new file mode 100644
index 0000000..c8f3f8f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/hardirq.h
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_
+#define _LIBLOCKDEP_LINUX_HARDIRQ_H_
+
+#define SOFTIRQ_BITS	0UL
+#define HARDIRQ_BITS	0UL
+#define SOFTIRQ_SHIFT	0UL
+#define HARDIRQ_SHIFT	0UL
+#define hardirq_count()	0UL
+#define softirq_count()	0UL
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h
new file mode 100644
index 0000000..0f84798
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/hash.h
@@ -0,0 +1 @@
+#include "../../../include/linux/hash.h"
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/interrupt.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/interrupt.h
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h
new file mode 100644
index 0000000..6cc296f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/irqflags.h
@@ -0,0 +1,38 @@
+#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+
+# define trace_hardirq_context(p)	0
+# define trace_softirq_context(p)	0
+# define trace_hardirqs_enabled(p)	0
+# define trace_softirqs_enabled(p)	0
+# define trace_hardirq_enter()		do { } while (0)
+# define trace_hardirq_exit()		do { } while (0)
+# define lockdep_softirq_enter()	do { } while (0)
+# define lockdep_softirq_exit()		do { } while (0)
+# define INIT_TRACE_IRQFLAGS
+
+# define stop_critical_timings() do { } while (0)
+# define start_critical_timings() do { } while (0)
+
+#define raw_local_irq_disable() do { } while (0)
+#define raw_local_irq_enable() do { } while (0)
+#define raw_local_irq_save(flags) ((flags) = 0)
+#define raw_local_irq_restore(flags) do { } while (0)
+#define raw_local_save_flags(flags) ((flags) = 0)
+#define raw_irqs_disabled_flags(flags) do { } while (0)
+#define raw_irqs_disabled() 0
+#define raw_safe_halt()
+
+#define local_irq_enable() do { } while (0)
+#define local_irq_disable() do { } while (0)
+#define local_irq_save(flags) ((flags) = 0)
+#define local_irq_restore(flags) do { } while (0)
+#define local_save_flags(flags)	((flags) = 0)
+#define irqs_disabled() (1)
+#define irqs_disabled_flags(flags) (0)
+#define safe_halt() do { } while (0)
+
+#define trace_lock_release(x, y)
+#define trace_lock_acquire(a, b, c, d, e, f, g)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h
new file mode 100644
index 0000000..b0f2dbd
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kallsyms.h
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_
+#define _LIBLOCKDEP_LINUX_KALLSYMS_H_
+
+#include <linux/kernel.h>
+#include <stdio.h>
+
+#define KSYM_NAME_LEN 128
+
+struct module;
+
+static inline const char *kallsyms_lookup(unsigned long addr,
+					  unsigned long *symbolsize,
+					  unsigned long *offset,
+					  char **modname, char *namebuf)
+{
+	return NULL;
+}
+
+#include <execinfo.h>
+#include <stdlib.h>
+static inline void print_ip_sym(unsigned long ip)
+{
+	char **name;
+
+	name = backtrace_symbols((void **)&ip, 1);
+
+	printf("%s\n", *name);
+
+	free(name);
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h
new file mode 100644
index 0000000..da97ce8
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kernel.h
@@ -0,0 +1,34 @@
+#ifndef _LIBLOCKDEP_LINUX_KERNEL_H_
+#define _LIBLOCKDEP_LINUX_KERNEL_H_
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/rcu.h>
+#include <linux/hardirq.h>
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({			\
+	const typeof(((type *)0)->member) * __mptr = (ptr);	\
+	(type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define WARN_ON(x) (x)
+#define WARN_ON_ONCE(x) (x)
+#define likely(x) (x)
+#define WARN(x, y, z) (x)
+#define uninitialized_var(x) x
+#define __init
+#define noinline
+#define list_add_tail_rcu list_add_tail
+
+#define _THIS_IP_ CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
new file mode 100644
index 0000000..94d598b
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
@@ -0,0 +1,8 @@
+#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+
+static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+}
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/linkage.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/linkage.h
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h
new file mode 100644
index 0000000..6e9ef31
--- /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 0000000..1ed83a5
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LOCKDEP_H_
+#define _LIBLOCKDEP_LOCKDEP_H_
+
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <limits.h>
+#include <linux/utsname.h>
+
+
+#define MAX_LOCK_DEPTH 200UL
+
+#include "../../../include/linux/lockdep.h"
+
+struct task_struct {
+	u64 curr_chain_key;
+	int lockdep_depth;
+	unsigned int lockdep_recursion;
+	struct held_lock held_locks[MAX_LOCK_DEPTH];
+	gfp_t lockdep_reclaim_gfp;
+	int pid;
+	char comm[17];
+};
+
+extern __thread struct task_struct current_obj;
+#define current (&current_obj)
+
+void liblockdep_init(void);
+void liblockdep_set_thread(void);
+
+#define debug_locks_off() 1
+#define task_pid_nr(tsk) ((tsk)->pid)
+
+#define KSYM_NAME_LEN 128
+#define printk printf
+
+#define KERN_ERR
+#define KERN_CONT
+
+#define list_del_rcu list_del
+
+#define atomic_t unsigned long
+#define atomic_inc(x) ((*(x))++)
+
+static struct new_utsname *init_utsname(void)
+{
+	static struct new_utsname n = (struct new_utsname) {
+		.release = "liblockdep",
+		.version = LIBLOCKDEP_VERSION,
+	};
+
+	return &n;
+}
+
+#define print_tainted() ""
+#define static_obj(x) 1
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/mm_types.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/mm_types.h
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h
new file mode 100644
index 0000000..09c7a7b
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/module.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_MODULE_H_
+#define _LIBLOCKDEP_LINUX_MODULE_H_
+
+#define module_param(name, type, perm)
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/mutex.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/mutex.h
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h
new file mode 100644
index 0000000..0c27bdf
--- /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 0000000..d73fe6f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/prefetch.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_
+#define _LIBLOCKDEP_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/proc_fs.h
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h
new file mode 100644
index 0000000..4c99fcb
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/rcu.h
@@ -0,0 +1,16 @@
+#ifndef _LIBLOCKDEP_RCU_H_
+#define _LIBLOCKDEP_RCU_H_
+
+int rcu_scheduler_active;
+
+static inline int rcu_lockdep_current_cpu_online(void)
+{
+	return 1;
+}
+
+static inline int rcu_is_cpu_idle(void)
+{
+	return 1;
+}
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/seq_file.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/seq_file.h
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h
new file mode 100644
index 0000000..68c1aa2
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/spinlock.h
@@ -0,0 +1,25 @@
+#ifndef _LIBLOCKDEP_SPINLOCK_H_
+#define _LIBLOCKDEP_SPINLOCK_H_
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#define arch_spinlock_t pthread_mutex_t
+#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
+
+static inline void arch_spin_lock(arch_spinlock_t *mutex)
+{
+	pthread_mutex_lock(mutex);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *mutex)
+{
+	pthread_mutex_unlock(mutex);
+}
+
+static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
+{
+	return true;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h
new file mode 100644
index 0000000..39aecc6
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/stacktrace.h
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_
+#define _LIBLOCKDEP_LINUX_STACKTRACE_H_
+
+#include <execinfo.h>
+
+struct stack_trace {
+	unsigned int nr_entries, max_entries;
+	unsigned long *entries;
+	int skip;
+};
+
+static inline void print_stack_trace(struct stack_trace *trace, int spaces)
+{
+	backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1);
+}
+
+#define save_stack_trace(trace)	\
+	((trace)->nr_entries =	\
+		backtrace((void **)(trace)->entries, (trace)->max_entries))
+
+static inline int dump_stack(void)
+{
+	void *array[64];
+	size_t size;
+
+	size = backtrace(array, 64);
+	backtrace_symbols_fd(array, size, 1);
+
+	return 0;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h
new file mode 100644
index 0000000..05dfcd1
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/stringify.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_
+#define _LIBLOCKDEP_LINUX_STRINGIFY_H_
+
+#define __stringify_1(x...)	#x
+#define __stringify(x...)	__stringify_1(x)
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/system.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/system.h
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h
new file mode 100644
index 0000000..929938f
--- /dev/null
+++ b/tools/lib/lockdep/uinclude/linux/types.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LINUX_TYPES_H_
+#define _LIBLOCKDEP_LINUX_TYPES_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+struct page;
+struct kmem_cache;
+
+typedef unsigned gfp_t;
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#endif
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/linux/util.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/linux/util.h
diff --git a/tools/virtio/linux/hrtimer.h b/tools/lib/lockdep/uinclude/trace/events/lock.h
similarity index 100%
copy from tools/virtio/linux/hrtimer.h
copy to tools/lib/lockdep/uinclude/trace/events/lock.h

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Add public headers for pthread_mutex_t implementation
  2013-02-04  1:50 ` [PATCH v3 2/7] liblockdep: public headers for mutex implementation Sasha Levin
@ 2013-02-04 13:51   ` tip-bot for Sasha Levin
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:51 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  0ebd64ee0f225028c5a97581cdfeeb15931ec35c
Gitweb:     http://git.kernel.org/tip/0ebd64ee0f225028c5a97581cdfeeb15931ec35c
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:39 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:04 +0100

liblockdep: Add public headers for pthread_mutex_t implementation

These headers provide the same API as their pthread mutex
counterparts.

The design here is to allow to easily switch to liblockdep lock
validation just by adding a "liblockdep_" to pthread_mutex_*()
calls, which means that it's easy to integrate liblockdep into
existing codebases.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-2-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/lib/lockdep/include/liblockdep/common.h | 42 +++++++++++++++
 tools/lib/lockdep/include/liblockdep/mutex.h  | 73 +++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h
new file mode 100644
index 0000000..b72f9c1
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/common.h
@@ -0,0 +1,42 @@
+#ifndef _LIBLOCKDEP_COMMON_H
+#define _LIBLOCKDEP_COMMON_H
+
+#include <pthread.h>
+
+#define CALLER_ADDR0 (__builtin_return_address(0))
+#define _THIS_IP_ CALLER_ADDR0
+#define NR_LOCKDEP_CACHING_CLASSES 2
+#define MAX_LOCKDEP_SUBCLASSES 8UL
+
+struct lockdep_subclass_key {
+	char __one_byte;
+};
+
+struct lock_class_key {
+	struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
+};
+
+struct lockdep_map {
+	struct lock_class_key	*key;
+	struct lock_class	*class_cache[NR_LOCKDEP_CACHING_CLASSES];
+	const char		*name;
+#ifdef CONFIG_LOCK_STAT
+	int			cpu;
+	unsigned long		ip;
+#endif
+};
+
+void liblockdep_init(void);
+void liblockdep_set_thread(void);
+void lockdep_init_map(struct lockdep_map *lock, const char *name,
+			struct lock_class_key *key, int subclass);
+void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+			int trylock, int read, int check,
+			struct lockdep_map *nest_lock, unsigned long ip);
+void lock_release(struct lockdep_map *lock, int nested,
+			unsigned long ip);
+
+#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
+	{ .name = (_name), .key = (void *)(_key), }
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h
new file mode 100644
index 0000000..5154a9d
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/mutex.h
@@ -0,0 +1,73 @@
+#ifndef _LIBLOCKDEP_MUTEX_H
+#define _LIBLOCKDEP_MUTEX_H
+
+#ifdef __USE_LIBLOCKDEP
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_mutex {
+	pthread_mutex_t mutex;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t;
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx)			\
+		(const struct liblockdep_pthread_mutex) {		\
+	.mutex = PTHREAD_MUTEX_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)),	\
+}
+
+static inline int __mutex_init(liblockdep_pthread_mutex_t *lock,
+				const char *name,
+				struct lock_class_key *key,
+				const pthread_mutexattr_t *__mutexattr)
+{
+	lockdep_init_map(&lock->dep_map, name, key, 0);
+	return pthread_mutex_init(&lock->mutex, __mutexattr);
+}
+
+#define liblockdep_pthread_mutex_init(mutex, mutexattr)		\
+({								\
+	static struct lock_class_key __key;			\
+								\
+	__mutex_init((mutex), #mutex, &__key, (mutexattr));	\
+})
+
+static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)ip);
+	return pthread_mutex_lock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_release(&lock->dep_map, 0, (unsigned long)ip);
+	return pthread_mutex_unlock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)ip);
+	return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
+{
+	return pthread_mutex_destroy(&lock->mutex);
+}
+
+#define pthread_mutex_t         liblockdep_pthread_mutex_t
+#define pthread_mutex_init      liblockdep_pthread_mutex_init
+#define pthread_mutex_lock      liblockdep_pthread_mutex_lock
+#define pthread_mutex_unlock    liblockdep_pthread_mutex_unlock
+#define pthread_mutex_trylock   liblockdep_pthread_mutex_trylock
+#define pthread_mutex_destroy   liblockdep_pthread_mutex_destroy
+
+#endif
+
+#endif

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Add pthread_mutex_t test suite
  2013-02-04  1:50 ` [PATCH v3 3/7] liblockdep: mutex test suite Sasha Levin
@ 2013-02-04 13:52   ` tip-bot for Sasha Levin
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:52 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  804a7ae57c90188263d49621cb4f1e0bae46c5ca
Gitweb:     http://git.kernel.org/tip/804a7ae57c90188263d49621cb4f1e0bae46c5ca
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:40 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:05 +0100

liblockdep: Add pthread_mutex_t test suite

This is a rather simple and basic test suite to test common
locking issues.

Beyond tests, it also shows how to use the library.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-3-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/lib/lockdep/run_tests.sh           | 15 +++++++++++++++
 tools/lib/lockdep/tests/AA.c             | 16 ++++++++++++++++
 tools/lib/lockdep/tests/ABBA.c           | 16 ++++++++++++++++
 tools/lib/lockdep/tests/ABBCCA.c         | 18 ++++++++++++++++++
 tools/lib/lockdep/tests/ABBCCDDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/ABCABC.c         | 18 ++++++++++++++++++
 tools/lib/lockdep/tests/ABCDBCDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/ABCDBDDA.c       | 20 ++++++++++++++++++++
 tools/lib/lockdep/tests/common.h         | 12 ++++++++++++
 tools/lib/lockdep/tests/unlock_balance.c | 15 +++++++++++++++
 10 files changed, 170 insertions(+)

diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
new file mode 100755
index 0000000..4dd32d1
--- /dev/null
+++ b/tools/lib/lockdep/run_tests.sh
@@ -0,0 +1,15 @@
+#! /bin/bash
+
+make &> /dev/null
+
+for i in `ls tests/*.c`; do
+	testname=$(basename -s .c "$i")
+	gcc -o tests/$testname -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
+	echo -ne "$testname... "
+	if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then
+		echo "PASSED!"
+	else
+		echo "FAILED!"
+	fi
+	rm tests/$testname
+done
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c
new file mode 100644
index 0000000..933d32f
--- /dev/null
+++ b/tools/lib/lockdep/tests/AA.c
@@ -0,0 +1,16 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+	pthread_mutex_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+
+	pthread_mutex_lock(&a);
+	pthread_mutex_unlock(&b);
+	pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c
new file mode 100644
index 0000000..9f5146b
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBA.c
@@ -0,0 +1,16 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c
new file mode 100644
index 0000000..b7435d7
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBCCA.c
@@ -0,0 +1,18 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(c, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c
new file mode 100644
index 0000000..2425330
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABBCCDDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+	pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c
new file mode 100644
index 0000000..2ee30fe
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCABC.c
@@ -0,0 +1,18 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, a);
+	LOCK_UNLOCK_2(b, c);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c
new file mode 100644
index 0000000..32d19d6
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCDBCDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblockdep_pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	liblockdep_pthread_mutex_init(&a, NULL);
+	liblockdep_pthread_mutex_init(&b, NULL);
+	liblockdep_pthread_mutex_init(&c, NULL);
+	liblockdep_pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(b, c);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c
new file mode 100644
index 0000000..850eaca
--- /dev/null
+++ b/tools/lib/lockdep/tests/ABCDBDDA.c
@@ -0,0 +1,20 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	pthread_mutex_t a, b, c, d;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+	pthread_mutex_init(&b, NULL);
+	pthread_mutex_init(&c, NULL);
+	pthread_mutex_init(&d, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(c, d);
+	LOCK_UNLOCK_2(b, d);
+	LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h
new file mode 100644
index 0000000..d89e94d
--- /dev/null
+++ b/tools/lib/lockdep/tests/common.h
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_TEST_COMMON_H
+#define _LIBLOCKDEP_TEST_COMMON_H
+
+#define LOCK_UNLOCK_2(a, b)			\
+	do {					\
+		pthread_mutex_lock(&(a));	\
+		pthread_mutex_lock(&(b));	\
+		pthread_mutex_unlock(&(b));	\
+		pthread_mutex_unlock(&(a));	\
+	} while(0)
+
+#endif
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c
new file mode 100644
index 0000000..9dfaf97
--- /dev/null
+++ b/tools/lib/lockdep/tests/unlock_balance.c
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+	pthread_mutex_t a;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_mutex_init(&a, NULL);
+
+	pthread_mutex_lock(&a);
+	pthread_mutex_unlock(&a);
+	pthread_mutex_unlock(&a);
+}

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Add public headers for pthread_rwlock_t implementation
  2013-02-04  1:50 ` [PATCH v3 4/7] liblockdep: public headers for rwlock implementation Sasha Levin
@ 2013-02-04 13:53   ` tip-bot for Sasha Levin
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:53 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  7fc788818c8f317c3a9d3331382aeecf4b726a3c
Gitweb:     http://git.kernel.org/tip/7fc788818c8f317c3a9d3331382aeecf4b726a3c
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:41 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:06 +0100

liblockdep: Add public headers for pthread_rwlock_t implementation

Both pthreads and lockdep support dealing with rwlocks, so
here's the liblockdep implementation for those.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-4-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/lib/lockdep/include/liblockdep/rwlock.h | 91 +++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h
new file mode 100644
index 0000000..26f9a68
--- /dev/null
+++ b/tools/lib/lockdep/include/liblockdep/rwlock.h
@@ -0,0 +1,91 @@
+#ifndef _LIBLOCKDEP_RWLOCK_H
+#define _LIBLOCKDEP_RWLOCK_H
+
+#ifdef __USE_LIBLOCKDEP
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_rwlock {
+	pthread_rwlock_t rwlock;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t;
+
+#define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl)			\
+		(struct liblockdep_pthread_rwlock) {			\
+	.rwlock = PTHREAD_RWLOCK_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)),	\
+}
+
+static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock,
+				const char *name,
+				struct lock_class_key *key,
+				const pthread_rwlockattr_t *attr)
+{
+	lockdep_init_map(&lock->dep_map, name, key, 0);
+
+	return pthread_rwlock_init(&lock->rwlock, attr);
+}
+
+#define liblockdep_pthread_rwlock_init(lock, attr)		\
+({							\
+	static struct lock_class_key __key;		\
+							\
+	__rwlock_init((lock), #lock, &__key, (attr));	\
+})
+
+static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_rdlock(&lock->rwlock);
+
+}
+
+static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_release(&lock->dep_map, 0, (unsigned long)ip);
+	return pthread_rwlock_unlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_wrlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock)
+{
+	void *ip = _THIS_IP_;
+	lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)ip);
+	return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
+{
+	return pthread_rwlock_destroy(&lock->rwlock);
+}
+
+#define pthread_rwlock_t		liblockdep_pthread_rwlock_t
+#define pthread_rwlock_init		liblockdep_pthread_rwlock_init
+#define pthread_rwlock_rdlock		liblockdep_pthread_rwlock_rdlock
+#define pthread_rwlock_unlock		liblockdep_pthread_rwlock_unlock
+#define pthread_rwlock_wrlock		liblockdep_pthread_rwlock_wrlock
+#define pthread_rwlock_tryrdlock	liblockdep_pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywlock		liblockdep_pthread_rwlock_trywlock
+#define pthread_rwlock_destroy		liblockdep_rwlock_destroy
+
+#endif
+
+#endif

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Add pthread_rwlock_t test suite
  2013-02-04  1:50 ` [PATCH v3 5/7] liblockdep: rwlock test suite Sasha Levin
@ 2013-02-04 13:55   ` tip-bot for Sasha Levin
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:55 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  8baa277b1b862ced9fce64d5ee5386676a723025
Gitweb:     http://git.kernel.org/tip/8baa277b1b862ced9fce64d5ee5386676a723025
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:42 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:06 +0100

liblockdep: Add pthread_rwlock_t test suite

A simple test to make sure we handle rwlocks correctly.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-5-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/lib/lockdep/tests/WW.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c
new file mode 100644
index 0000000..4b1be0f
--- /dev/null
+++ b/tools/lib/lockdep/tests/WW.c
@@ -0,0 +1,16 @@
+#include <liblockdep/rwlock.h>
+
+void main(void)
+{
+	pthread_rwlock_t a, b;
+
+	liblockdep_init();
+	liblockdep_set_thread();
+
+	pthread_rwlock_init(&a, NULL);
+	pthread_rwlock_init(&b, NULL);
+
+	pthread_rwlock_wrlock(&a);
+	pthread_rwlock_rdlock(&b);
+	pthread_rwlock_wrlock(&a);
+}

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] liblockdep: Add a MAINTAINERS entry
  2013-02-04  1:50 ` [PATCH v3 6/7] liblockdep: add a MAINTAINERS entry Sasha Levin
@ 2013-02-04 13:56   ` tip-bot for Sasha Levin
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:56 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  3279bccc7ff663ef1ccd8b9e8d4ac197c0e041e7
Gitweb:     http://git.kernel.org/tip/3279bccc7ff663ef1ccd8b9e8d4ac197c0e041e7
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:43 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:07 +0100

liblockdep: Add a MAINTAINERS entry

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-6-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8ae709e..3ea8ee1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4637,6 +4637,11 @@ F:	drivers/lguest/
 F:	include/linux/lguest*.h
 F:	tools/lguest/
 
+LIBLOCK
+M:	Sasha Levin <sasha.levin@oracle.com>
+S:	Maintained
+F:	tools/lib/lockdep/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:	Paul Mackerras <paulus@au.ibm.com>
 W:	http://www.ibm.com/linux/ltc/projects/ppc

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:core/locking] perf: Integrate liblockdep support into perf
  2013-02-04  1:50 ` [PATCH v3 7/7] perf: integrate liblockdep support into perf Sasha Levin
@ 2013-02-04 13:57   ` tip-bot for Sasha Levin
  2013-02-21 17:16   ` [PATCH] perf: define LIBLOCKDEP_LIBS to fix linker errors Dongsu Park
  1 sibling, 0 replies; 16+ messages in thread
From: tip-bot for Sasha Levin @ 2013-02-04 13:57 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, sasha.levin, hpa, mingo, a.p.zijlstra, torvalds,
	akpm, tglx

Commit-ID:  b2e7c77a379071318b2a9c9e500e3b8b47084391
Gitweb:     http://git.kernel.org/tip/b2e7c77a379071318b2a9c9e500e3b8b47084391
Author:     Sasha Levin <sasha.levin@oracle.com>
AuthorDate: Sun, 3 Feb 2013 20:50:44 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 4 Feb 2013 11:39:07 +0100

perf: Integrate liblockdep support into perf

liblockdep is a user-space version of lockdep, originally
written for the tools/kvm virtualization tool.

We can use it to analyze and verify locking correctness in
perf as well.

Usage is simple, to compile perf with liblockdep all that's
needed it:

	make LOCKDEP=1

Once liblockdep support is compiled in, perf will yell if
locking goes wrong for any reason:

=============================================
[ INFO: possible recursive locking detected ]
liblockdep 0.0.1
---------------------------------------------
perf/23237 is trying to acquire lock:
 (sched.start_work_mutex){......}, at: ./perf() [0x419793]

but task is already holding lock:
 (sched.start_work_mutex){......}, at: ./perf() [0x419793]

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(sched.start_work_mutex);
  lock(sched.start_work_mutex);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by perf/23237:
 #0:  (sched.start_work_mutex){......}, at: ./perf() [0x419793]
 #1:  (sched.work_done_wait_mutex){......}, at: ./perf() [0x419793]

stack backtrace:
/usr/lib64/liblockdep.so(+0x1ba0)[0x7fa067f99ba0]
/usr/lib64/liblockdep.so(+0x37bf)[0x7fa067f9b7bf]
/usr/lib64/liblockdep.so(+0x3899)[0x7fa067f9b899]
/usr/lib64/liblockdep.so(+0x429a)[0x7fa067f9c29a]
/usr/lib64/liblockdep.so(+0x4db1)[0x7fa067f9cdb1]
/usr/lib64/liblockdep.so(lock_acquire+0x97)[0x7fa067f9d8b4]
./perf(cmd_sched+0xb166)[0x42d976]
./perf[0x419793]
./perf(main+0x529)[0x418f59]
/lib64/libc.so.6(__libc_start_main+0xed)[0x7fa063ae591d]
./perf[0x4190d9]

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Cc: paulus@samba.org
Cc: acme@ghostprotocols.net
Cc: penberg@kernel.org
Cc: peterz@infradead.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1359942644-26371-7-git-send-email-sasha.levin@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/perf/Makefile                 | 22 ++++++++++++++++++++++
 tools/perf/builtin-sched.c          |  6 ++++--
 tools/perf/builtin-top.c            |  4 ++++
 tools/perf/config/feature-tests.mak | 12 ++++++++++++
 tools/perf/perf.c                   |  3 +++
 tools/perf/ui/setup.c               |  5 ++++-
 tools/perf/util/hist.h              |  1 +
 tools/perf/util/liblockdep.h        | 11 +++++++++++
 tools/perf/util/util.h              |  1 +
 9 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8ab05e5..785cd51 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -572,6 +572,21 @@ ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
 endif # Libunwind support
 endif # NO_LIBUNWIND
 
+ifndef NO_LIBLOCKDEP
+# for linking with liblockdep library, run like:
+# make LIBLOCKDEP=1
+ifeq ($(LOCKDEP),1)
+	LIBLOCKDEP_CFLAGS  := -I../lib/lockdep/include -D__USE_LIBLOCKDEP
+	LIBLOCKDEP_LDFLAGS := -L../lib/lockdep/ -llockdep
+endif
+
+FLAGS_LIBLOCKDEP=$(LIBLOCKDEP_CFLAGS) $(ALL_CFLAGS) $(LIBLOCKDEP_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
+ifneq ($(call try-cc,$(SOURCE_LIBLOCKDEP),$(FLAGS_LIBLOCKDEP),liblockdep),y)
+	msg := $(warning No liblockdep support.);
+	NO_LIBLOCKDEP := 1
+endif # liblockdep support
+endif # NO_LIBLOCKDEP
+
 -include arch/$(ARCH)/Makefile
 
 ifneq ($(OUTPUT),)
@@ -621,6 +636,13 @@ ifndef NO_LIBUNWIND
 	LIB_OBJS += $(OUTPUT)util/unwind.o
 endif
 
+ifndef NO_LIBLOCKDEP
+	BASIC_CFLAGS += -D__USE_LIBLOCKDEP
+	EXTLIBS += $(LIBLOCKDEP_LIBS)
+	BASIC_CFLAGS := $(LIBLOCKDEP_CFLAGS) $(BASIC_CFLAGS)
+	BASIC_LDFLAGS := $(LIBLOCKDEP_LDFLAGS) $(BASIC_LDFLAGS)
+endif
+
 ifndef NO_LIBAUDIT
 	FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
 	ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index cc28b85..53d9225 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -468,6 +468,8 @@ static void *thread_func(void *ctx)
 	char comm2[22];
 	int fd;
 
+	liblockdep_set_thread();
+
 	free(parms);
 
 	sprintf(comm2, ":%s", this_task->comm);
@@ -1677,8 +1679,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
 		},
 		.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
 		.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
-		.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
-		.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.start_work_mutex     = LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(sched.start_work_mutex),
+		.work_done_wait_mutex = LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(sched.work_done_wait_mutex),
 		.curr_pid	      = { [0 ... MAX_CPUS - 1] = -1 },
 		.sort_order	      = default_sort_order,
 		.replay_repeat	      = 10,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff395..c9b99ef 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -588,6 +588,8 @@ static void *display_thread_tui(void *arg)
 		.refresh	= top->delay_secs,
 	};
 
+	liblockdep_set_thread();
+
 	perf_top__sort_new_samples(top);
 
 	/*
@@ -613,6 +615,8 @@ static void *display_thread(void *arg)
 	struct perf_top *top = arg;
 	int delay_msecs, c;
 
+	liblockdep_set_thread();
+
 	tcgetattr(0, &save);
 	tc = save;
 	tc.c_lflag &= ~(ICANON | ECHO);
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index f5ac774..1f5a37e 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -217,6 +217,18 @@ int main(void)
 endef
 endif
 
+ifndef NO_LIBLOCKDEP
+define SOURCE_LIBLOCKDEP
+#include <liblockdep/mutex.h>
+
+int main(void)
+{
+	liblockdep_init();
+	return 0;
+}
+endef
+endif
+
 define SOURCE_ON_EXIT
 #include <stdio.h>
 
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 0f661fb..ddbd315 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -446,6 +446,9 @@ int main(int argc, const char **argv)
 {
 	const char *cmd;
 
+	liblockdep_init();
+	liblockdep_set_thread();
+
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ebb4cc1..5c0cdeb 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -3,14 +3,17 @@
 #include "../util/cache.h"
 #include "../util/debug.h"
 #include "../util/hist.h"
+#include "../util/liblockdep.h"
 
-pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t ui__lock;
 
 void setup_browser(bool fallback_to_pager)
 {
 	if (!isatty(1) || dump_trace)
 		use_browser = 0;
 
+	pthread_mutex_init(&ui__lock, NULL);
+
 	/* default to TUI */
 	if (use_browser < 0)
 		use_browser = 1;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8b091a5..328afe0 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -5,6 +5,7 @@
 #include <pthread.h>
 #include "callchain.h"
 #include "header.h"
+#include "liblockdep.h"
 
 extern struct callchain_param callchain_param;
 
diff --git a/tools/perf/util/liblockdep.h b/tools/perf/util/liblockdep.h
new file mode 100644
index 0000000..628a2f5
--- /dev/null
+++ b/tools/perf/util/liblockdep.h
@@ -0,0 +1,11 @@
+#ifdef __USE_LIBLOCKDEP
+
+#include <liblockdep/mutex.h>
+
+#else
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx) PTHREAD_MUTEX_INITIALIZER
+#define liblockdep_init()
+#define liblockdep_set_thread()
+
+#endif
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c233091..06e6244 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -73,6 +73,7 @@
 #include <linux/magic.h>
 #include "types.h"
 #include <sys/ttydefaults.h>
+#include "liblockdep.h"
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH] perf: define LIBLOCKDEP_LIBS to fix linker errors
  2013-02-04  1:50 ` [PATCH v3 7/7] perf: integrate liblockdep support into perf Sasha Levin
  2013-02-04 13:57   ` [tip:core/locking] perf: Integrate " tip-bot for Sasha Levin
@ 2013-02-21 17:16   ` Dongsu Park
  1 sibling, 0 replies; 16+ messages in thread
From: Dongsu Park @ 2013-02-21 17:16 UTC (permalink / raw)
  To: Sasha Levin; +Cc: linux-kernel, Dongsu Park

EXTLIBS has to include -llockdep, so that perf can be linked against
liblockdep properly by gcc 4.6 or newer. That can be done by setting
LIBLOCKDEP_LIBS to "-llockdep", as it's already included in EXTLIBS.
Without this fix, building perf will fail with the following errors:

builtin-sched.o: In function `thread_func':
/linux/tools/perf/builtin-sched.c:471:
undefined reference to `liblockdep_set_thread'
builtin-sched.o: In function `liblockdep_pthread_mutex_lock':
/linux/tools/perf/../lib/lockdep/include/liblockdep/mutex.h:41:
undefined reference to `lock_acquire'
builtin-sched.o: In function `liblockdep_pthread_mutex_unlock':
/linux/tools/perf/../lib/lockdep/include/liblockdep/mutex.h:48:
undefined reference to `lock_release'

Signed-off-by: Dongsu Park <dongsu.park@profitbricks.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
---
 tools/perf/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 785cd51..8d5c9eb 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -576,8 +576,9 @@ ifndef NO_LIBLOCKDEP
 # for linking with liblockdep library, run like:
 # make LIBLOCKDEP=1
 ifeq ($(LOCKDEP),1)
+	LIBLOCKDEP_LIBS := -llockdep
 	LIBLOCKDEP_CFLAGS  := -I../lib/lockdep/include -D__USE_LIBLOCKDEP
-	LIBLOCKDEP_LDFLAGS := -L../lib/lockdep/ -llockdep
+	LIBLOCKDEP_LDFLAGS := -L../lib/lockdep/ $(LIBLOCKDEP_LIBS)
 endif
 
 FLAGS_LIBLOCKDEP=$(LIBLOCKDEP_CFLAGS) $(ALL_CFLAGS) $(LIBLOCKDEP_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
-- 
1.8.0.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-02-21 17:17 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-04  1:50 [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
2013-02-04  1:50 ` [PATCH v3 2/7] liblockdep: public headers for mutex implementation Sasha Levin
2013-02-04 13:51   ` [tip:core/locking] liblockdep: Add public headers for pthread_mutex_t implementation tip-bot for Sasha Levin
2013-02-04  1:50 ` [PATCH v3 3/7] liblockdep: mutex test suite Sasha Levin
2013-02-04 13:52   ` [tip:core/locking] liblockdep: Add pthread_mutex_t " tip-bot for Sasha Levin
2013-02-04  1:50 ` [PATCH v3 4/7] liblockdep: public headers for rwlock implementation Sasha Levin
2013-02-04 13:53   ` [tip:core/locking] liblockdep: Add public headers for pthread_rwlock_t implementation tip-bot for Sasha Levin
2013-02-04  1:50 ` [PATCH v3 5/7] liblockdep: rwlock test suite Sasha Levin
2013-02-04 13:55   ` [tip:core/locking] liblockdep: Add pthread_rwlock_t " tip-bot for Sasha Levin
2013-02-04  1:50 ` [PATCH v3 6/7] liblockdep: add a MAINTAINERS entry Sasha Levin
2013-02-04 13:56   ` [tip:core/locking] liblockdep: Add " tip-bot for Sasha Levin
2013-02-04  1:50 ` [PATCH v3 7/7] perf: integrate liblockdep support into perf Sasha Levin
2013-02-04 13:57   ` [tip:core/locking] perf: Integrate " tip-bot for Sasha Levin
2013-02-21 17:16   ` [PATCH] perf: define LIBLOCKDEP_LIBS to fix linker errors Dongsu Park
2013-02-04 10:48 ` [PATCH v3 1/7] liblockdep: wrap kernel/lockdep.c to allow usage from userspace Ingo Molnar
2013-02-04 13:48 ` [tip:core/locking] liblockdep: Wrap kernel/ lockdep.c " tip-bot for Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).