Detect unbalanced lock/unlock
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 13 Nov 2014 20:46:04 +0000 (15:46 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 13 Nov 2014 20:46:04 +0000 (15:46 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
urcu-checker.c
urcu/static/urcu-bp.h
urcu/static/urcu-qsbr.h
urcu/static/urcu.h

index cd4721d3cd95f1a1a4f2454dd5c19b99c5807ff6..97220ab73a9745684f1b4640d2662b5f5121cef4 100644 (file)
@@ -67,7 +67,7 @@ static inline pid_t gettid(void)
                (long) getpid(), (long) gettid(), ## args)
 
 struct urcu_debug_entry {
-       void *ip;
+       char *func;
        int depth;
 };
 
@@ -145,16 +145,32 @@ void print_bt(struct backtrace *bt)
 void rcu_read_lock_debug(void)
 {
        struct urcu_debug_stack *r = &URCU_TLS(rcu_debug_stack);
+       char *func = get_symbol(__builtin_return_address(0));
 
-       r->stack[r->stackend++].ip = __builtin_return_address(0);
+       r->stack[r->stackend++].func = func;
 }
 
 void rcu_read_unlock_debug(void)
 {
        struct urcu_debug_stack *r = &URCU_TLS(rcu_debug_stack);
+       char *func = get_symbol(__builtin_return_address(0));
 
        assert(r->stackend != 0);
-       r->stack[--r->stackend].ip = NULL;
+       if (r->stack[r->stackend - 1].func && func &&
+                       strcmp(r->stack[r->stackend - 1].func,
+                               func) != 0) {
+               struct backtrace bt;
+
+               err_printf("URCU lock/unlock caller mismatch: lock by <%s> unlock by <%s>\n",
+                       r->stack[r->stackend - 1].func, func);
+               save_backtrace(&bt);
+               print_bt(&bt);
+               free_backtrace(&bt);
+       }
+       r->stackend--;
+       free(r->stack[r->stackend].func);
+       r->stack[r->stackend].func = NULL;
+       free(func);
 }
 
 void rcu_read_ongoing_check_debug(const char *func)
@@ -163,12 +179,13 @@ void rcu_read_ongoing_check_debug(const char *func)
 
        if (r->stackend == 0) {
                struct backtrace bt;
+               char *func = get_symbol(__builtin_return_address(0));
 
                err_printf("rcu_dereference() used outside of critical section at %p <%s>\n",
-                       __builtin_return_address(0),
-                       get_symbol(__builtin_return_address(0)));
+                       __builtin_return_address(0), func);
                save_backtrace(&bt);
                print_bt(&bt);
                free_backtrace(&bt);
+               free(func);
        }
 }
index 0bdefff2b15de3339806e4e3df7cb2117148a651..0ae18d6ca48b58de543ffb13c8a828b448ec988f 100644 (file)
@@ -152,7 +152,8 @@ static inline void _rcu_read_lock_update(unsigned long tmp)
  * intent is that this function meets the 10-line criterion in LGPL,
  * allowing this function to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_lock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_lock(void)
 {
        unsigned long tmp;
 
@@ -169,7 +170,8 @@ static inline void _rcu_read_lock(void)
  * 10 lines of code, and is intended to be usable by non-LGPL code, as
  * called out in LGPL.
  */
-static inline void _rcu_read_unlock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_unlock(void)
 {
        /*
         * Finish using rcu before decrementing the pointer.
index 1ef830aba1833fa888ebdfa3ee4daa1034cbdf8c..4092d6bc4f67ffe34c5b190b3f2923504dc25039 100644 (file)
@@ -131,7 +131,8 @@ static inline enum rcu_state rcu_reader_state(unsigned long *ctr)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_lock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_lock(void)
 {
        rcu_read_lock_debug();
        rcu_assert(URCU_TLS(rcu_reader).ctr);
@@ -144,7 +145,8 @@ static inline void _rcu_read_lock(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_unlock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_unlock(void)
 {
        rcu_read_unlock_debug();
 }
index 0fe32e88cea48241a463054f4e4411aee0428e3a..9659a2f0d822bb077fc4d63bcae17a013751ca10 100644 (file)
@@ -216,7 +216,8 @@ static inline void _rcu_read_lock_update(unsigned long tmp)
  * intent is that this function meets the 10-line criterion in LGPL,
  * allowing this function to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_lock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_lock(void)
 {
        unsigned long tmp;
 
@@ -250,7 +251,8 @@ static inline void _rcu_read_unlock_update_and_wakeup(unsigned long tmp)
  * helper are smaller than 10 lines of code, and are intended to be
  * usable by non-LGPL code, as called out in LGPL.
  */
-static inline void _rcu_read_unlock(void)
+static inline __attribute__((always_inline))
+void _rcu_read_unlock(void)
 {
        unsigned long tmp;
 
This page took 0.028118 seconds and 4 git commands to generate.