[Skiboot] [PATCH 7/7] core/lock: Add debug options to store backtrace of where lock was taken

Andrew Donnellan andrew.donnellan at au1.ibm.com
Mon Mar 18 15:43:29 AEDT 2019


On 18/3/19 3:29 pm, Andrew Donnellan wrote:
> Contrary to popular belief, skiboot developers are imperfect and
> occasionally write locking bugs. When we exit skiboot, we check if we're
> still holding any locks, and if so, we print an error with a list of the
> locks currently held and the locations where they were taken.
> 
> However, this only tells us the location where lock() was called, which may
> not be enough to work out what's going on. To give us more to go on with,
> we can store backtrace data in the lock and print that out when we
> unexpectedly still hold locks.
> 
> Because the backtrace data is rather big, we only enable this if
> DEBUG_LOCKS_BACKTRACE is defined, which in turn is switched on when
> DEBUG=1.
> 
> Signed-off-by: Andrew Donnellan <andrew.donnellan at au1.ibm.com>

Apparently this causes a test failure in core/test/run-mem_region, which 
is interesting!

> 
> ---
> 
> RFC->v1:
> - Switch this on when DEBUG=1 (Stewart)
> - Rebase on top of some backtrace API changes
> ---
>   core/lock.c      | 19 +++++++++++++++++--
>   include/config.h |  7 +++++++
>   include/lock.h   | 11 +++++++++++
>   3 files changed, 35 insertions(+), 2 deletions(-)
> 
> diff --git a/core/lock.c b/core/lock.c
> index fbf0b21ed5c6..6fbb5eb9bf5e 100644
> --- a/core/lock.c
> +++ b/core/lock.c
> @@ -208,6 +208,12 @@ bool try_lock_caller(struct lock *l, const char *owner)
>   		cpu->con_suspend++;
>   	if (__try_lock(cpu, l)) {
>   		l->owner = owner;
> +
> +#ifdef DEBUG_LOCKS_BACKTRACE
> +		backtrace_create(l->bt_buf, LOCKS_BACKTRACE_MAX_ENTS,
> +				 &l->bt_metadata);
> +#endif
> +
>   		list_add(&cpu->locks_held, &l->list);
>   		return true;
>   	}
> @@ -312,8 +318,12 @@ void dump_locks_list(void)
>   	struct lock *l;
>   
>   	prlog(PR_ERR, "Locks held:\n");
> -	list_for_each(&this_cpu()->locks_held, l, list)
> +	list_for_each(&this_cpu()->locks_held, l, list) {
>   		prlog(PR_ERR, "  %s\n", l->owner);
> +#ifdef DEBUG_LOCKS_BACKTRACE
> +		backtrace_print(l->bt_buf, &l->bt_metadata, NULL, NULL, true);
> +#endif
> +	}
>   }
>   
>   void drop_my_locks(bool warn)
> @@ -322,8 +332,13 @@ void drop_my_locks(bool warn)
>   
>   	disable_fast_reboot("Lock corruption");
>   	while((l = list_top(&this_cpu()->locks_held, struct lock, list)) != NULL) {
> -		if (warn)
> +		if (warn) {
>   			prlog(PR_ERR, "  %s\n", l->owner);
> +#ifdef DEBUG_LOCKS_BACKTRACE
> +			backtrace_print(l->bt_buf, &l->bt_metadata, NULL, NULL,
> +					true);
> +#endif
> +		}
>   		unlock(l);
>   	}
>   }
> diff --git a/include/config.h b/include/config.h
> index 438f1b0f3373..7059e39ddb91 100644
> --- a/include/config.h
> +++ b/include/config.h
> @@ -39,6 +39,13 @@
>   /* Enable lock debugging */
>   #define DEBUG_LOCKS		1
>   
> +/* Enable printing of backtraces when locks not released */
> +#ifdef DEBUG
> +#define DEBUG_LOCKS_BACKTRACE  1
> +#else
> +//#define DEBUG_LOCKS_BACKTRACE	1
> +#endif
> +
>   /* Enable lock dependency checker */
>   #define DEADLOCK_CHECKER	1
>   
> diff --git a/include/lock.h b/include/lock.h
> index b18757394dbb..e08ec08fcdfb 100644
> --- a/include/lock.h
> +++ b/include/lock.h
> @@ -23,6 +23,12 @@
>   #include <ccan/list/list.h>
>   #include <ccan/str/str.h>
>   
> +#ifdef DEBUG_LOCKS_BACKTRACE
> +#include <stack.h>
> +
> +#define LOCKS_BACKTRACE_MAX_ENTS	60
> +#endif
> +
>   struct lock {
>   	/* Lock value has bit 63 as lock bit and the PIR of the owner
>   	 * in the top 32-bit
> @@ -38,6 +44,11 @@ struct lock {
>   	/* file/line of lock owner */
>   	const char *owner;
>   
> +#ifdef DEBUG_LOCKS_BACKTRACE
> +	struct bt_entry bt_buf[LOCKS_BACKTRACE_MAX_ENTS];
> +	struct bt_metadata bt_metadata;
> +#endif
> +
>   	/* linkage in per-cpu list of owned locks */
>   	struct list_node list;
>   };
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan at au1.ibm.com  IBM Australia Limited



More information about the Skiboot mailing list