From: Sasha Levin <sasha.levin@oracle.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: torvalds@linux-foundation.org, mingo@kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/9] liblockdep: Wrap kernel/lockdep.c to allow usage from userspace
Date: Wed, 08 May 2013 09:27:46 -0400 [thread overview]
Message-ID: <518A52D2.4050505@oracle.com> (raw)
In-Reply-To: <20130508100143.GA6131@dyad.programming.kicks-ass.net>
On 05/08/2013 06:01 AM, Peter Zijlstra wrote:
> On Tue, Apr 30, 2013 at 02:54:33PM -0400, Sasha Levin wrote:
>> diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
>> new file mode 100644
>> index 0000000..eb5e481
>> --- /dev/null
>> +++ b/tools/lib/lockdep/common.c
>> @@ -0,0 +1,33 @@
>> +#include <stddef.h>
>> +#include <stdbool.h>
>> +#include <linux/compiler.h>
>> +#include <linux/lockdep.h>
>> +#include <unistd.h>
>> +#include <sys/syscall.h>
>> +
>> +static struct task_struct current_obj;
>> +
>> +/* lockdep wants these */
>> +bool debug_locks = true;
>> +bool debug_locks_silent;
>> +
>> +__attribute__((constructor)) static void liblockdep_init(void)
>> +{
>> + lockdep_init();
>> +}
>> +
>> +__attribute__((destructor)) static void liblockdep_exit(void)
>> +{
>> + debug_check_no_locks_held(¤t_obj);
>> +}
>> +
>> +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 ¤t_obj;
>> +}
>
>> diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
>> new file mode 100644
>> index 0000000..8e9a5c4
>> --- /dev/null
>> +++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
>> @@ -0,0 +1,58 @@
>> +#ifndef _LIBLOCKDEP_LOCKDEP_H_
>> +#define _LIBLOCKDEP_LOCKDEP_H_
>> +
>> +#include <sys/prctl.h>
>> +#include <sys/syscall.h>
>> +#include <string.h>
>> +#include <limits.h>
>> +#include <linux/utsname.h>
>> +
>> +
>> +#define MAX_LOCK_DEPTH 2000UL
>> +
>> +#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 struct task_struct *__curr(void);
>> +
>> +#define current (__curr())
>> +
>> +#define debug_locks_off() 1
>> +#define task_pid_nr(tsk) ((tsk)->pid)
>> +
>> +#define KSYM_NAME_LEN 128
>> +#define printk printf
>> +
>> +#define KERN_ERR
>> +#define KERN_CONT
>> +
>> +#define list_del_rcu list_del
>> +
>> +#define atomic_t unsigned long
>> +#define atomic_inc(x) ((*(x))++)
>> +
>> +static struct new_utsname *init_utsname(void)
>> +{
>> + static struct new_utsname n = (struct new_utsname) {
>> + .release = "liblockdep",
>> + .version = LIBLOCKDEP_VERSION,
>> + };
>> +
>> + return &n;
>> +}
>> +
>> +#define print_tainted() ""
>> +#define static_obj(x) 1
>> +
>> +#define debug_show_all_locks()
>> +
>> +#endif
>
> I don't see how this could possible work for threaded programs; you only have a
> single task_struct instance. Wouldn't you need something like the below?
[snip]
Hi Peter,
You're right - I broke multithreading for some odd reason (mostly me being stupid)
after having it working :/
It's enough to set the __thread flag on current_obj:
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
index eb5e481..8ef602f 100644
--- a/tools/lib/lockdep/common.c
+++ b/tools/lib/lockdep/common.c
@@ -5,7 +5,7 @@
#include <unistd.h>
#include <sys/syscall.h>
-static struct task_struct current_obj;
+static __thread struct task_struct current_obj;
/* lockdep wants these */
bool debug_locks = true;
Since we don't need any special initialization of the struct at any point. This
means that the patch above is enough and we don't need to hook pthread_create.
I've tested it by adding the following test to the tests dir:
#include <pthread.h>
#include <liblockdep/mutex.h>
#include "common.h"
pthread_mutex_t a, b;
static void *thread_a(void *arg)
{
LOCK_UNLOCK_2(a, b);
return NULL;
}
static void *thread_b(void *arg)
{
LOCK_UNLOCK_2(b, a);
return NULL;
}
void main(void)
{
pthread_t ta, tb;
pthread_mutex_init(&a, NULL);
pthread_mutex_init(&b, NULL);
pthread_create(&ta, NULL, thread_a, NULL);
pthread_create(&tb, NULL, thread_b, NULL);
pthread_join(ta, NULL);
pthread_join(tb, NULL);
}
Which, as expected, produced the following spew:
======================================================
[ INFO: possible circular locking dependency detected ]
liblockdep 0.0.1
-------------------------------------------------------
ABBA_MT/30105 is trying to acquire lock:
(&a){......}, at: /lib64/libpthread.so.0(+0x8f3b) [0x7ffa7d2f1f3b]
but task is already holding lock:
(&b){......}, at: /lib64/libpthread.so.0(+0x8f3b) [0x7ffa7d2f1f3b]
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&b){......}:
tests/ABBA_MT[0x4017e4]
tests/ABBA_MT[0x403381]
tests/ABBA_MT[0x40361b]
tests/ABBA_MT[0x403cb1]
tests/ABBA_MT[0x40476e]
tests/ABBA_MT[0x40522d]
tests/ABBA_MT[0x4012d2]
/lib64/libpthread.so.0(+0x8f3b)[0x7ffa7d2f1f3b]
/lib64/libc.so.6(clone+0x6d)[0x7ffa7d02d26d]
-> #0 (&a){......}:
tests/ABBA_MT[0x4017e4]
tests/ABBA_MT[0x402c95]
tests/ABBA_MT[0x403267]
tests/ABBA_MT[0x40361b]
tests/ABBA_MT[0x403cb1]
tests/ABBA_MT[0x40476e]
tests/ABBA_MT[0x40522d]
tests/ABBA_MT[0x401372]
/lib64/libpthread.so.0(+0x8f3b)[0x7ffa7d2f1f3b]
/lib64/libc.so.6(clone+0x6d)[0x7ffa7d02d26d]
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&b);
lock(&a);
lock(&b);
lock(&a);
*** DEADLOCK ***
1 lock held by ABBA_MT/30105:
#0: (&b){......}, at: /lib64/libpthread.so.0(+0x8f3b) [0x7ffa7d2f1f3b]
stack backtrace:
tests/ABBA_MT[0x401518]
tests/ABBA_MT[0x402d4f]
tests/ABBA_MT[0x403267]
tests/ABBA_MT[0x40361b]
tests/ABBA_MT[0x403cb1]
tests/ABBA_MT[0x40476e]
tests/ABBA_MT[0x40522d]
tests/ABBA_MT[0x401372]
/lib64/libpthread.so.0(+0x8f3b)[0x7ffa7d2f1f3b]
/lib64/libc.so.6(clone+0x6d)[0x7ffa7d02d26d]
Thanks,
Sasha
next prev parent reply other threads:[~2013-05-08 13:28 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-30 18:54 [PATCH 0/9] liblockdep: userspace lockdep Sasha Levin
2013-04-30 18:54 ` [PATCH 1/9] lockdep: Be nice about building from userspace Sasha Levin
2013-04-30 18:54 ` [PATCH 2/9] liblockdep: Wrap kernel/lockdep.c to allow usage " Sasha Levin
2013-05-08 10:01 ` Peter Zijlstra
2013-05-08 13:27 ` Sasha Levin [this message]
2013-05-08 13:35 ` Peter Zijlstra
2013-05-08 13:53 ` Sasha Levin
2013-04-30 18:54 ` [PATCH 3/9] liblockdep: Add public headers for pthread_mutex_t implementation Sasha Levin
2013-04-30 18:54 ` [PATCH 4/9] liblockdep: Add pthread_mutex_t test suite Sasha Levin
2013-04-30 18:54 ` [PATCH 5/9] liblockdep: Add public headers for pthread_rwlock_t implementation Sasha Levin
2013-04-30 18:54 ` [PATCH 6/9] liblockdep: Add pthread_rwlock_t test suite Sasha Levin
2013-04-30 18:54 ` [PATCH 7/9] liblockdep: Support using LD_PRELOAD Sasha Levin
2013-05-08 10:22 ` Peter Zijlstra
2013-05-08 13:29 ` Sasha Levin
2013-04-30 18:54 ` [PATCH 8/9] liblockdep: Add the 'lockdep' user-space utility Sasha Levin
2013-04-30 18:54 ` [PATCH 9/9] liblockdep: Add a MAINTAINERS entry Sasha Levin
2013-05-07 16:15 ` [PATCH 0/9] liblockdep: userspace lockdep Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=518A52D2.4050505@oracle.com \
--to=sasha.levin@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.