summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-09-16 04:36:19 +0200
committerLennart Poettering <lennart@poettering.net>2009-09-16 04:36:19 +0200
commit211f1a9e33a1cac33a7b9a88000faaf56258f281 (patch)
tree3d1601258ee480964424e2f24805724c4dcd9f5b
parent5e0ac1c24222ac9764c25a851e9f5f209959b924 (diff)
optionally track RT status of threads using a mutex
-rw-r--r--mutrace.c82
-rwxr-xr-xmutrace.in16
2 files changed, 76 insertions, 22 deletions
diff --git a/mutrace.c b/mutrace.c
index 0d5235a..279ca0f 100644
--- a/mutrace.c
+++ b/mutrace.c
@@ -35,6 +35,7 @@
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/prctl.h>
+#include <sched.h>
#include <malloc.h>
/* FIXMES:
@@ -43,6 +44,13 @@
*
*/
+#ifndef SCHED_RESET_ON_FORK
+/* "Your libc lacks the definition of SCHED_RESET_ON_FORK. We'll now
+ * define it ourselves, however make sure your kernel is new
+ * enough! */
+#define SCHED_RESET_ON_FORK 0x40000000
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
#define DEBUG_TRAP __asm__("int $3")
#else
@@ -56,7 +64,9 @@ struct mutex_info {
pthread_mutex_t *mutex;
int type, protocol;
- bool broken;
+ bool broken:1;
+ bool realtime:1;
+ bool dead:1;
unsigned n_lock_level;
@@ -90,6 +100,7 @@ static unsigned show_n_contended_min = 0;
static unsigned show_n_max = 10;
static bool raise_trap = false;
+static bool track_rt = false;
static int (*real_pthread_mutex_init)(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) = NULL;
static int (*real_pthread_mutex_destroy)(pthread_mutex_t *mutex) = NULL;
@@ -290,6 +301,9 @@ static void setup(void) {
if (getenv("MUTRACE_TRAP"))
raise_trap = true;
+ if (getenv("MUTRACE_TRACK_RT"))
+ track_rt = true;
+
alive_mutexes = calloc(hash_size, sizeof(struct mutex_info*));
assert(alive_mutexes);
@@ -377,6 +391,10 @@ static int mutex_info_compare(const void *_a, const void *_b) {
static bool mutex_info_show(struct mutex_info *mi) {
+ /* Mutexes used by real-time code are always noteworthy */
+ if (mi->realtime)
+ return true;
+
if (mi->n_locked < show_n_locked_min)
return false;
@@ -401,40 +419,40 @@ static bool mutex_info_dump(struct mutex_info *mi) {
return true;
}
-static const char* mutex_type_name(int type) {
+static char mutex_type_name(int type) {
switch (type) {
case PTHREAD_MUTEX_NORMAL:
- return "normal";
+ return '-';
case PTHREAD_MUTEX_RECURSIVE:
- return "recursive";
+ return 'r';
case PTHREAD_MUTEX_ERRORCHECK:
- return "errorcheck";
+ return 'e';
case PTHREAD_MUTEX_ADAPTIVE_NP:
- return "adaptive";
+ return 'a';
default:
- return "unknown";
+ return '?';
}
}
-static const char* mutex_protocol_name(int protocol) {
+static char mutex_protocol_name(int protocol) {
switch (protocol) {
case PTHREAD_PRIO_NONE:
- return "none";
+ return '-';
case PTHREAD_PRIO_INHERIT:
- return "inherit";
+ return 'i';
case PTHREAD_PRIO_PROTECT:
- return "protect";
+ return 'p';
default:
- return "unknown";
+ return '?';
}
}
@@ -444,7 +462,7 @@ static bool mutex_info_stat(struct mutex_info *mi) {
return false;
fprintf(stderr,
- "%8u %8u %8u %8u %12.3f %12.3f %12.3f %10s %7s%s\n",
+ "%8u %8u %8u %8u %12.3f %12.3f %12.3f %c%c%c%c\n",
mi->id,
mi->n_locked,
mi->n_owner_changed,
@@ -452,9 +470,10 @@ static bool mutex_info_stat(struct mutex_info *mi) {
(double) mi->nsec_locked_total / 1000000.0,
(double) mi->nsec_locked_total / mi->n_locked / 1000000.0,
(double) mi->nsec_locked_max / 1000000.0,
+ mi->broken ? '!' : (mi->dead ? 'x' : '-'),
+ mi->realtime ? 'R' : '-',
mutex_type_name(mi->type),
- mutex_protocol_name(mi->protocol),
- mi->broken ? " (inconsistent!)" : "");
+ mutex_protocol_name(mi->protocol));
return true;
}
@@ -524,7 +543,7 @@ static void show_summary(void) {
"\n"
"mutrace: Showing %u most contended mutexes:\n"
"\n"
- " Mutex # Locked Changed Cont. tot.Time[ms] avg.Time[ms] max.Time[ms] Type Prot.\n",
+ " Mutex # Locked Changed Cont. tot.Time[ms] avg.Time[ms] max.Time[ms] Flag\n",
m);
for (i = 0, m = 0; i < n && (show_n_max <= 0 || m < show_n_max); i++)
@@ -533,7 +552,19 @@ static void show_summary(void) {
if (i < n)
fprintf(stderr,
- " ... ... ... ... ... ... ... ... ...\n");
+ " ... ... ... ... ... ... ... ||||\n");
+ else
+ fprintf(stderr,
+ " ||||\n");
+
+ fprintf(stderr,
+ " /|||\n"
+ " State: x = dead, ! = inconsistent /||\n"
+ " Use: R = used in realtime thread /|\n"
+ " Type: r = RECURSIVE, e = ERRRORCHECK, a = ADAPTIVE /\n"
+ " Protocol: i = INHERIT, p = PROTECT \n");
+
+
} else
fprintf(stderr,
"\n"
@@ -591,6 +622,19 @@ void _Exit(int status) {
real__Exit(status);
}
+static bool is_realtime(void) {
+ int policy;
+
+ policy = sched_getscheduler(_gettid());
+ assert(policy >= 0);
+
+ policy &= ~SCHED_RESET_ON_FORK;
+
+ return
+ policy == SCHED_FIFO ||
+ policy == SCHED_RR;
+}
+
static bool verify_frame(const char *s) {
if (strstr(s, "/" SONAME "("))
@@ -694,6 +738,7 @@ static void mutex_info_remove(unsigned u, pthread_mutex_t *mutex) {
else
alive_mutexes[u] = mi->next;
+ mi->dead = true;
mi->next = dead_mutexes[u];
dead_mutexes[u] = mi;
}
@@ -823,6 +868,9 @@ static void mutex_lock(pthread_mutex_t *mutex, bool busy) {
mi->last_owner = tid;
}
+ if (track_rt && !mi->realtime && is_realtime())
+ mi->realtime = true;
+
mi->nsec_timestamp = nsec_now();
mutex_info_release(mutex);
diff --git a/mutrace.in b/mutrace.in
index 0d06ec3..8225f03 100755
--- a/mutrace.in
+++ b/mutrace.in
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public
# License along with mutrace. If not, see <http://www.gnu.org/licenses/>.
-if ! TEMP=`getopt -o h --long hash-size:,frames:,locked-min:,owner-changed-min:,contended-min:,max:,trap,help,all -n mutrace -- "$@"` ; then
+if ! TEMP=`getopt -o +arh --long hash-size:,frames:,locked-min:,owner-changed-min:,contended-min:,max:,trap,help,all -n mutrace -- "$@"` ; then
exit 1
fi
@@ -60,7 +60,12 @@ while : ; do
shift 1
;;
- --all)
+ -r|--track-rt)
+ export MUTRACE_TRACK_RT=1
+ shift 1
+ ;;
+
+ -a|--all)
export MUTRACE_LOCKED_MIN=0
export MUTRACE_OWNER_CHANGED_MIN=0
export MUTRACE_CONTENDED_MIN=0
@@ -72,7 +77,7 @@ while : ; do
cat <<EOF
@PACKAGE_STRING@
-Usage: @PACKAGE_NAME@ [OPTIONS...] -- APPLICATION [ARGUMENTS...]
+Usage: @PACKAGE_NAME@ [OPTIONS...] APPLICATION [ARGUMENTS...]
COMMANDS:
-h, --help Show this help
@@ -91,12 +96,13 @@ OPTIONS:
--all Show all mutexes, overrides the values of the
three values above
+ -r, --track-rt Track for each mutex if it was accessed from
+ a realtime thread
--trap Trigger a debugger trap each time a mutex
inconsistency is detected (for use in
conjunction with gdb)
EOF
-
- shift 1
+ exit 0
;;
--)
shift