(long) getpid(), (long) gettid(), ## args)
struct urcu_debug_entry {
- void *ip;
+ char *func;
int depth;
};
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)
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);
}
}
* 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;
* 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.
* 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);
* 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();
}
* 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;
* 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;