Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

2009-02-19 Rodrigo Kumpera <rkumpera@novell.com>

	* Makefile.am: Add lock-tracer.h and lock-trace.c.

	* appdomain.c: Call the tracer init function.

 	* domain-internals.h: Enable the tracer for the domain locks.

	* image.c: Enable the tracer for image locks.

	* loader.c: Enable the trace for the loader lock.

	* lock-tracer.h:
	* lock-tracer.c: Initial implementation of the lock trace utility.
	The tracer requires a compile time define to be enabled and a env var
	to be enabled at runtime.

svn path=/trunk/mono/; revision=127476
  • Loading branch information...
commit 34feb3493b8c3b9723fb9302b7c586e1bf4c8db8 1 parent bd6746f
Rodrigo Kumpera kumpera authored
17 mono/metadata/ChangeLog
... ... @@ -1,5 +1,22 @@
1 1 2009-02-19 Rodrigo Kumpera <rkumpera@novell.com>
2 2
  3 + * Makefile.am: Add lock-tracer.h and lock-trace.c.
  4 +
  5 + * appdomain.c: Call the tracer init function.
  6 +
  7 + * domain-internals.h: Enable the tracer for the domain locks.
  8 +
  9 + * image.c: Enable the tracer for image locks.
  10 +
  11 + * loader.c: Enable the trace for the loader lock.
  12 +
  13 + * lock-tracer.h:
  14 + * lock-tracer.c: Initial implementation of the lock trace utility.
  15 + The tracer requires a compile time define to be enabled and a env var
  16 + to be enabled at runtime.
  17 +
  18 +2009-02-19 Rodrigo Kumpera <rkumpera@novell.com>
  19 +
3 20 * domain.c (mono_domain_code_foreach): Improve documentation.
4 21
5 22 2009-02-19 Rodrigo Kumpera <rkumpera@novell.com>
4 mono/metadata/Makefile.am
@@ -143,7 +143,9 @@ libmonoruntime_la_SOURCES = \
143 143 debug-helpers.c \
144 144 generic-sharing.c \
145 145 mempool-internals.h \
146   - metadata-verify.c
  146 + metadata-verify.c \
  147 + lock-tracer.c \
  148 + lock-tracer.h
147 149
148 150 libmonoruntime_static_la_SOURCES = $(libmonoruntime_la_SOURCES)
149 151
3  mono/metadata/appdomain.c
@@ -47,6 +47,7 @@
47 47 #include <mono/metadata/mono-debug.h>
48 48 #include <mono/metadata/attach.h>
49 49 #include <mono/metadata/file-io.h>
  50 +#include <mono/metadata/lock-tracer.h>
50 51 #include <mono/utils/mono-uri.h>
51 52 #include <mono/utils/mono-logger.h>
52 53 #include <mono/utils/mono-path.h>
@@ -236,6 +237,8 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb,
236 237
237 238 mono_attach_init ();
238 239
  240 + mono_locks_tracer_init ();
  241 +
239 242 /* mscorlib is loaded before we install the load hook */
240 243 mono_domain_fire_assembly_load (mono_defaults.corlib->assembly, NULL);
241 244
13 mono/metadata/domain-internals.h
@@ -5,6 +5,7 @@
5 5 #define __MONO_METADATA_DOMAIN_INTERNALS_H__
6 6
7 7 #include <mono/metadata/appdomain.h>
  8 +#include <mono/metadata/lock-tracer.h>
8 9 #include <mono/utils/mono-codeman.h>
9 10 #include <mono/utils/mono-hash.h>
10 11 #include <mono/utils/mono-compiler.h>
@@ -249,12 +250,12 @@ typedef struct {
249 250 const AssemblyVersionSet version_sets [2];
250 251 } MonoRuntimeInfo;
251 252
252   -#define mono_domain_lock(domain) EnterCriticalSection(&(domain)->lock)
253   -#define mono_domain_unlock(domain) LeaveCriticalSection(&(domain)->lock)
254   -#define mono_domain_assemblies_lock(domain) EnterCriticalSection(&(domain)->assemblies_lock)
255   -#define mono_domain_assemblies_unlock(domain) LeaveCriticalSection(&(domain)->assemblies_lock)
256   -#define mono_domain_jit_code_hash_lock(domain) EnterCriticalSection(&(domain)->jit_code_hash_lock)
257   -#define mono_domain_jit_code_hash_unlock(domain) LeaveCriticalSection(&(domain)->jit_code_hash_lock)
  253 +#define mono_domain_lock(domain) mono_locks_acquire(&(domain)->lock, DomainLock)
  254 +#define mono_domain_unlock(domain) mono_locks_release(&(domain)->lock, DomainLock)
  255 +#define mono_domain_assemblies_lock(domain) mono_locks_acquire(&(domain)->assemblies_lock, DomainAssembliesLock)
  256 +#define mono_domain_assemblies_unlock(domain) mono_locks_release(&(domain)->assemblies_lock, DomainAssembliesLock)
  257 +#define mono_domain_jit_code_hash_lock(domain) mono_locks_acquire(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
  258 +#define mono_domain_jit_code_hash_unlock(domain) mono_locks_release(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
258 259
259 260 typedef MonoDomain* (*MonoLoadFunc) (const char *filename, const char *runtime_version);
260 261
4 mono/metadata/image.c
@@ -2060,13 +2060,13 @@ g_slist_append_image (MonoImage *image, GSList *list, gpointer data)
2060 2060 void
2061 2061 mono_image_lock (MonoImage *image)
2062 2062 {
2063   - EnterCriticalSection (&image->lock);
  2063 + mono_locks_acquire (&image->lock, ImageDataLock);
2064 2064 }
2065 2065
2066 2066 void
2067 2067 mono_image_unlock (MonoImage *image)
2068 2068 {
2069   - LeaveCriticalSection (&image->lock);
  2069 + mono_locks_release (&image->lock, ImageDataLock);
2070 2070 }
2071 2071
2072 2072
5 mono/metadata/loader.c
@@ -36,6 +36,7 @@
36 36 #include <mono/metadata/profiler-private.h>
37 37 #include <mono/metadata/exception.h>
38 38 #include <mono/metadata/marshal.h>
  39 +#include <mono/metadata/lock-tracer.h>
39 40 #include <mono/utils/mono-logger.h>
40 41 #include <mono/utils/mono-dl.h>
41 42 #include <mono/utils/mono-membar.h>
@@ -1948,13 +1949,13 @@ mono_method_get_last_managed (void)
1948 1949 void
1949 1950 mono_loader_lock (void)
1950 1951 {
1951   - EnterCriticalSection (&loader_mutex);
  1952 + mono_locks_acquire (&loader_mutex, LoaderLock);
1952 1953 }
1953 1954
1954 1955 void
1955 1956 mono_loader_unlock (void)
1956 1957 {
1957   - LeaveCriticalSection (&loader_mutex);
  1958 + mono_locks_release (&loader_mutex, LoaderLock);
1958 1959 }
1959 1960
1960 1961 /**
120 mono/metadata/lock-tracer.c
... ... @@ -0,0 +1,120 @@
  1 +/*
  2 + * lock-tracer.c: Runtime simple lock tracer
  3 + *
  4 + * Authors:
  5 + * Rodrigo Kumpera (rkumpera@novell.com)
  6 + *
  7 + */
  8 +
  9 +#include <config.h>
  10 +#include <stdio.h>
  11 +#include <string.h>
  12 +
  13 +#include <sys/types.h>
  14 +#include <unistd.h>
  15 +
  16 +#ifdef HAVE_EXECINFO_H
  17 +#include <execinfo.h>
  18 +#endif
  19 +
  20 +#include <mono/io-layer/io-layer.h>
  21 +
  22 +#include "lock-tracer.h"
  23 +
  24 +/*
  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.
  27 + *
  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.
  33 + *
  34 + * TODO:
  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.
  40 + *
  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.
  44 + */
  45 +
  46 +#ifdef LOCK_TRACER
  47 +
  48 +static FILE *trace_file;
  49 +static CRITICAL_SECTION tracer_lock;
  50 +
  51 +typedef enum {
  52 + RECORD_MUST_NOT_HOLD_ANY,
  53 + RECORD_MUST_NOT_HOLD_ONE,
  54 + RECORD_MUST_HOLD_ONE,
  55 + RECORD_LOCK_ACQUIRED,
  56 + RECORD_LOCK_RELEASED
  57 +} RecordType;
  58 +
  59 +void
  60 +mono_locks_tracer_init (void)
  61 +{
  62 + char *name;
  63 + InitializeCriticalSection (&tracer_lock);
  64 + if (!getenv ("MONO_ENABLE_LOCK_TRACER"))
  65 + return;
  66 + name = g_strdup_printf ("locks.%d", getpid ());
  67 + trace_file = fopen (name, "w+");
  68 + g_free (name);
  69 +}
  70 +
  71 +
  72 +#ifdef HAVE_EXECINFO_H
  73 +
  74 +static int
  75 +mono_backtrace (gpointer array[], int traces)
  76 +{
  77 + return backtrace (array, traces);
  78 +}
  79 +
  80 +#else
  81 +
  82 +static int
  83 +mono_backtrace (gpointer array[], int traces)
  84 +{
  85 + return 0;
  86 +}
  87 +
  88 +#endif
  89 +
  90 +static void
  91 +add_record (RecordType record_kind, RuntimeLocks kind, gpointer lock)
  92 +{
  93 + gpointer frames[10];
  94 + char *msg;
  95 + if (!trace_file)
  96 + return;
  97 +
  98 + memset (frames, 0, sizeof (gpointer));
  99 + mono_backtrace (frames, 6);
  100 +
  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);
  104 + fflush (trace_file);
  105 + g_free (msg);
  106 +}
  107 +
  108 +void
  109 +mono_locks_lock_acquired (RuntimeLocks kind, gpointer lock)
  110 +{
  111 + add_record (RECORD_LOCK_ACQUIRED, kind, lock);
  112 +}
  113 +
  114 +void
  115 +mono_locks_lock_released (RuntimeLocks kind, gpointer lock)
  116 +{
  117 + add_record (RECORD_LOCK_RELEASED, kind, lock);
  118 +}
  119 +
  120 +#endif
48 mono/metadata/lock-tracer.h
... ... @@ -0,0 +1,48 @@
  1 +#ifndef __MONO_METADATA_LOCK_TRACER_H__
  2 +#define __MONO_METADATA_LOCK_TRACER_H__
  3 +
  4 +/*This is a private header*/
  5 +#include <glib.h>
  6 +
  7 +#include "mono/utils/mono-compiler.h"
  8 +
  9 +G_BEGIN_DECLS
  10 +
  11 +typedef enum {
  12 + InvalidLock = 0,
  13 + LoaderLock,
  14 + ImageDataLock,
  15 + DomainLock,
  16 + DomainAssembliesLock,
  17 + DomainJitCodeHashLock,
  18 +} RuntimeLocks;
  19 +
  20 +#ifdef LOCK_TRACER
  21 +
  22 +void mono_locks_tracer_init (void) MONO_INTERNAL;
  23 +
  24 +void mono_locks_lock_acquired (RuntimeLocks kind, gpointer lock) MONO_INTERNAL;
  25 +void mono_locks_lock_released (RuntimeLocks kind, gpointer lock) MONO_INTERNAL;
  26 +
  27 +#else
  28 +
  29 +#define mono_locks_tracer_init() do {} while (0)
  30 +
  31 +#define mono_locks_lock_acquired(__UNUSED0, __UNUSED1) do {} while (0)
  32 +#define mono_locks_lock_released(__UNUSED0, __UNUSED1) do {} while (0)
  33 +
  34 +#endif
  35 +
  36 +#define mono_locks_acquire(LOCK, NAME) do { \
  37 + EnterCriticalSection (LOCK); \
  38 + mono_locks_lock_acquired (NAME, LOCK); \
  39 +} while (0)
  40 +
  41 +#define mono_locks_release(LOCK, NAME) do { \
  42 + mono_locks_lock_released (NAME, LOCK); \
  43 + LeaveCriticalSection (LOCK); \
  44 +} while (0)
  45 +
  46 +G_END_DECLS
  47 +
  48 +#endif /* __MONO_METADATA_LOCK_TRACER_H__ */

0 comments on commit 34feb34

Please sign in to comment.
Something went wrong with that request. Please try again.