Commit 7246f4dc authored by Sasha Levin's avatar Sasha Levin Committed by Linus Torvalds

tools/lib/lockdep: drop liblockdep

TL;DR: While a tool like liblockdep is useful, it probably doesn't
belong within the kernel tree.

liblockdep attempts to reuse kernel code both directly (by directly
building the kernel's lockdep code) as well as indirectly (by using
sanitized headers). This makes liblockdep an integral part of the
kernel.

It also makes liblockdep quite unique: while other userspace code might
use sanitized headers, it generally doesn't attempt to use kernel code
directly which means that changes on the kernel side of things don't
affect (and break) it directly.

All our workflows and tooling around liblockdep don't support this
uniqueness. Changes that go into the kernel code aren't validated to not
break in-tree userspace code.

liblockdep ended up being very fragile, breaking over and over, to the
point that living in the same tree as the lockdep code lost most of it's
value.

liblockdep should continue living in an external tree, syncing with
the kernel often, in a controllable way.
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d9c8e52f
......@@ -10799,11 +10799,6 @@ F: drivers/ata/
F: include/linux/ata.h
F: include/linux/libata.h
LIBLOCKDEP
M: Sasha Levin <alexander.levin@microsoft.com>
S: Maintained
F: tools/lib/lockdep/
LIBNVDIMM BLK: MMIO-APERTURE DRIVER
M: Dan Williams <dan.j.williams@intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
......
......@@ -24,7 +24,6 @@ help:
@echo ' intel-speed-select - Intel Speed Select tool'
@echo ' kvm_stat - top-like utility for displaying kvm statistics'
@echo ' leds - LEDs tools'
@echo ' liblockdep - user-space wrapper for kernel locking-validator'
@echo ' objtool - an ELF object analysis tool'
@echo ' pci - PCI tools'
@echo ' perf - Linux performance measurement and analysis tool'
......@@ -72,9 +71,6 @@ cgroup counter firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objto
bpf/%: FORCE
$(call descend,$@)
liblockdep: FORCE
$(call descend,lib/lockdep)
libapi: FORCE
$(call descend,lib/api)
......@@ -101,7 +97,7 @@ freefall: FORCE
kvm_stat: FORCE
$(call descend,kvm/$@)
all: acpi cgroup counter cpupower gpio hv firewire liblockdep \
all: acpi cgroup counter cpupower gpio hv firewire \
perf selftests bootconfig spi turbostat usb \
virtio vm bpf x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat wmi \
......@@ -116,9 +112,6 @@ cpupower_install:
cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install:
$(call descend,$(@:_install=),install)
liblockdep_install:
$(call descend,lib/lockdep,install)
selftests_install:
$(call descend,testing/$(@:_install=),install)
......@@ -135,7 +128,7 @@ kvm_stat_install:
$(call descend,kvm/$(@:_install=),install)
install: acpi_install cgroup_install counter_install cpupower_install gpio_install \
hv_install firewire_install iio_install liblockdep_install \
hv_install firewire_install iio_install \
perf_install selftests_install turbostat_install usb_install \
virtio_install vm_install bpf_install x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install \
......@@ -151,9 +144,6 @@ cpupower_clean:
cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean:
$(call descend,$(@:_clean=),clean)
liblockdep_clean:
$(call descend,lib/lockdep,clean)
libapi_clean:
$(call descend,lib/api,clean)
......@@ -185,7 +175,7 @@ build_clean:
clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \
perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \
vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean \
gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
intel-speed-select_clean tracing_clean
......
# SPDX-License-Identifier: GPL-2.0-only
liblockdep.so.*
liblockdep-y += common.o lockdep.o preload.o rbtree.o
# SPDX-License-Identifier: GPL-2.0
# file format version
FILE_VERSION = 1
LIBLOCKDEP_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion)
# 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 and LD, or setting CROSS_COMPILE as a prefix.
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
$(call allow-override,AR,$(CROSS_COMPILE)ar)
$(call allow-override,LD,$(CROSS_COMPILE)ld)
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
libdir_relative = lib
libdir = $(prefix)/$(libdir_relative)
bindir_relative = bin
bindir = $(prefix)/$(bindir_relative)
export DESTDIR DESTDIR_SQ INSTALL
MAKEFLAGS += --no-print-directory
include ../../scripts/Makefile.include
# copy a bit from Linux kbuild
ifeq ("$(origin V)", "command line")
VERBOSE = $(V)
endif
ifndef VERBOSE
VERBOSE = 0
endif
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif
# Shell quotes
libdir_SQ = $(subst ','\'',$(libdir))
bindir_SQ = $(subst ','\'',$(bindir))
LIB_IN := $(OUTPUT)liblockdep-in.o
BIN_FILE = lockdep
LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
CONFIG_INCLUDES =
CONFIG_LIBS =
CONFIG_FLAGS =
OBJ = $@
N =
export Q VERBOSE
INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
# Set compile option CFLAGS if not set elsewhere
CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
CFLAGS += -fPIC
CFLAGS += -Wall
override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
ifeq ($(VERBOSE),1)
Q =
print_shared_lib_compile =
print_install =
else
Q = @
print_shared_lib_compile = echo ' LD '$(OBJ);
print_static_lib_build = echo ' LD '$(OBJ);
print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
endif
all:
export srctree OUTPUT CC LD CFLAGS V
include $(srctree)/tools/build/Makefile.include
do_compile_shared_library = \
($(print_shared_lib_compile) \
$(CC) $(LDFLAGS) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='$(@F)';$(shell ln -sf $(@F) $(@D)/liblockdep.so))
do_build_static_lib = \
($(print_static_lib_build) \
$(RM) $@; $(AR) rcs $@ $^)
CMD_TARGETS = $(LIB_FILE)
TARGETS = $(CMD_TARGETS)
all: fixdep all_cmd
all_cmd: $(CMD_TARGETS)
$(LIB_IN): force
$(Q)$(MAKE) $(build)=liblockdep
$(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
$(Q)$(do_compile_shared_library)
$(OUTPUT)liblockdep.a: $(LIB_IN)
$(Q)$(do_build_static_lib)
tags: force
$(RM) tags
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
--regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/'
TAGS: force
$(RM) TAGS
find . -name '*.[ch]' | xargs etags \
--regex='/_PE(\([^,)]*\).*/TEP_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),$(libdir_SQ))
$(Q)$(call do_install,$(BIN_FILE),$(bindir_SQ))
install: install_lib
clean:
$(RM) $(OUTPUT)*.o *~ $(TARGETS) $(OUTPUT)*.a $(OUTPUT)*liblockdep*.so* $(VERSION_FILES) $(OUTPUT).*.d $(OUTPUT).*.cmd
$(RM) tags TAGS
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)
// SPDX-License-Identifier: GPL-2.0
#include <stddef.h>
#include <stdbool.h>
#include <linux/compiler.h>
#include <linux/lockdep.h>
#include <unistd.h>
#include <sys/syscall.h>
static __thread struct task_struct current_obj;
/* lockdep wants these */
bool debug_locks = true;
bool debug_locks_silent;
__attribute__((destructor)) static void liblockdep_exit(void)
{
debug_check_no_locks_held();
}
struct task_struct *__curr(void)
{
if (current_obj.pid == 0) {
/* Makes lockdep output pretty */
prctl(PR_GET_NAME, current_obj.comm);
current_obj.pid = syscall(__NR_gettid);
}
return &current_obj;
}
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBLOCKDEP_COMMON_H
#define _LIBLOCKDEP_COMMON_H
#include <pthread.h>
#define NR_LOCKDEP_CACHING_CLASSES 2
#define MAX_LOCKDEP_SUBCLASSES 8UL
#ifndef CALLER_ADDR0
#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
#endif
#ifndef _RET_IP_
#define _RET_IP_ CALLER_ADDR0
#endif
#ifndef _THIS_IP_
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
#endif
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 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, unsigned long ip);
void lockdep_reset_lock(struct lockdep_map *lock);
void lockdep_register_key(struct lock_class_key *key);
void lockdep_unregister_key(struct lock_class_key *key);
extern void debug_check_no_locks_freed(const void *from, unsigned long len);
#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
{ .name = (_name), .key = (void *)(_key), }
#endif
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBLOCKDEP_MUTEX_H
#define _LIBLOCKDEP_MUTEX_H
#include <pthread.h>
#include "common.h"
struct liblockdep_pthread_mutex {
pthread_mutex_t mutex;
struct lock_class_key key;
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) \
({ \
lockdep_register_key(&(mutex)->key); \
__mutex_init((mutex), #mutex, &(mutex)->key, (mutexattr)); \
})
static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock)
{
lock_acquire(&lock->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_);
return pthread_mutex_lock(&lock->mutex);
}
static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock)
{
lock_release(&lock->dep_map, (unsigned long)_RET_IP_);
return pthread_mutex_unlock(&lock->mutex);
}
static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock)
{
lock_acquire(&lock->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_);
return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0;
}
static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
{
lockdep_reset_lock(&lock->dep_map);
lockdep_unregister_key(&lock->key);
return pthread_mutex_destroy(&lock->mutex);
}
#ifdef __USE_LIBLOCKDEP
#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
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBLOCKDEP_RWLOCK_H
#define _LIBLOCKDEP_RWLOCK_H
#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)
{
lock_acquire(&lock->dep_map, 0, 0, 2, 1, NULL, (unsigned long)_RET_IP_);
return pthread_rwlock_rdlock(&lock->rwlock);
}
static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock)
{
lock_release(&lock->dep_map, (unsigned long)_RET_IP_);
return pthread_rwlock_unlock(&lock->rwlock);
}
static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock)
{
lock_acquire(&lock->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_);
return pthread_rwlock_wrlock(&lock->rwlock);
}
static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock)
{
lock_acquire(&lock->dep_map, 0, 1, 2, 1, NULL, (unsigned long)_RET_IP_);
return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
}
static inline int liblockdep_pthread_rwlock_trywrlock(liblockdep_pthread_rwlock_t *lock)
{
lock_acquire(&lock->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_);
return pthread_rwlock_trywrlock(&lock->rwlock) == 0 ? 1 : 0;
}
static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
{
return pthread_rwlock_destroy(&lock->rwlock);
}
#ifdef __USE_LIBLOCKDEP
#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_trywrlock liblockdep_pthread_rwlock_trywrlock
#define pthread_rwlock_destroy liblockdep_rwlock_destroy
#endif
#endif
#!/bin/bash
LD_PRELOAD="./liblockdep.so $LD_PRELOAD" "$@"
// SPDX-License-Identifier: GPL-2.0
#include <linux/lockdep.h>
#include <stdlib.h>
/* Trivial API wrappers, we don't (yet) have RCU in user-space: */
#define hlist_for_each_entry_rcu hlist_for_each_entry
#define hlist_add_head_rcu hlist_add_head
#define hlist_del_rcu hlist_del
#define list_for_each_entry_rcu list_for_each_entry
#define list_add_tail_rcu list_add_tail
u32 prandom_u32(void)
{
/* Used only by lock_pin_lock() which is dead code */
abort();
}
void print_irqtrace_events(struct task_struct *curr)
{
abort();
}
static struct new_utsname *init_utsname(void)
{
static struct new_utsname n = (struct new_utsname) {
.release = "liblockdep",
.version = LIBLOCKDEP_VERSION,
};
return &n;
}
#include "../../../kernel/locking/lockdep.c"
#include "../../../kernel/locking/lockdep_internals.h"
#include "../../../kernel/locking/lockdep_states.h"
This diff is collapsed.
#include "../../lib/rbtree.c"
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
if ! make >/dev/null; then
echo "Building liblockdep failed."
echo "FAILED!"
exit 1
fi
find tests -name '*.c' | sort | while read -r i; do
testname=$(basename "$i" .c)
echo -ne "$testname... "
if gcc -o "tests/$testname" -pthread "$i" liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &&
timeout 1 "tests/$testname" 2>&1 | /bin/bash "tests/${testname}.sh"; then
echo "PASSED!"
else
echo "FAILED!"
fi
rm -f "tests/$testname"
done
find tests -name '*.c' | sort | while read -r i; do
testname=$(basename "$i" .c)
echo -ne "(PRELOAD) $testname... "
if gcc -o "tests/$testname" -pthread -Iinclude "$i" &&
timeout 1 ./lockdep "tests/$testname" 2>&1 |
/bin/bash "tests/${testname}.sh"; then
echo "PASSED!"
else
echo "FAILED!"
fi
rm -f "tests/$testname"
done
find tests -name '*.c' | sort | while read -r i; do
testname=$(basename "$i" .c)
echo -ne "(PRELOAD + Valgrind) $testname... "
if gcc -o "tests/$testname" -pthread -Iinclude "$i" &&
{ timeout 10 valgrind --read-var-info=yes ./lockdep "./tests/$testname" >& "tests/${testname}.vg.out"; true; } &&
/bin/bash "tests/${testname}.sh" < "tests/${testname}.vg.out" &&
! grep -Eq '(^==[0-9]*== (Invalid |Uninitialised ))|Mismatched free|Source and destination overlap| UME ' "tests/${testname}.vg.out"; then
echo "PASSED!"
else
echo "FAILED!"
fi
rm -f "tests/$testname"
done
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
int main(void)
{
pthread_mutex_t a;
pthread_mutex_init(&a, NULL);
pthread_mutex_lock(&a);
pthread_mutex_lock(&a);
return 0;
}
#!/bin/bash
grep -q 'WARNING: possible recursive locking detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
void main(void)
{
pthread_mutex_t a, b;
pthread_mutex_init(&a, NULL);
pthread_mutex_init(&b, NULL);
pthread_mutex_lock(&a);
pthread_mutex_lock(&b);
pthread_mutex_lock(&a);
}
#!/bin/bash
grep -q 'WARNING: possible recursive locking detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b;
pthread_mutex_init(&a, NULL);
pthread_mutex_init(&b, NULL);
LOCK_UNLOCK_2(a, b);
LOCK_UNLOCK_2(b, a);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
pthread_mutex_init(&a, NULL);
pthread_mutex_init(&b, NULL);
LOCK_UNLOCK_2(a, b);
LOCK_UNLOCK_2(b, a);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t a = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t b = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t bar;
void *ba_lock(void *arg)
{
int ret, i;
pthread_mutex_lock(&b);
if (pthread_barrier_wait(&bar) == PTHREAD_BARRIER_SERIAL_THREAD)
pthread_barrier_destroy(&bar);
pthread_mutex_lock(&a);
pthread_mutex_unlock(&a);
pthread_mutex_unlock(&b);
}
int main(void)
{
pthread_t t;
pthread_barrier_init(&bar, NULL, 2);
if (pthread_create(&t, NULL, ba_lock, NULL)) {
fprintf(stderr, "pthread_create() failed\n");
return 1;
}
pthread_mutex_lock(&a);
if (pthread_barrier_wait(&bar) == PTHREAD_BARRIER_SERIAL_THREAD)
pthread_barrier_destroy(&bar);
pthread_mutex_lock(&b);
pthread_mutex_unlock(&b);
pthread_mutex_unlock(&a);
pthread_join(t, NULL);
return 0;
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b, c;
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);
pthread_mutex_destroy(&c);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b, c, d;
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);
pthread_mutex_destroy(&d);
pthread_mutex_destroy(&c);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b, c;
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);
pthread_mutex_destroy(&c);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b, c, d;
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, c);
LOCK_UNLOCK_2(d, a);
pthread_mutex_destroy(&d);
pthread_mutex_destroy(&c);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
#include "common.h"
void main(void)
{
pthread_mutex_t a, b, c, d;
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);
pthread_mutex_destroy(&d);
pthread_mutex_destroy(&c);
pthread_mutex_destroy(&b);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: possible circular locking dependency detected'
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/rwlock.h>
void main(void)
{
pthread_rwlock_t a, b;
pthread_rwlock_init(&a, NULL);
pthread_rwlock_init(&b, NULL);
pthread_rwlock_wrlock(&a);
pthread_rwlock_rdlock(&b);
pthread_rwlock_wrlock(&a);
}
#!/bin/bash
grep -q 'WARNING: possible recursive locking detected'
/* SPDX-License-Identifier: GPL-2.0 */
#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
// SPDX-License-Identifier: GPL-2.0
#include <liblockdep/mutex.h>
void main(void)
{
pthread_mutex_t a;
pthread_mutex_init(&a, NULL);
pthread_mutex_lock(&a);
pthread_mutex_unlock(&a);
pthread_mutex_unlock(&a);
pthread_mutex_destroy(&a);
}
#!/bin/bash
grep -q 'WARNING: bad unlock balance detected'
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment