linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] liblock: userspace lockdep
@ 2013-02-01  4:47 Sasha Levin
  2013-02-01  4:47 ` [PATCH 1/7] liblock: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

This patch series adds a userspace lock correctnes validator into
tools/lib/liblock.

There are no changes to any kernel code whatsoever, lockdep is
being used as is.

First 6 patches are the liblock implementation, the last one is
an example of liblock being used on an existing codebase.


Sasha Levin (7):
  liblock: wrap kernel/lockdep.c to allow usage from userspace
  liblock: public headers for mutex implementation
  liblock: mutex test suite
  liblock: public headers for rwlock implementation
  liblock: rwlock test suite
  liblock: add a MAINTAINERS entry
  perf: integrate liblock support into perf

 MAINTAINERS                                    |   5 +
 tools/lib/liblock/Makefile                     | 247 +++++++++++++++++++++++++
 tools/lib/liblock/common.c                     |  22 +++
 tools/lib/liblock/include/liblock/common.h     |  42 +++++
 tools/lib/liblock/include/liblock/mutex.h      |  62 +++++++
 tools/lib/liblock/include/liblock/rwlock.h     |  78 ++++++++
 tools/lib/liblock/lockdep.c                    |   2 +
 tools/lib/liblock/lockdep_internals.h          |   1 +
 tools/lib/liblock/lockdep_states.h             |   1 +
 tools/lib/liblock/run_tests.sh                 |  16 ++
 tools/lib/liblock/tests/AA.c                   |  16 ++
 tools/lib/liblock/tests/ABBA.c                 |  16 ++
 tools/lib/liblock/tests/ABBCCA.c               |  18 ++
 tools/lib/liblock/tests/ABBCCDDA.c             |  20 ++
 tools/lib/liblock/tests/ABCABC.c               |  18 ++
 tools/lib/liblock/tests/ABCDBCDA.c             |  20 ++
 tools/lib/liblock/tests/ABCDBDDA.c             |  20 ++
 tools/lib/liblock/tests/WW.c                   |  16 ++
 tools/lib/liblock/tests/common.h               |  11 ++
 tools/lib/liblock/tests/unlock_balance.c       |  15 ++
 tools/lib/liblock/uinclude/asm/hweight.h       |   0
 tools/lib/liblock/uinclude/asm/sections.h      |   0
 tools/lib/liblock/uinclude/linux/bitops.h      |   0
 tools/lib/liblock/uinclude/linux/compiler.h    |   7 +
 tools/lib/liblock/uinclude/linux/debug_locks.h |  12 ++
 tools/lib/liblock/uinclude/linux/delay.h       |   0
 tools/lib/liblock/uinclude/linux/export.h      |   7 +
 tools/lib/liblock/uinclude/linux/ftrace.h      |   0
 tools/lib/liblock/uinclude/linux/gfp.h         |   0
 tools/lib/liblock/uinclude/linux/hardirq.h     |  11 ++
 tools/lib/liblock/uinclude/linux/hash.h        |   1 +
 tools/lib/liblock/uinclude/linux/interrupt.h   |   0
 tools/lib/liblock/uinclude/linux/irqflags.h    |  38 ++++
 tools/lib/liblock/uinclude/linux/kallsyms.h    |  32 ++++
 tools/lib/liblock/uinclude/linux/kernel.h      |  34 ++++
 tools/lib/liblock/uinclude/linux/kmemcheck.h   |   8 +
 tools/lib/liblock/uinclude/linux/linkage.h     |   0
 tools/lib/liblock/uinclude/linux/list.h        |   1 +
 tools/lib/liblock/uinclude/linux/lockdep.h     |  58 ++++++
 tools/lib/liblock/uinclude/linux/mm_types.h    |   0
 tools/lib/liblock/uinclude/linux/module.h      |   6 +
 tools/lib/liblock/uinclude/linux/mutex.h       |   0
 tools/lib/liblock/uinclude/linux/poison.h      |   1 +
 tools/lib/liblock/uinclude/linux/prefetch.h    |   6 +
 tools/lib/liblock/uinclude/linux/proc_fs.h     |   0
 tools/lib/liblock/uinclude/linux/rcu.h         |  16 ++
 tools/lib/liblock/uinclude/linux/seq_file.h    |   0
 tools/lib/liblock/uinclude/linux/spinlock.h    |  25 +++
 tools/lib/liblock/uinclude/linux/stacktrace.h  |  31 ++++
 tools/lib/liblock/uinclude/linux/stringify.h   |   7 +
 tools/lib/liblock/uinclude/linux/system.h      |   0
 tools/lib/liblock/uinclude/linux/types.h       |  58 ++++++
 tools/lib/liblock/uinclude/linux/util.h        |   0
 tools/lib/liblock/uinclude/trace/events/lock.h |   0
 tools/perf/Makefile                            |  22 +++
 tools/perf/builtin-sched.c                     |  31 ++--
 tools/perf/builtin-top.c                       |  19 +-
 tools/perf/config/feature-tests.mak            |  12 ++
 tools/perf/perf.c                              |   4 +
 tools/perf/ui/browser.c                        |  21 ++-
 tools/perf/ui/browsers/annotate.c              |  10 +-
 tools/perf/ui/setup.c                          |   4 +-
 tools/perf/ui/tui/helpline.c                   |   4 +-
 tools/perf/ui/tui/progress.c                   |   4 +-
 tools/perf/ui/tui/setup.c                      |   4 +-
 tools/perf/ui/tui/util.c                       |   4 +-
 tools/perf/ui/ui.h                             |   3 +-
 tools/perf/util/annotate.c                     |   6 +-
 tools/perf/util/annotate.h                     |   3 +-
 tools/perf/util/evsel.c                        |   2 +-
 tools/perf/util/hist.c                         |   8 +-
 tools/perf/util/hist.h                         |   3 +-
 tools/perf/util/liblock.h                      |  17 ++
 73 files changed, 1128 insertions(+), 58 deletions(-)
 create mode 100644 tools/lib/liblock/Makefile
 create mode 100644 tools/lib/liblock/common.c
 create mode 100644 tools/lib/liblock/include/liblock/common.h
 create mode 100644 tools/lib/liblock/include/liblock/mutex.h
 create mode 100644 tools/lib/liblock/include/liblock/rwlock.h
 create mode 100644 tools/lib/liblock/lockdep.c
 create mode 100644 tools/lib/liblock/lockdep_internals.h
 create mode 100644 tools/lib/liblock/lockdep_states.h
 create mode 100755 tools/lib/liblock/run_tests.sh
 create mode 100644 tools/lib/liblock/tests/AA.c
 create mode 100644 tools/lib/liblock/tests/ABBA.c
 create mode 100644 tools/lib/liblock/tests/ABBCCA.c
 create mode 100644 tools/lib/liblock/tests/ABBCCDDA.c
 create mode 100644 tools/lib/liblock/tests/ABCABC.c
 create mode 100644 tools/lib/liblock/tests/ABCDBCDA.c
 create mode 100644 tools/lib/liblock/tests/ABCDBDDA.c
 create mode 100644 tools/lib/liblock/tests/WW.c
 create mode 100644 tools/lib/liblock/tests/common.h
 create mode 100644 tools/lib/liblock/tests/unlock_balance.c
 create mode 100644 tools/lib/liblock/uinclude/asm/hweight.h
 create mode 100644 tools/lib/liblock/uinclude/asm/sections.h
 create mode 100644 tools/lib/liblock/uinclude/linux/bitops.h
 create mode 100644 tools/lib/liblock/uinclude/linux/compiler.h
 create mode 100644 tools/lib/liblock/uinclude/linux/debug_locks.h
 create mode 100644 tools/lib/liblock/uinclude/linux/delay.h
 create mode 100644 tools/lib/liblock/uinclude/linux/export.h
 create mode 100644 tools/lib/liblock/uinclude/linux/ftrace.h
 create mode 100644 tools/lib/liblock/uinclude/linux/gfp.h
 create mode 100644 tools/lib/liblock/uinclude/linux/hardirq.h
 create mode 100644 tools/lib/liblock/uinclude/linux/hash.h
 create mode 100644 tools/lib/liblock/uinclude/linux/interrupt.h
 create mode 100644 tools/lib/liblock/uinclude/linux/irqflags.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kallsyms.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kernel.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kmemcheck.h
 create mode 100644 tools/lib/liblock/uinclude/linux/linkage.h
 create mode 100644 tools/lib/liblock/uinclude/linux/list.h
 create mode 100644 tools/lib/liblock/uinclude/linux/lockdep.h
 create mode 100644 tools/lib/liblock/uinclude/linux/mm_types.h
 create mode 100644 tools/lib/liblock/uinclude/linux/module.h
 create mode 100644 tools/lib/liblock/uinclude/linux/mutex.h
 create mode 100644 tools/lib/liblock/uinclude/linux/poison.h
 create mode 100644 tools/lib/liblock/uinclude/linux/prefetch.h
 create mode 100644 tools/lib/liblock/uinclude/linux/proc_fs.h
 create mode 100644 tools/lib/liblock/uinclude/linux/rcu.h
 create mode 100644 tools/lib/liblock/uinclude/linux/seq_file.h
 create mode 100644 tools/lib/liblock/uinclude/linux/spinlock.h
 create mode 100644 tools/lib/liblock/uinclude/linux/stacktrace.h
 create mode 100644 tools/lib/liblock/uinclude/linux/stringify.h
 create mode 100644 tools/lib/liblock/uinclude/linux/system.h
 create mode 100644 tools/lib/liblock/uinclude/linux/types.h
 create mode 100644 tools/lib/liblock/uinclude/linux/util.h
 create mode 100644 tools/lib/liblock/uinclude/trace/events/lock.h
 create mode 100644 tools/perf/util/liblock.h

-- 
1.8.1.1


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

* [PATCH 1/7] liblock: wrap kernel/lockdep.c to allow usage from userspace
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  4:47 ` [PATCH 2/7] liblock: public headers for mutex implementation Sasha Levin
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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/liblock/Makefile                     | 247 +++++++++++++++++++++++++
 tools/lib/liblock/common.c                     |  22 +++
 tools/lib/liblock/lockdep.c                    |   2 +
 tools/lib/liblock/lockdep_internals.h          |   1 +
 tools/lib/liblock/lockdep_states.h             |   1 +
 tools/lib/liblock/uinclude/asm/hweight.h       |   0
 tools/lib/liblock/uinclude/asm/sections.h      |   0
 tools/lib/liblock/uinclude/linux/bitops.h      |   0
 tools/lib/liblock/uinclude/linux/compiler.h    |   7 +
 tools/lib/liblock/uinclude/linux/debug_locks.h |  12 ++
 tools/lib/liblock/uinclude/linux/delay.h       |   0
 tools/lib/liblock/uinclude/linux/export.h      |   7 +
 tools/lib/liblock/uinclude/linux/ftrace.h      |   0
 tools/lib/liblock/uinclude/linux/gfp.h         |   0
 tools/lib/liblock/uinclude/linux/hardirq.h     |  11 ++
 tools/lib/liblock/uinclude/linux/hash.h        |   1 +
 tools/lib/liblock/uinclude/linux/interrupt.h   |   0
 tools/lib/liblock/uinclude/linux/irqflags.h    |  38 ++++
 tools/lib/liblock/uinclude/linux/kallsyms.h    |  32 ++++
 tools/lib/liblock/uinclude/linux/kernel.h      |  34 ++++
 tools/lib/liblock/uinclude/linux/kmemcheck.h   |   8 +
 tools/lib/liblock/uinclude/linux/linkage.h     |   0
 tools/lib/liblock/uinclude/linux/list.h        |   1 +
 tools/lib/liblock/uinclude/linux/lockdep.h     |  58 ++++++
 tools/lib/liblock/uinclude/linux/mm_types.h    |   0
 tools/lib/liblock/uinclude/linux/module.h      |   6 +
 tools/lib/liblock/uinclude/linux/mutex.h       |   0
 tools/lib/liblock/uinclude/linux/poison.h      |   1 +
 tools/lib/liblock/uinclude/linux/prefetch.h    |   6 +
 tools/lib/liblock/uinclude/linux/proc_fs.h     |   0
 tools/lib/liblock/uinclude/linux/rcu.h         |  16 ++
 tools/lib/liblock/uinclude/linux/seq_file.h    |   0
 tools/lib/liblock/uinclude/linux/spinlock.h    |  25 +++
 tools/lib/liblock/uinclude/linux/stacktrace.h  |  31 ++++
 tools/lib/liblock/uinclude/linux/stringify.h   |   7 +
 tools/lib/liblock/uinclude/linux/system.h      |   0
 tools/lib/liblock/uinclude/linux/types.h       |  58 ++++++
 tools/lib/liblock/uinclude/linux/util.h        |   0
 tools/lib/liblock/uinclude/trace/events/lock.h |   0
 39 files changed, 632 insertions(+)
 create mode 100644 tools/lib/liblock/Makefile
 create mode 100644 tools/lib/liblock/common.c
 create mode 100644 tools/lib/liblock/lockdep.c
 create mode 100644 tools/lib/liblock/lockdep_internals.h
 create mode 100644 tools/lib/liblock/lockdep_states.h
 create mode 100644 tools/lib/liblock/uinclude/asm/hweight.h
 create mode 100644 tools/lib/liblock/uinclude/asm/sections.h
 create mode 100644 tools/lib/liblock/uinclude/linux/bitops.h
 create mode 100644 tools/lib/liblock/uinclude/linux/compiler.h
 create mode 100644 tools/lib/liblock/uinclude/linux/debug_locks.h
 create mode 100644 tools/lib/liblock/uinclude/linux/delay.h
 create mode 100644 tools/lib/liblock/uinclude/linux/export.h
 create mode 100644 tools/lib/liblock/uinclude/linux/ftrace.h
 create mode 100644 tools/lib/liblock/uinclude/linux/gfp.h
 create mode 100644 tools/lib/liblock/uinclude/linux/hardirq.h
 create mode 100644 tools/lib/liblock/uinclude/linux/hash.h
 create mode 100644 tools/lib/liblock/uinclude/linux/interrupt.h
 create mode 100644 tools/lib/liblock/uinclude/linux/irqflags.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kallsyms.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kernel.h
 create mode 100644 tools/lib/liblock/uinclude/linux/kmemcheck.h
 create mode 100644 tools/lib/liblock/uinclude/linux/linkage.h
 create mode 100644 tools/lib/liblock/uinclude/linux/list.h
 create mode 100644 tools/lib/liblock/uinclude/linux/lockdep.h
 create mode 100644 tools/lib/liblock/uinclude/linux/mm_types.h
 create mode 100644 tools/lib/liblock/uinclude/linux/module.h
 create mode 100644 tools/lib/liblock/uinclude/linux/mutex.h
 create mode 100644 tools/lib/liblock/uinclude/linux/poison.h
 create mode 100644 tools/lib/liblock/uinclude/linux/prefetch.h
 create mode 100644 tools/lib/liblock/uinclude/linux/proc_fs.h
 create mode 100644 tools/lib/liblock/uinclude/linux/rcu.h
 create mode 100644 tools/lib/liblock/uinclude/linux/seq_file.h
 create mode 100644 tools/lib/liblock/uinclude/linux/spinlock.h
 create mode 100644 tools/lib/liblock/uinclude/linux/stacktrace.h
 create mode 100644 tools/lib/liblock/uinclude/linux/stringify.h
 create mode 100644 tools/lib/liblock/uinclude/linux/system.h
 create mode 100644 tools/lib/liblock/uinclude/linux/types.h
 create mode 100644 tools/lib/liblock/uinclude/linux/util.h
 create mode 100644 tools/lib/liblock/uinclude/trace/events/lock.h

diff --git a/tools/lib/liblock/Makefile b/tools/lib/liblock/Makefile
new file mode 100644
index 0000000..0909e4d
--- /dev/null
+++ b/tools/lib/liblock/Makefile
@@ -0,0 +1,247 @@
+# liblock 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 = liblock.a liblock.so
+
+CONFIG_INCLUDES = 
+CONFIG_LIBS	=
+CONFIG_FLAGS	=
+
+OBJ		= $@
+N		=
+
+export Q VERBOSE
+
+LIBLOCK_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 -DLIBLOCK_VERSION='"$(LIBLOCK_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)
+
+liblock.so: $(PEVENT_LIB_OBJS)
+	$(Q)$(do_compile_shared_library)
+
+liblock.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/liblock/common.c b/tools/lib/liblock/common.c
new file mode 100644
index 0000000..8657380
--- /dev/null
+++ b/tools/lib/liblock/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 = false;
+
+void liblock_init(void)
+{
+	lockdep_init();
+}
+
+void liblock_set_thread(void)
+{
+	prctl(PR_GET_NAME, current->comm);
+	current->pid = syscall(__NR_gettid);
+}
diff --git a/tools/lib/liblock/lockdep.c b/tools/lib/liblock/lockdep.c
new file mode 100644
index 0000000..8ddd0ff
--- /dev/null
+++ b/tools/lib/liblock/lockdep.c
@@ -0,0 +1,2 @@
+#include <linux/lockdep.h>
+#include "../../../kernel/lockdep.c"
diff --git a/tools/lib/liblock/lockdep_internals.h b/tools/lib/liblock/lockdep_internals.h
new file mode 100644
index 0000000..109e96f
--- /dev/null
+++ b/tools/lib/liblock/lockdep_internals.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_internals.h"
diff --git a/tools/lib/liblock/lockdep_states.h b/tools/lib/liblock/lockdep_states.h
new file mode 100644
index 0000000..6b75423
--- /dev/null
+++ b/tools/lib/liblock/lockdep_states.h
@@ -0,0 +1 @@
+#include "../../../kernel/lockdep_states.h"
diff --git a/tools/lib/liblock/uinclude/asm/hweight.h b/tools/lib/liblock/uinclude/asm/hweight.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/asm/sections.h b/tools/lib/liblock/uinclude/asm/sections.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/bitops.h b/tools/lib/liblock/uinclude/linux/bitops.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/compiler.h b/tools/lib/liblock/uinclude/linux/compiler.h
new file mode 100644
index 0000000..8f44a7c
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/compiler.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCK_LINUX_COMPILER_H_
+#define _LIBLOCK_LINUX_COMPILER_H_
+
+#define __used		__attribute__((__unused__))
+#define unlikely
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/debug_locks.h b/tools/lib/liblock/uinclude/linux/debug_locks.h
new file mode 100644
index 0000000..45c65bd
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/debug_locks.h
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCK_DEBUG_LOCKS_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/delay.h b/tools/lib/liblock/uinclude/linux/delay.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/export.h b/tools/lib/liblock/uinclude/linux/export.h
new file mode 100644
index 0000000..4c7ffd4
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/export.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCK_LINUX_EXPORT_H_
+#define _LIBLOCK_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/ftrace.h b/tools/lib/liblock/uinclude/linux/ftrace.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/gfp.h b/tools/lib/liblock/uinclude/linux/gfp.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/hardirq.h b/tools/lib/liblock/uinclude/linux/hardirq.h
new file mode 100644
index 0000000..f2e91a1
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/hardirq.h
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCK_LINUX_HARDIRQ_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/hash.h b/tools/lib/liblock/uinclude/linux/hash.h
new file mode 100644
index 0000000..0f84798
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/hash.h
@@ -0,0 +1 @@
+#include "../../../include/linux/hash.h"
diff --git a/tools/lib/liblock/uinclude/linux/interrupt.h b/tools/lib/liblock/uinclude/linux/interrupt.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/irqflags.h b/tools/lib/liblock/uinclude/linux/irqflags.h
new file mode 100644
index 0000000..c394aba
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/irqflags.h
@@ -0,0 +1,38 @@
+#ifndef _LIBLOCK_LINUX_TRACE_IRQFLAGS_H_
+#define _LIBLOCK_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) do { flags = 0; } while (0)
+#define raw_local_irq_restore(flags) do { } while (0)
+#define raw_local_save_flags(flags) do { flags = 0; } while (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) do { flags = 0 ;} while (0)
+#define local_irq_restore(flags) do { } while (0)
+#define local_save_flags(flags)	do { flags = 0; } while (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/liblock/uinclude/linux/kallsyms.h b/tools/lib/liblock/uinclude/linux/kallsyms.h
new file mode 100644
index 0000000..fda2d40
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/kallsyms.h
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCK_LINUX_KALLSYMS_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/kernel.h b/tools/lib/liblock/uinclude/linux/kernel.h
new file mode 100644
index 0000000..e2f19ee
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/kernel.h
@@ -0,0 +1,34 @@
+#ifndef _LIBLOCK_LINUX_KERNEL_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/kmemcheck.h b/tools/lib/liblock/uinclude/linux/kmemcheck.h
new file mode 100644
index 0000000..25bde2e
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/kmemcheck.h
@@ -0,0 +1,8 @@
+#ifndef _LIBLOCK_LINUX_KMEMCHECK_H_
+#define _LIBLOCK_LINUX_KMEMCHECK_H_
+
+static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+}
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/linkage.h b/tools/lib/liblock/uinclude/linux/linkage.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/list.h b/tools/lib/liblock/uinclude/linux/list.h
new file mode 100644
index 0000000..6e9ef31
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/list.h
@@ -0,0 +1 @@
+#include "../../../include/linux/list.h"
diff --git a/tools/lib/liblock/uinclude/linux/lockdep.h b/tools/lib/liblock/uinclude/linux/lockdep.h
new file mode 100644
index 0000000..c3a693c
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/lockdep.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCK_LOCKDEP_H_
+#define _LIBLOCK_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 liblock_init(void);
+void liblock_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 = "liblock",
+		.version = LIBLOCK_VERSION,
+	};
+
+	return &n;
+}
+
+#define print_tainted() ""
+#define static_obj(x) 1
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/mm_types.h b/tools/lib/liblock/uinclude/linux/mm_types.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/module.h b/tools/lib/liblock/uinclude/linux/module.h
new file mode 100644
index 0000000..a86c36d
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/module.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCK_LINUX_MODULE_H_
+#define _LIBLOCK_LINUX_MODULE_H_
+
+#define module_param(name, type, perm)
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/mutex.h b/tools/lib/liblock/uinclude/linux/mutex.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/poison.h b/tools/lib/liblock/uinclude/linux/poison.h
new file mode 100644
index 0000000..0c27bdf
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/poison.h
@@ -0,0 +1 @@
+#include "../../../include/linux/poison.h"
diff --git a/tools/lib/liblock/uinclude/linux/prefetch.h b/tools/lib/liblock/uinclude/linux/prefetch.h
new file mode 100644
index 0000000..9873927
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/prefetch.h
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCK_LINUX_PREFETCH_H_
+#define _LIBLOCK_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/proc_fs.h b/tools/lib/liblock/uinclude/linux/proc_fs.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/rcu.h b/tools/lib/liblock/uinclude/linux/rcu.h
new file mode 100644
index 0000000..f2e152b
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/rcu.h
@@ -0,0 +1,16 @@
+#ifndef _LIBLOCK_RCU_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/seq_file.h b/tools/lib/liblock/uinclude/linux/seq_file.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/spinlock.h b/tools/lib/liblock/uinclude/linux/spinlock.h
new file mode 100644
index 0000000..17ba1a3
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/spinlock.h
@@ -0,0 +1,25 @@
+#ifndef _LIBLOCK_SPINLOCK_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/stacktrace.h b/tools/lib/liblock/uinclude/linux/stacktrace.h
new file mode 100644
index 0000000..0f279e8
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/stacktrace.h
@@ -0,0 +1,31 @@
+#ifndef _LIBLOCK_LINUX_STACKTRACE_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/stringify.h b/tools/lib/liblock/uinclude/linux/stringify.h
new file mode 100644
index 0000000..984f0fd
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/stringify.h
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCK_LINUX_STRINGIFY_H_
+#define _LIBLOCK_LINUX_STRINGIFY_H_
+
+#define __stringify_1(x...)	#x
+#define __stringify(x...)	__stringify_1(x)
+
+#endif
diff --git a/tools/lib/liblock/uinclude/linux/system.h b/tools/lib/liblock/uinclude/linux/system.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/linux/types.h b/tools/lib/liblock/uinclude/linux/types.h
new file mode 100644
index 0000000..33c6884
--- /dev/null
+++ b/tools/lib/liblock/uinclude/linux/types.h
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCK_LINUX_TYPES_H_
+#define _LIBLOCK_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/liblock/uinclude/linux/util.h b/tools/lib/liblock/uinclude/linux/util.h
new file mode 100644
index 0000000..e69de29
diff --git a/tools/lib/liblock/uinclude/trace/events/lock.h b/tools/lib/liblock/uinclude/trace/events/lock.h
new file mode 100644
index 0000000..e69de29
-- 
1.8.1.1


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

* [PATCH 2/7] liblock: public headers for mutex implementation
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
  2013-02-01  4:47 ` [PATCH 1/7] liblock: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  9:57   ` Ingo Molnar
  2013-02-01  4:47 ` [PATCH 3/7] liblock: mutex test suite Sasha Levin
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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 liblock lock validation
just by adding a "liblock_" to pthread_mutex_*() calls, which means that
it's easy to integrate liblock into existing codebases.

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

diff --git a/tools/lib/liblock/include/liblock/common.h b/tools/lib/liblock/include/liblock/common.h
new file mode 100644
index 0000000..a3409d7
--- /dev/null
+++ b/tools/lib/liblock/include/liblock/common.h
@@ -0,0 +1,42 @@
+#ifndef _LIBLOCK_COMMON_H
+#define _LIBLOCK_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 liblock_init(void);
+void liblock_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/liblock/include/liblock/mutex.h b/tools/lib/liblock/include/liblock/mutex.h
new file mode 100644
index 0000000..d350733
--- /dev/null
+++ b/tools/lib/liblock/include/liblock/mutex.h
@@ -0,0 +1,62 @@
+#ifndef _LIBLOCK_MUTEX_H
+#define _LIBLOCK_MUTEX_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblock_pthread_mutex {
+	pthread_mutex_t mutex;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblock_pthread_mutex liblock_pthread_mutex_t;
+
+#define LIBLOCK_PTHREAD_MUTEX_INITIALIZER(mtx)				\
+		(const struct liblock_pthread_mutex) {			\
+	.mutex = PTHREAD_MUTEX_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)),	\
+}
+
+static inline int __mutex_init(liblock_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 liblock_pthread_mutex_init(mutex, mutexattr) 		\
+({								\
+	static struct lock_class_key __key;			\
+    								\
+	__mutex_init((mutex), #mutex, &__key, (mutexattr));	\
+})
+
+static inline int liblock_pthread_mutex_lock(liblock_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 liblock_pthread_mutex_unlock(liblock_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 liblock_pthread_mutex_trylock(liblock_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 liblock_pthread_mutex_destroy(liblock_pthread_mutex_t *lock)
+{
+	return pthread_mutex_destroy(&lock->mutex);
+}
+
+#endif
-- 
1.8.1.1


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

* [PATCH 3/7] liblock: mutex test suite
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
  2013-02-01  4:47 ` [PATCH 1/7] liblock: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
  2013-02-01  4:47 ` [PATCH 2/7] liblock: public headers for mutex implementation Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  4:47 ` [PATCH 4/7] liblock: public headers for rwlock implementation Sasha Levin
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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/liblock/run_tests.sh           | 16 ++++++++++++++++
 tools/lib/liblock/tests/AA.c             | 16 ++++++++++++++++
 tools/lib/liblock/tests/ABBA.c           | 16 ++++++++++++++++
 tools/lib/liblock/tests/ABBCCA.c         | 18 ++++++++++++++++++
 tools/lib/liblock/tests/ABBCCDDA.c       | 20 ++++++++++++++++++++
 tools/lib/liblock/tests/ABCABC.c         | 18 ++++++++++++++++++
 tools/lib/liblock/tests/ABCDBCDA.c       | 20 ++++++++++++++++++++
 tools/lib/liblock/tests/ABCDBDDA.c       | 20 ++++++++++++++++++++
 tools/lib/liblock/tests/common.h         | 11 +++++++++++
 tools/lib/liblock/tests/unlock_balance.c | 15 +++++++++++++++
 10 files changed, 170 insertions(+)
 create mode 100755 tools/lib/liblock/run_tests.sh
 create mode 100644 tools/lib/liblock/tests/AA.c
 create mode 100644 tools/lib/liblock/tests/ABBA.c
 create mode 100644 tools/lib/liblock/tests/ABBCCA.c
 create mode 100644 tools/lib/liblock/tests/ABBCCDDA.c
 create mode 100644 tools/lib/liblock/tests/ABCABC.c
 create mode 100644 tools/lib/liblock/tests/ABCDBCDA.c
 create mode 100644 tools/lib/liblock/tests/ABCDBDDA.c
 create mode 100644 tools/lib/liblock/tests/common.h
 create mode 100644 tools/lib/liblock/tests/unlock_balance.c

diff --git a/tools/lib/liblock/run_tests.sh b/tools/lib/liblock/run_tests.sh
new file mode 100755
index 0000000..bbf5281
--- /dev/null
+++ b/tools/lib/liblock/run_tests.sh
@@ -0,0 +1,16 @@
+#! /bin/bash
+
+make &> /dev/null
+
+for i in `ls tests/*.c`; do
+	testname=$(basename -s .c "$i")
+	gcc -o tests/$testname -lpthread $i liblock.a -Iinclude &> /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/liblock/tests/AA.c b/tools/lib/liblock/tests/AA.c
new file mode 100644
index 0000000..558109c
--- /dev/null
+++ b/tools/lib/liblock/tests/AA.c
@@ -0,0 +1,16 @@
+#include <liblock/mutex.h>
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+
+	liblock_pthread_mutex_lock(&a);
+	liblock_pthread_mutex_unlock(&b);
+	liblock_pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/liblock/tests/ABBA.c b/tools/lib/liblock/tests/ABBA.c
new file mode 100644
index 0000000..b5070fd
--- /dev/null
+++ b/tools/lib/liblock/tests/ABBA.c
@@ -0,0 +1,16 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+
+	LOCK_UNLOCK_2(a, b);
+	LOCK_UNLOCK_2(b, a);
+}
diff --git a/tools/lib/liblock/tests/ABBCCA.c b/tools/lib/liblock/tests/ABBCCA.c
new file mode 100644
index 0000000..5fc5fa2
--- /dev/null
+++ b/tools/lib/liblock/tests/ABBCCA.c
@@ -0,0 +1,18 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b, c;
+	
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+	liblock_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/liblock/tests/ABBCCDDA.c b/tools/lib/liblock/tests/ABBCCDDA.c
new file mode 100644
index 0000000..5cf05bb
--- /dev/null
+++ b/tools/lib/liblock/tests/ABBCCDDA.c
@@ -0,0 +1,20 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b, c, d;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+	liblock_pthread_mutex_init(&c, NULL);
+	liblock_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/liblock/tests/ABCABC.c b/tools/lib/liblock/tests/ABCABC.c
new file mode 100644
index 0000000..eab71ff
--- /dev/null
+++ b/tools/lib/liblock/tests/ABCABC.c
@@ -0,0 +1,18 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b, c;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+	liblock_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/liblock/tests/ABCDBCDA.c b/tools/lib/liblock/tests/ABCDBCDA.c
new file mode 100644
index 0000000..3250f0f
--- /dev/null
+++ b/tools/lib/liblock/tests/ABCDBCDA.c
@@ -0,0 +1,20 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b, c, d;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+	liblock_pthread_mutex_init(&c, NULL);
+	liblock_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/liblock/tests/ABCDBDDA.c b/tools/lib/liblock/tests/ABCDBDDA.c
new file mode 100644
index 0000000..b49c5d9
--- /dev/null
+++ b/tools/lib/liblock/tests/ABCDBDDA.c
@@ -0,0 +1,20 @@
+#include <liblock/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+	liblock_pthread_mutex_t a, b, c, d;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+	liblock_pthread_mutex_init(&b, NULL);
+	liblock_pthread_mutex_init(&c, NULL);
+	liblock_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/liblock/tests/common.h b/tools/lib/liblock/tests/common.h
new file mode 100644
index 0000000..d5f6d5e
--- /dev/null
+++ b/tools/lib/liblock/tests/common.h
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCK_TEST_COMMON_H
+#define _LIBLOCK_TEST_COMMON_H
+
+#define LOCK_UNLOCK_2(a, b)			\
+	liblock_pthread_mutex_lock(&(a));	\
+	liblock_pthread_mutex_lock(&(b));	\
+	liblock_pthread_mutex_unlock(&(b));	\
+	liblock_pthread_mutex_unlock(&(a));
+
+
+#endif
diff --git a/tools/lib/liblock/tests/unlock_balance.c b/tools/lib/liblock/tests/unlock_balance.c
new file mode 100644
index 0000000..e68ca99
--- /dev/null
+++ b/tools/lib/liblock/tests/unlock_balance.c
@@ -0,0 +1,15 @@
+#include <liblock/mutex.h>
+
+void main(void)
+{
+	liblock_pthread_mutex_t a;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_mutex_init(&a, NULL);
+
+	liblock_pthread_mutex_lock(&a);
+	liblock_pthread_mutex_unlock(&a);
+	liblock_pthread_mutex_unlock(&a);
+}
-- 
1.8.1.1


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

* [PATCH 4/7] liblock: public headers for rwlock implementation
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
                   ` (2 preceding siblings ...)
  2013-02-01  4:47 ` [PATCH 3/7] liblock: mutex test suite Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  4:47 ` [PATCH 5/7] liblock: rwlock test suite Sasha Levin
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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
liblock implementation for those.

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

diff --git a/tools/lib/liblock/include/liblock/rwlock.h b/tools/lib/liblock/include/liblock/rwlock.h
new file mode 100644
index 0000000..0dbe879
--- /dev/null
+++ b/tools/lib/liblock/include/liblock/rwlock.h
@@ -0,0 +1,78 @@
+#ifndef _LIBLOCK_RWLOCK_H
+#define _LIBLOCK_RWLOCK_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblock_pthread_rwlock {
+	pthread_rwlock_t rwlock;
+	struct lockdep_map dep_map;
+};
+
+typedef struct liblock_pthread_rwlock liblock_pthread_rwlock_t;
+
+#define LIBLOCK_PTHREAD_RWLOCK_INITIALIZER(rwl)				\
+		(struct liblock_pthread_rwlock) {			\
+	.rwlock = PTHREAD_RWLOCK_INITIALIZER,				\
+	.dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)),	\
+}
+
+static inline int __rwlock_init(liblock_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 liblock_pthread_rwlock_init(lock, attr)		\
+({							\
+	static struct lock_class_key __key;		\
+							\
+	__rwlock_init((lock), #lock, &__key, (attr));	\
+})
+
+static inline int liblock_pthread_rwlock_rdlock(liblock_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 liblock_pthread_rwlock_unlock(liblock_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 liblock_pthread_rwlock_wrlock(liblock_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 liblock_pthread_rwlock_tryrdlock(liblock_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 liblock_pthread_rwlock_trywlock(liblock_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 liblock_rwlock_destroy(liblock_pthread_rwlock_t *lock)
+{
+	return pthread_rwlock_destroy(&lock->rwlock);
+}
+
+#endif
-- 
1.8.1.1


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

* [PATCH 5/7] liblock: rwlock test suite
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
                   ` (3 preceding siblings ...)
  2013-02-01  4:47 ` [PATCH 4/7] liblock: public headers for rwlock implementation Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  4:47 ` [PATCH 6/7] liblock: add a MAINTAINERS entry Sasha Levin
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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/liblock/tests/WW.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 tools/lib/liblock/tests/WW.c

diff --git a/tools/lib/liblock/tests/WW.c b/tools/lib/liblock/tests/WW.c
new file mode 100644
index 0000000..f2d00bd
--- /dev/null
+++ b/tools/lib/liblock/tests/WW.c
@@ -0,0 +1,16 @@
+#include <liblock/rwlock.h>
+
+void main(void)
+{
+	liblock_pthread_rwlock_t a, b;
+
+	liblock_init();
+	liblock_set_thread();
+
+	liblock_pthread_rwlock_init(&a, NULL);
+	liblock_pthread_rwlock_init(&b, NULL);
+
+	liblock_pthread_rwlock_wrlock(&a);
+	liblock_pthread_rwlock_rdlock(&b);
+	liblock_pthread_rwlock_wrlock(&a);
+}
-- 
1.8.1.1


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

* [PATCH 6/7] liblock: add a MAINTAINERS entry
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
                   ` (4 preceding siblings ...)
  2013-02-01  4:47 ` [PATCH 5/7] liblock: rwlock test suite Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  4:47 ` [PATCH 7/7] perf: integrate liblock support into perf Sasha Levin
  2013-02-01  7:35 ` [PATCH 0/7] liblock: userspace lockdep Pekka Enberg
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 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..f26afae 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/liblock/
+
 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.1


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

* [PATCH 7/7] perf: integrate liblock support into perf
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
                   ` (5 preceding siblings ...)
  2013-02-01  4:47 ` [PATCH 6/7] liblock: add a MAINTAINERS entry Sasha Levin
@ 2013-02-01  4:47 ` Sasha Levin
  2013-02-01  7:35 ` [PATCH 0/7] liblock: userspace lockdep Pekka Enberg
  7 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01  4:47 UTC (permalink / raw)
  To: mingo, peterz; +Cc: paulus, acme, penberg, linux-kernel, Sasha Levin

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

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

	make LIBLOCK=[path to liblock]

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

=============================================
[ INFO: possible recursive locking detected ]
liblock 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/liblock.so(+0x1ba0)[0x7fa067f99ba0]
/usr/lib64/liblock.so(+0x37bf)[0x7fa067f9b7bf]
/usr/lib64/liblock.so(+0x3899)[0x7fa067f9b899]
/usr/lib64/liblock.so(+0x429a)[0x7fa067f9c29a]
/usr/lib64/liblock.so(+0x4db1)[0x7fa067f9cdb1]
/usr/lib64/liblock.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          | 31 +++++++++++++++++--------------
 tools/perf/builtin-top.c            | 19 ++++++++++---------
 tools/perf/config/feature-tests.mak | 12 ++++++++++++
 tools/perf/perf.c                   |  4 ++++
 tools/perf/ui/browser.c             | 21 +++++++++++----------
 tools/perf/ui/browsers/annotate.c   | 10 +++++-----
 tools/perf/ui/setup.c               |  4 +++-
 tools/perf/ui/tui/helpline.c        |  4 ++--
 tools/perf/ui/tui/progress.c        |  4 ++--
 tools/perf/ui/tui/setup.c           |  4 ++--
 tools/perf/ui/tui/util.c            |  4 ++--
 tools/perf/ui/ui.h                  |  3 ++-
 tools/perf/util/annotate.c          |  6 +++---
 tools/perf/util/annotate.h          |  3 ++-
 tools/perf/util/evsel.c             |  2 +-
 tools/perf/util/hist.c              |  8 ++++----
 tools/perf/util/hist.h              |  3 ++-
 tools/perf/util/liblock.h           | 17 +++++++++++++++++
 19 files changed, 123 insertions(+), 58 deletions(-)
 create mode 100644 tools/perf/util/liblock.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8ab05e5..13e8795 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_LIBLOCK
+# for linking with liblock library, run like:
+# make DEBUG=1 LIBLOCK_DIR=/path/to/linux.git/tools/lib/liblock/
+ifdef LIBLOCK_DIR
+	LIBLOCK_CFLAGS  := -I$(LIBLOCK_DIR)/include
+	LIBLOCK_LDFLAGS := -L$(LIBLOCK_DIR)/ -llock
+endif
+
+FLAGS_LIBLOCK=$(LIBLOCK_CFLAGS) $(ALL_CFLAGS) $(LIBLOCK_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
+ifneq ($(call try-cc,$(SOURCE_LIBLOCK),$(FLAGS_LIBLOCK),liblock),y)
+	msg := $(warning No liblock found.);
+	NO_LIBLOCK := 1
+endif # liblock support
+endif # NO_LIBLOCK
+
 -include arch/$(ARCH)/Makefile
 
 ifneq ($(OUTPUT),)
@@ -621,6 +636,13 @@ ifndef NO_LIBUNWIND
 	LIB_OBJS += $(OUTPUT)util/unwind.o
 endif
 
+ifndef NO_LIBLOCK
+	BASIC_CFLAGS += -DLIBLOCK_SUPPORT
+	EXTLIBS += $(LIBLOCK_LIBS)
+	BASIC_CFLAGS := $(LIBLOCK_CFLAGS) $(BASIC_CFLAGS)
+	BASIC_LDFLAGS := $(LIBLOCK_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..5e67c156 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -10,6 +10,7 @@
 #include "util/header.h"
 #include "util/session.h"
 #include "util/tool.h"
+#include "util/liblock.h"
 
 #include "util/parse-options.h"
 #include "util/trace-event.h"
@@ -125,8 +126,8 @@ struct perf_sched {
 	struct task_desc *pid_to_task[MAX_PID];
 	struct task_desc **tasks;
 	const struct trace_sched_handler *tp_handler;
-	pthread_mutex_t	 start_work_mutex;
-	pthread_mutex_t	 work_done_wait_mutex;
+	liblock_pthread_mutex_t	 start_work_mutex;
+	liblock_pthread_mutex_t	 work_done_wait_mutex;
 	int		 profile_cpu;
 /*
  * Track the current task - that way we can know whether there's any
@@ -468,6 +469,8 @@ static void *thread_func(void *ctx)
 	char comm2[22];
 	int fd;
 
+	liblock_set_thread();
+
 	free(parms);
 
 	sprintf(comm2, ":%s", this_task->comm);
@@ -478,9 +481,9 @@ static void *thread_func(void *ctx)
 again:
 	ret = sem_post(&this_task->ready_for_work);
 	BUG_ON(ret);
-	ret = pthread_mutex_lock(&sched->start_work_mutex);
+	ret = liblock_pthread_mutex_lock(&sched->start_work_mutex);
 	BUG_ON(ret);
-	ret = pthread_mutex_unlock(&sched->start_work_mutex);
+	ret = liblock_pthread_mutex_unlock(&sched->start_work_mutex);
 	BUG_ON(ret);
 
 	cpu_usage_0 = get_cpu_usage_nsec_self(fd);
@@ -495,9 +498,9 @@ again:
 	ret = sem_post(&this_task->work_done_sem);
 	BUG_ON(ret);
 
-	ret = pthread_mutex_lock(&sched->work_done_wait_mutex);
+	ret = liblock_pthread_mutex_lock(&sched->work_done_wait_mutex);
 	BUG_ON(ret);
-	ret = pthread_mutex_unlock(&sched->work_done_wait_mutex);
+	ret = liblock_pthread_mutex_unlock(&sched->work_done_wait_mutex);
 	BUG_ON(ret);
 
 	goto again;
@@ -515,9 +518,9 @@ static void create_tasks(struct perf_sched *sched)
 	err = pthread_attr_setstacksize(&attr,
 			(size_t) max(16 * 1024, PTHREAD_STACK_MIN));
 	BUG_ON(err);
-	err = pthread_mutex_lock(&sched->start_work_mutex);
+	err = liblock_pthread_mutex_lock(&sched->start_work_mutex);
 	BUG_ON(err);
-	err = pthread_mutex_lock(&sched->work_done_wait_mutex);
+	err = liblock_pthread_mutex_lock(&sched->work_done_wait_mutex);
 	BUG_ON(err);
 	for (i = 0; i < sched->nr_tasks; i++) {
 		struct sched_thread_parms *parms = malloc(sizeof(*parms));
@@ -541,7 +544,7 @@ static void wait_for_tasks(struct perf_sched *sched)
 
 	sched->start_time = get_nsecs();
 	sched->cpu_usage = 0;
-	pthread_mutex_unlock(&sched->work_done_wait_mutex);
+	liblock_pthread_mutex_unlock(&sched->work_done_wait_mutex);
 
 	for (i = 0; i < sched->nr_tasks; i++) {
 		task = sched->tasks[i];
@@ -549,12 +552,12 @@ static void wait_for_tasks(struct perf_sched *sched)
 		BUG_ON(ret);
 		sem_init(&task->ready_for_work, 0, 0);
 	}
-	ret = pthread_mutex_lock(&sched->work_done_wait_mutex);
+	ret = liblock_pthread_mutex_lock(&sched->work_done_wait_mutex);
 	BUG_ON(ret);
 
 	cpu_usage_0 = get_cpu_usage_nsec_parent();
 
-	pthread_mutex_unlock(&sched->start_work_mutex);
+	liblock_pthread_mutex_unlock(&sched->start_work_mutex);
 
 	for (i = 0; i < sched->nr_tasks; i++) {
 		task = sched->tasks[i];
@@ -576,7 +579,7 @@ static void wait_for_tasks(struct perf_sched *sched)
 	sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 +
 					 sched->parent_cpu_usage)/10;
 
-	ret = pthread_mutex_lock(&sched->start_work_mutex);
+	ret = liblock_pthread_mutex_lock(&sched->start_work_mutex);
 	BUG_ON(ret);
 
 	for (i = 0; i < sched->nr_tasks; i++) {
@@ -1677,8 +1680,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     = LIBLOCK_PTHREAD_MUTEX_INITIALIZER(sched.start_work_mutex),
+		.work_done_wait_mutex = LIBLOCK_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..f8e944c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -40,6 +40,7 @@
 #include "util/xyarray.h"
 #include "util/sort.h"
 #include "util/intlist.h"
+#include "util/liblock.h"
 
 #include "util/debug.h"
 
@@ -137,14 +138,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
 
 	notes = symbol__annotation(sym);
 	if (notes->src != NULL) {
-		pthread_mutex_lock(&notes->lock);
+		liblock_pthread_mutex_lock(&notes->lock);
 		goto out_assign;
 	}
 
-	pthread_mutex_lock(&notes->lock);
+	liblock_pthread_mutex_lock(&notes->lock);
 
 	if (symbol__alloc_hist(sym) < 0) {
-		pthread_mutex_unlock(&notes->lock);
+		liblock_pthread_mutex_unlock(&notes->lock);
 		pr_err("Not enough memory for annotating '%s' symbol!\n",
 		       sym->name);
 		sleep(1);
@@ -157,7 +158,7 @@ out_assign:
 		top->sym_filter_entry = he;
 	}
 
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 	return err;
 }
 
@@ -210,11 +211,11 @@ static void perf_top__record_precise_ip(struct perf_top *top,
 	sym = he->ms.sym;
 	notes = symbol__annotation(sym);
 
-	if (pthread_mutex_trylock(&notes->lock))
+	if (liblock_pthread_mutex_trylock(&notes->lock))
 		return;
 
 	if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
-		pthread_mutex_unlock(&notes->lock);
+		liblock_pthread_mutex_unlock(&notes->lock);
 		pr_err("Not enough memory for annotating '%s' symbol!\n",
 		       sym->name);
 		sleep(1);
@@ -224,7 +225,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
 	ip = he->ms.map->map_ip(he->ms.map, ip);
 	err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
 
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 
 	if (err == -ERANGE && !he->ms.map->erange_warned)
 		ui__warn_map_erange(he->ms.map, sym, ip);
@@ -243,7 +244,7 @@ static void perf_top__show_details(struct perf_top *top)
 	symbol = he->ms.sym;
 	notes = symbol__annotation(symbol);
 
-	pthread_mutex_lock(&notes->lock);
+	liblock_pthread_mutex_lock(&notes->lock);
 
 	if (notes->src == NULL)
 		goto out_unlock;
@@ -260,7 +261,7 @@ static void perf_top__show_details(struct perf_top *top)
 	if (more != 0)
 		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
 out_unlock:
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 }
 
 static const char		CONSOLE_CLEAR[] = "^[[H^[[2J";
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index f5ac774..2744dda 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_LIBLOCK
+define SOURCE_LIBLOCK
+#include <liblock/mutex.h>
+
+int main(void)
+{
+	liblock_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..b4eb842 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -14,6 +14,7 @@
 #include "util/run-command.h"
 #include "util/parse-events.h"
 #include "util/debugfs.h"
+#include "util/liblock.h"
 #include <pthread.h>
 
 const char perf_usage_string[] =
@@ -446,6 +447,9 @@ int main(int argc, const char **argv)
 {
 	const char *cmd;
 
+	liblock_init();
+	liblock_set_thread();
+
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 4aeb7d5..6bb5375 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -14,6 +14,7 @@
 #include "helpline.h"
 #include "keysyms.h"
 #include "../color.h"
+#include "../util/liblock.h"
 
 static int ui_browser__percent_color(struct ui_browser *browser,
 				     double percent, bool current)
@@ -240,9 +241,9 @@ void __ui_browser__show_title(struct ui_browser *browser, const char *title)
 
 void ui_browser__show_title(struct ui_browser *browser, const char *title)
 {
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	__ui_browser__show_title(browser, title);
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 }
 
 int ui_browser__show(struct ui_browser *browser, const char *title,
@@ -253,7 +254,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
 
 	ui_browser__refresh_dimensions(browser);
 
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	__ui_browser__show_title(browser, title);
 
 	browser->title = title;
@@ -265,15 +266,15 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
 	va_end(ap);
 	if (err > 0)
 		ui_helpline__push(browser->helpline);
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 	return err ? 0 : -1;
 }
 
 void ui_browser__hide(struct ui_browser *browser __maybe_unused)
 {
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	ui_helpline__pop();
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 }
 
 static void ui_browser__scrollbar_set(struct ui_browser *browser)
@@ -319,9 +320,9 @@ static int __ui_browser__refresh(struct ui_browser *browser)
 
 int ui_browser__refresh(struct ui_browser *browser)
 {
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	__ui_browser__refresh(browser);
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 
 	return 0;
 }
@@ -357,10 +358,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
 	while (1) {
 		off_t offset;
 
-		pthread_mutex_lock(&ui__lock);
+		liblock_pthread_mutex_lock(&ui__lock);
 		err = __ui_browser__refresh(browser);
 		SLsmg_refresh();
-		pthread_mutex_unlock(&ui__lock);
+		liblock_pthread_mutex_unlock(&ui__lock);
 		if (err < 0)
 			break;
 
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 5dab3ca..d639a9b 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -331,7 +331,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
 
 	browser->entries = RB_ROOT;
 
-	pthread_mutex_lock(&notes->lock);
+	liblock_pthread_mutex_lock(&notes->lock);
 
 	list_for_each_entry(pos, &notes->src->source, node) {
 		struct browser_disasm_line *bpos = disasm_line__browser(pos);
@@ -342,7 +342,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
 		}
 		disasm_rb_tree__insert(&browser->entries, bpos);
 	}
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 
 	browser->curr_hot = rb_last(&browser->entries);
 }
@@ -413,16 +413,16 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
 	}
 
 	notes = symbol__annotation(target);
-	pthread_mutex_lock(&notes->lock);
+	liblock_pthread_mutex_lock(&notes->lock);
 
 	if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
-		pthread_mutex_unlock(&notes->lock);
+		liblock_pthread_mutex_unlock(&notes->lock);
 		ui__warning("Not enough memory for annotating '%s' symbol!\n",
 			    target->name);
 		return true;
 	}
 
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 	symbol__tui_annotate(target, ms->map, evidx, hbt);
 	ui_browser__show_title(&browser->b, sym->name);
 	return true;
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ebb4cc1..105c5ba 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -4,10 +4,12 @@
 #include "../util/debug.h"
 #include "../util/hist.h"
 
-pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
+liblock_pthread_mutex_t ui__lock;
 
 void setup_browser(bool fallback_to_pager)
 {
+	liblock_pthread_mutex_init(&ui__lock, NULL);
+
 	if (!isatty(1) || dump_trace)
 		use_browser = 0;
 
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 2884d2f..a0cfc1e 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -41,7 +41,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
 	int ret;
 	static int backlog;
 
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	ret = vscnprintf(ui_helpline__last_msg + backlog,
 			sizeof(ui_helpline__last_msg) - backlog, format, ap);
 	backlog += ret;
@@ -51,7 +51,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
 		SLsmg_refresh();
 		backlog = 0;
 	}
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 
 	return ret;
 }
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index 6c2184d..dc86655 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -18,7 +18,7 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
 		return;
 
 	ui__refresh_dimensions(true);
-	pthread_mutex_lock(&ui__lock);
+	liblock_pthread_mutex_lock(&ui__lock);
 	y = SLtt_Screen_Rows / 2 - 2;
 	SLsmg_set_color(0);
 	SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
@@ -28,7 +28,7 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
 	bar = ((SLtt_Screen_Cols - 2) * curr) / total;
 	SLsmg_fill_region(y, 1, 1, bar, ' ');
 	SLsmg_refresh();
-	pthread_mutex_unlock(&ui__lock);
+	liblock_pthread_mutex_unlock(&ui__lock);
 }
 
 static struct ui_progress tui_progress_fns =
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 81efa19..04aeeea 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -21,10 +21,10 @@ void ui__refresh_dimensions(bool force)
 {
 	if (force || ui__need_resize) {
 		ui__need_resize = 0;
-		pthread_mutex_lock(&ui__lock);
+		liblock_pthread_mutex_lock(&ui__lock);
 		SLtt_get_screen_size();
 		SLsmg_reinit_smg();
-		pthread_mutex_unlock(&ui__lock);
+		liblock_pthread_mutex_unlock(&ui__lock);
 	}
 }
 
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index 092902e..19ac265 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -215,9 +215,9 @@ static int __ui__warning(const char *title, const char *format, va_list args)
 	if (vasprintf(&s, format, args) > 0) {
 		int key;
 
-		pthread_mutex_lock(&ui__lock);
+		liblock_pthread_mutex_lock(&ui__lock);
 		key = ui__question_window(title, s, "Press any key...", 0);
-		pthread_mutex_unlock(&ui__lock);
+		liblock_pthread_mutex_unlock(&ui__lock);
 		free(s);
 		return key;
 	}
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index d86359c..d0faaee 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -4,8 +4,9 @@
 #include <pthread.h>
 #include <stdbool.h>
 #include <linux/compiler.h>
+#include "../util/liblock.h"
 
-extern pthread_mutex_t ui__lock;
+extern liblock_pthread_mutex_t ui__lock;
 
 extern int use_browser;
 
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 07aaeea..31ac327 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -422,7 +422,7 @@ static struct ins *ins__find(const char *name)
 int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
 {
 	struct annotation *notes = symbol__annotation(sym);
-	pthread_mutex_init(&notes->lock, NULL);
+	liblock_pthread_mutex_init(&notes->lock, NULL);
 	return 0;
 }
 
@@ -456,11 +456,11 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
 {
 	struct annotation *notes = symbol__annotation(sym);
 
-	pthread_mutex_lock(&notes->lock);
+	liblock_pthread_mutex_lock(&notes->lock);
 	if (notes->src != NULL)
 		memset(notes->src->histograms, 0,
 		       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
-	pthread_mutex_unlock(&notes->lock);
+	liblock_pthread_mutex_unlock(&notes->lock);
 }
 
 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 8eec943..1323cff 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -9,6 +9,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <pthread.h>
+#include "liblock.h"
 
 struct ins;
 
@@ -101,7 +102,7 @@ struct annotated_source {
 };
 
 struct annotation {
-	pthread_mutex_t		lock;
+	liblock_pthread_mutex_t	lock;
 	struct annotated_source *src;
 };
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1b16dd1..5bb7281 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -47,7 +47,7 @@ void hists__init(struct hists *hists)
 	hists->entries_in = &hists->entries_in_array[0];
 	hists->entries_collapsed = RB_ROOT;
 	hists->entries = RB_ROOT;
-	pthread_mutex_init(&hists->lock, NULL);
+	liblock_pthread_mutex_init(&hists->lock, NULL);
 }
 
 void perf_evsel__init(struct perf_evsel *evsel,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cb17e2a..f0a847e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -277,7 +277,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
 	struct hist_entry *he;
 	int cmp;
 
-	pthread_mutex_lock(&hists->lock);
+	liblock_pthread_mutex_lock(&hists->lock);
 
 	p = &hists->entries_in->rb_node;
 
@@ -319,7 +319,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
 out:
 	hist_entry__add_cpumode_period(he, al->cpumode, period);
 out_unlock:
-	pthread_mutex_unlock(&hists->lock);
+	liblock_pthread_mutex_unlock(&hists->lock);
 	return he;
 }
 
@@ -463,13 +463,13 @@ static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
 {
 	struct rb_root *root;
 
-	pthread_mutex_lock(&hists->lock);
+	liblock_pthread_mutex_lock(&hists->lock);
 
 	root = hists->entries_in;
 	if (++hists->entries_in > &hists->entries_in_array[1])
 		hists->entries_in = &hists->entries_in_array[0];
 
-	pthread_mutex_unlock(&hists->lock);
+	liblock_pthread_mutex_unlock(&hists->lock);
 
 	return root;
 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8b091a5..f0eabd8 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 "liblock.h"
 
 extern struct callchain_param callchain_param;
 
@@ -65,7 +66,7 @@ struct hists {
 	const struct dso	*dso_filter;
 	const char		*uid_filter_str;
 	const char		*symbol_filter_str;
-	pthread_mutex_t		lock;
+	liblock_pthread_mutex_t	lock;
 	struct events_stats	stats;
 	u64			event_stream;
 	u16			col_len[HISTC_NR_COLS];
diff --git a/tools/perf/util/liblock.h b/tools/perf/util/liblock.h
new file mode 100644
index 0000000..55d7cc9
--- /dev/null
+++ b/tools/perf/util/liblock.h
@@ -0,0 +1,17 @@
+#ifdef LIBLOCK_SUPPORT
+
+#include <liblock/mutex.h>
+
+#else
+
+#define LIBLOCK_PTHREAD_MUTEX_INITIALIZER(mtx) PTHREAD_MUTEX_INITIALIZER
+#define liblock_init()
+#define liblock_set_thread()
+#define liblock_pthread_mutex_t         pthread_mutex_t
+#define liblock_pthread_mutex_init      pthread_mutex_init
+#define liblock_pthread_mutex_lock      pthread_mutex_lock
+#define liblock_pthread_mutex_unlock    pthread_mutex_unlock
+#define liblock_pthread_mutex_trylock   pthread_mutex_trylock
+#define liblock_pthread_mutex_destroy   pthread_mutex_destroy
+
+#endif
-- 
1.8.1.1


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

* Re: [PATCH 0/7] liblock: userspace lockdep
  2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
                   ` (6 preceding siblings ...)
  2013-02-01  4:47 ` [PATCH 7/7] perf: integrate liblock support into perf Sasha Levin
@ 2013-02-01  7:35 ` Pekka Enberg
  7 siblings, 0 replies; 11+ messages in thread
From: Pekka Enberg @ 2013-02-01  7:35 UTC (permalink / raw)
  To: Sasha Levin; +Cc: mingo, peterz, paulus, acme, linux-kernel

On Fri, Feb 1, 2013 at 6:47 AM, Sasha Levin <sasha.levin@oracle.com> wrote:
> This patch series adds a userspace lock correctnes validator into
> tools/lib/liblock.
>
> There are no changes to any kernel code whatsoever, lockdep is
> being used as is.
>
> First 6 patches are the liblock implementation, the last one is
> an example of liblock being used on an existing codebase.

This is awesome, Sasha! For the whole series:

Acked-by: Pekka Enberg <penberg@kernel.org>

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

* Re: [PATCH 2/7] liblock: public headers for mutex implementation
  2013-02-01  4:47 ` [PATCH 2/7] liblock: public headers for mutex implementation Sasha Levin
@ 2013-02-01  9:57   ` Ingo Molnar
  2013-02-01 14:20     ` Sasha Levin
  0 siblings, 1 reply; 11+ messages in thread
From: Ingo Molnar @ 2013-02-01  9:57 UTC (permalink / raw)
  To: Sasha Levin; +Cc: mingo, peterz, paulus, acme, penberg, linux-kernel


* Sasha Levin <sasha.levin@oracle.com> wrote:

> These headers provide the same API as their pthread mutex counterparts.
> 
> The design here is to allow to easily switch to liblock lock validation
> just by adding a "liblock_" to pthread_mutex_*() calls, which means that
> it's easy to integrate liblock into existing codebases.

I'd suggest to name the user-space counterpart 'liblockdep', to 
make it clear that this is user-space lockdep.

Regarding pthread_mutex_t checking, I think what we *really* 
want is a wrapper that can be activated via:

#define __USE_LIBLOCKDEP

And which then takes over the pthread primitives via:

  #define pthread_mutex_lock liblockdep_pthread_mutex_lock

or so.

That way the source code only needs a __USE_LIBLOCKDEP in one or 
two key places and checking is activated.

Thanks,

	Ingo

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

* Re: [PATCH 2/7] liblock: public headers for mutex implementation
  2013-02-01  9:57   ` Ingo Molnar
@ 2013-02-01 14:20     ` Sasha Levin
  0 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2013-02-01 14:20 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: mingo, peterz, paulus, acme, penberg, linux-kernel

On 02/01/2013 04:57 AM, Ingo Molnar wrote:
> 
> * Sasha Levin <sasha.levin@oracle.com> wrote:
> 
>> These headers provide the same API as their pthread mutex counterparts.
>>
>> The design here is to allow to easily switch to liblock lock validation
>> just by adding a "liblock_" to pthread_mutex_*() calls, which means that
>> it's easy to integrate liblock into existing codebases.
> 
> I'd suggest to name the user-space counterpart 'liblockdep', to 
> make it clear that this is user-space lockdep.

Agreed. Pekka also mentioned that liblock sounds to much like lib-block, so
renaming it to liblockdep will take care of that :)

> Regarding pthread_mutex_t checking, I think what we *really* 
> want is a wrapper that can be activated via:
> 
> #define __USE_LIBLOCKDEP
> 
> And which then takes over the pthread primitives via:
> 
>   #define pthread_mutex_lock liblockdep_pthread_mutex_lock
> 
> or so.
> 
> That way the source code only needs a __USE_LIBLOCKDEP in one or 
> two key places and checking is activated.

There are 2 issues I see with that:
 - api calls which are liblockdep specific (liblockdep_init() for example) would
still have to be wrapped somehow in the new code.
 - LIBLOCKDEP_PTHREAD_MUTEX_INIT(mtx) doesn't only change the name of the original
pthread mutex initializer, it also starts requiring the mutex name as parameter so
that it could pass it on to lockdep.

Dealing with these two will mean that there's a '#ifdef __USE_LIBLOCKDEP' both in
the lib and in the source code that uses it, which might be a bit confusing.

Either way, I'll resend the patch with these changes so we'll have a better view
of how it would look.


Thanks,
Sasha


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

end of thread, other threads:[~2013-02-01 14:20 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-01  4:47 [PATCH 0/7] liblock: userspace lockdep Sasha Levin
2013-02-01  4:47 ` [PATCH 1/7] liblock: wrap kernel/lockdep.c to allow usage from userspace Sasha Levin
2013-02-01  4:47 ` [PATCH 2/7] liblock: public headers for mutex implementation Sasha Levin
2013-02-01  9:57   ` Ingo Molnar
2013-02-01 14:20     ` Sasha Levin
2013-02-01  4:47 ` [PATCH 3/7] liblock: mutex test suite Sasha Levin
2013-02-01  4:47 ` [PATCH 4/7] liblock: public headers for rwlock implementation Sasha Levin
2013-02-01  4:47 ` [PATCH 5/7] liblock: rwlock test suite Sasha Levin
2013-02-01  4:47 ` [PATCH 6/7] liblock: add a MAINTAINERS entry Sasha Levin
2013-02-01  4:47 ` [PATCH 7/7] perf: integrate liblock support into perf Sasha Levin
2013-02-01  7:35 ` [PATCH 0/7] liblock: userspace lockdep Pekka Enberg

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).