Skip to content

Commit

Permalink
core/lock: Add lock timeout warnings
Browse files Browse the repository at this point in the history
There are currently no timeout warnings for locks in skiboot. We assume
that the lock will eventually become free, which may not always be the
case.

This patch adds timeout warnings for locks. Any lock which spins for more
than 5 seconds will throw a warning and stacktrace for that thread. This is
useful for debugging siturations where a lock which hang, waiting for the
lock to be freed.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
Reviewed-by: Cyril Bur <cyril.bur@au1.ibm.com>
[stewart: make code match comment, have 5s timeout]
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
  • Loading branch information
m-brow authored and stewartsmith committed Mar 7, 2018
1 parent 2d4c774 commit 84186ef
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions core/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <processor.h>
#include <cpu.h>
#include <console.h>
#include <timebase.h>

/* Set to bust locks. Note, this is initialized to true because our
* lock debugging code is not going to work until we have the per
Expand Down Expand Up @@ -132,11 +133,27 @@ static void remove_lock_request(void)
this_cpu()->requested_lock = NULL;
}

#define LOCK_TIMEOUT_MS 5000
static inline bool lock_timeout(unsigned long start)
{
/* Print warning if lock has been spinning for more than TIMEOUT_MS */
unsigned long wait = tb_to_msecs(mftb());

if (wait - start > LOCK_TIMEOUT_MS) {
prlog(PR_WARNING, "WARNING: Lock has been "\
"spinning for %lums\n", wait - start);
backtrace();
return true;
}

return false;
}
#else
static inline void lock_check(struct lock *l) { };
static inline void unlock_check(struct lock *l) { };
static inline void add_lock_request(struct lock *l) { };
static inline void remove_lock_request(void) { };
static inline bool lock_timeout(unsigned long s) { return false; }
#endif /* DEBUG_LOCKS */

bool lock_held_by_me(struct lock *l)
Expand Down Expand Up @@ -181,6 +198,9 @@ bool try_lock_caller(struct lock *l, const char *owner)

void lock_caller(struct lock *l, const char *owner)
{
bool timeout_warn = false;
unsigned long start;

if (bust_locks)
return;

Expand All @@ -190,13 +210,20 @@ void lock_caller(struct lock *l, const char *owner)
return;
add_lock_request(l);

#ifdef DEBUG_LOCKS
start = tb_to_msecs(mftb());
#endif

for (;;) {
if (try_lock_caller(l, owner))
break;
smt_lowest();
while (l->lock_val)
barrier();
smt_medium();

if (!timeout_warn)
timeout_warn = lock_timeout(start);
}

remove_lock_request();
Expand Down

0 comments on commit 84186ef

Please sign in to comment.