2 * lock-tracer.c: Runtime simple lock tracer
5 * Rodrigo Kumpera (rkumpera@novell.com)
13 #include <sys/types.h>
16 #ifdef HAVE_EXECINFO_H
20 #include <mono/io-layer/io-layer.h>
22 #include "lock-tracer.h"
25 * This is a very simple lock trace implementation. It can be used to verify that the runtime is
26 * correctly following all locking rules.
28 * To log more kind of locks just do the following:
29 * - add an entry into the RuntimeLocks enum
30 * - change EnterCriticalSection(mutex) to mono_locks_acquire (mutex, LockName)
31 * - change LeaveCriticalSection to mono_locks_release (mutex, LockName)
32 * - change the decoder to understand the new lock kind.
35 * - Use unbuffered IO without fsync
36 * - Switch to a binary log format
37 * - Enable tracing of more runtime locks
38 * - Add lock check assertions (must_not_hold_any_lock_but, must_hold_lock, etc)
39 * This should be used to verify methods that expect that a given lock is held at entrypoint, for example.
41 * To use the trace, define LOCK_TRACER in lock-trace.h and when running mono define MONO_ENABLE_LOCK_TRACER.
42 * This will produce a locks.ZZZ where ZZZ is the pid of the mono process.
43 * Use the decoder to verify the result.
48 static FILE *trace_file
;
49 static CRITICAL_SECTION tracer_lock
;
52 RECORD_MUST_NOT_HOLD_ANY
,
53 RECORD_MUST_NOT_HOLD_ONE
,
60 mono_locks_tracer_init (void)
63 InitializeCriticalSection (&tracer_lock
);
64 if (!getenv ("MONO_ENABLE_LOCK_TRACER"))
66 name
= g_strdup_printf ("locks.%d", getpid ());
67 trace_file
= fopen (name
, "w+");
72 #ifdef HAVE_EXECINFO_H
75 mono_backtrace (gpointer array
[], int traces
)
77 return backtrace (array
, traces
);
83 mono_backtrace (gpointer array
[], int traces
)
91 add_record (RecordType record_kind
, RuntimeLocks kind
, gpointer lock
)
98 memset (frames
, 0, sizeof (gpointer
));
99 mono_backtrace (frames
, 6);
101 /*We only dump 5 frames, which should be more than enough to most analysis.*/
102 msg
= g_strdup_printf ("%x,%d,%d,%p,%p,%p,%p,%p,%p\n", (guint32
)GetCurrentThreadId (), record_kind
, kind
, lock
, frames
[1], frames
[2], frames
[3], frames
[4], frames
[5]);
103 fwrite (msg
, strlen (msg
), 1, trace_file
);
109 mono_locks_lock_acquired (RuntimeLocks kind
, gpointer lock
)
111 add_record (RECORD_LOCK_ACQUIRED
, kind
, lock
);
115 mono_locks_lock_released (RuntimeLocks kind
, gpointer lock
)
117 add_record (RECORD_LOCK_RELEASED
, kind
, lock
);