#! /usr/bin/env stap
/*
* Copyright (C) 2009 Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*
* Description: displays which task is holding big kernel lock (BKL) when the
* number of waiting processes reaches a certain number.
*
* Run: stap bkl.stp [-G backtrace=]
*
* Author: Flavio Leitner
* Modified by Jose Castillo by adding
* print_backtrace() to get the codepath of the function
* that holds the bkl and an optional backtrace value that
* enables/disables print_backtrace().
*/
# how many tasks waiting on big lock
global waiting = 0
# when the current holder first obtained the lock
global holder_time
# are we printing backtraces?
global backtrace = -1
probe begin {
printf("stap ready\n");
}
probe kernel.function("_lock_kernel").call!,
kernel.function("lock_kernel").call
{
++waiting;
}
probe kernel.function("_lock_kernel").return!,
kernel.function("lock_kernel").return
{
# under biglock
holder_time = gettimeofday_us();
--waiting;
}
probe kernel.function("_unlock_kernel")!,
kernel.function("unlock_kernel")
{
# under biglock
backtrace_enabled = 0
if (waiting >= $1) {
if (holder_time != 0) {
waiting_time = gettimeofday_us() - holder_time
if ( backtrace != -1 && waiting_time >= backtrace ) {
backtrace_enabled = 1
}
}
else {
waiting_time = -1;
}
printf("%-25s: waiting(%d), holder: %s(%d) %dus\n",
ctime(gettimeofday_s()),
waiting,
execname(),
pid(),
(holder_time != 0) ? gettimeofday_us() - holder_time : -1);
if (backtrace_enabled)
print_backtrace()
}
holder_time = 0
}
probe end { printf("stap exiting\n"); }