const char *lock_name;
void *lock_addr;
int times_locked;
+ int times_lock_attempted;
+ struct timeval last_locked;
+ struct timeval last_unlocked;
int line_num;
enum ast_lock_type type;
/*! This thread is waiting on this lock */
for (i = 0; i < lock_info->num_locks; i++) {
if (lock_info->locks[i].lock_addr == lock_addr) {
lock_info->locks[i].times_locked++;
+ lock_info->locks[i].times_lock_attempted++;
+ lock_info->locks[i].last_locked = ast_tvnow();
#ifdef HAVE_BKTR
lock_info->locks[i].backtrace = bt;
#endif
lock_info->locks[i].lock_name = lock_name;
lock_info->locks[i].lock_addr = lock_addr;
lock_info->locks[i].times_locked = 1;
+ lock_info->locks[i].times_lock_attempted = 1;
+ lock_info->locks[i].last_locked = ast_tvnow();
lock_info->locks[i].type = type;
lock_info->locks[i].pending = 1;
#ifdef HAVE_BKTR
if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
lock_info->locks[lock_info->num_locks - 1].pending = -1;
lock_info->locks[lock_info->num_locks - 1].times_locked--;
+ lock_info->locks[lock_info->num_locks - 1].last_unlocked = ast_tvnow();
}
pthread_mutex_unlock(&lock_info->lock);
#endif /* ! LOW_MEMORY */
if (lock_info->locks[i].times_locked > 1) {
lock_info->locks[i].times_locked--;
+ lock_info->locks[i].last_unlocked = ast_tvnow();
#ifdef HAVE_BKTR
lock_info->locks[i].backtrace = bt;
#endif
int j;
ast_mutex_t *lock;
struct ast_lock_track *lt;
-
- ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d%s)\n",
+ struct timeval held_for;
+ struct timeval now = ast_tvnow();
+ char lock_time[32], unlock_time[32], held_time[32];
+
+ held_for = ast_tvsub(now, lock_info->locks[i].last_locked);
+ /* format time duration strings */
+ ast_format_duration_hh_mm_ss(lock_info->locks[i].last_locked.tv_sec,
+ lock_time, sizeof(lock_time));
+ ast_format_duration_hh_mm_ss(lock_info->locks[i].last_unlocked.tv_sec,
+ unlock_time, sizeof(unlock_time));
+ ast_format_duration_hh_mm_ss(held_for.tv_sec, held_time, sizeof(held_time));
+
+ ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p\n"
+ "=== %s.%06ld, %s.%06ld, %s.%06ld (%d, %d%s)\n",
lock_info->locks[i].pending > 0 ? "Waiting for " :
lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
lock_info->locks[i].file,
locktype2str(lock_info->locks[i].type),
lock_info->locks[i].line_num,
- lock_info->locks[i].func, lock_info->locks[i].lock_name,
+ lock_info->locks[i].func,
+ lock_info->locks[i].lock_name,
lock_info->locks[i].lock_addr,
+ lock_time,
+ lock_info->locks[i].last_locked.tv_usec,
+ unlock_time,
+ lock_info->locks[i].last_unlocked.tv_usec,
+ held_time,
+ held_for.tv_usec,
lock_info->locks[i].times_locked,
+ lock_info->locks[i].times_lock_attempted,
lock_info->locks[i].suspended ? " - suspended" : "");
#ifdef HAVE_BKTR
append_backtrace_information(str, lock_info->locks[i].backtrace);
#if !defined(LOW_MEMORY)
struct thr_lock_info *lock_info;
struct ast_str *str;
+ char print_time[32];
+ struct timeval now = ast_tvnow();
if (!(str = ast_str_create(4096))) {
return NULL;
}
+ ast_format_duration_hh_mm_ss(now.tv_sec, print_time, sizeof(print_time));
+
ast_str_append(&str, 0, "\n"
"=======================================================================\n"
"=== %s\n"
- "=== Currently Held Locks\n"
+ "=== Currently Held Locks at Time: %s.%06ld =================\n"
"=======================================================================\n"
"===\n"
- "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
- "===\n", ast_get_version());
-
+ "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr>\n"
+ "=== <locked at>, <failed at>, <held for> (attempts, times locked)\n"
+ "===\n", ast_get_version(), print_time, now.tv_usec);
if (!str) {
return NULL;
}