Skip to content

Commit

Permalink
[profiler] Acquire the exclusive buffer lock after the suspend lock.
Browse files Browse the repository at this point in the history
This prevents possible STW deadlocks.
  • Loading branch information
Alex Rønne Petersen committed Aug 30, 2016
1 parent 25edbd4 commit 4f62b5a
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions libgc/include/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ GC_API GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested));
/* pointer to a previously allocated heap */
/* object. */

// Keep somewhat in sync with mono/metadata/profiler.h:enum MonoGCEvent
typedef enum {
GC_EVENT_START,
GC_EVENT_MARK_START,
Expand Down
16 changes: 14 additions & 2 deletions mono/metadata/boehm-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,6 @@ on_gc_notification (GC_EventType event)
switch (e) {
case MONO_GC_EVENT_PRE_STOP_WORLD:
MONO_GC_WORLD_STOP_BEGIN ();
mono_thread_info_suspend_lock ();
break;

case MONO_GC_EVENT_POST_STOP_WORLD:
Expand All @@ -441,7 +440,6 @@ on_gc_notification (GC_EventType event)

case MONO_GC_EVENT_POST_START_WORLD:
MONO_GC_WORLD_RESTART_END (1);
mono_thread_info_suspend_unlock ();
break;

case MONO_GC_EVENT_START:
Expand Down Expand Up @@ -481,7 +479,21 @@ on_gc_notification (GC_EventType event)
}

mono_profiler_gc_event (e, 0);

switch (e) {
case MONO_GC_EVENT_PRE_STOP_WORLD:
mono_thread_info_suspend_lock ();
mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0);
break;
case MONO_GC_EVENT_POST_START_WORLD:
mono_thread_info_suspend_unlock ();
mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0);
break;
default:
break;
}
}


static void
on_gc_heap_resize (size_t new_size)
Expand Down
19 changes: 18 additions & 1 deletion mono/metadata/profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,34 @@ typedef enum {
MONO_PROFILE_FAILED
} MonoProfileResult;

// Keep somewhat in sync with libgc/include/gc.h:enum GC_EventType
typedef enum {
MONO_GC_EVENT_START,
MONO_GC_EVENT_MARK_START,
MONO_GC_EVENT_MARK_END,
MONO_GC_EVENT_RECLAIM_START,
MONO_GC_EVENT_RECLAIM_END,
MONO_GC_EVENT_END,
/*
* This is the actual arrival order of the following events:
*
* MONO_GC_EVENT_PRE_STOP_WORLD
* MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED
* MONO_GC_EVENT_POST_STOP_WORLD
* MONO_GC_EVENT_PRE_START_WORLD
* MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
* MONO_GC_EVENT_POST_START_WORLD
*
* The LOCKED and UNLOCKED events guarantee that, by the time they arrive,
* the GC and suspend locks will both have been acquired and released,
* respectively.
*/
MONO_GC_EVENT_PRE_STOP_WORLD,
MONO_GC_EVENT_POST_STOP_WORLD,
MONO_GC_EVENT_PRE_START_WORLD,
MONO_GC_EVENT_POST_START_WORLD
MONO_GC_EVENT_POST_START_WORLD,
MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED,
MONO_GC_EVENT_POST_START_WORLD_UNLOCKED
} MonoGCEvent;

/* coverage info */
Expand Down
4 changes: 4 additions & 0 deletions mono/metadata/sgen-stw.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ sgen_client_stop_world (int generation)

acquire_gc_locks ();

mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation);

/* We start to scan after locks are taking, this ensures we won't be interrupted. */
sgen_process_togglerefs ();

Expand Down Expand Up @@ -283,6 +285,8 @@ sgen_client_restart_world (int generation, gint64 *stw_time)
*/
release_gc_locks ();

mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation);

*stw_time = usec;
}

Expand Down
2 changes: 2 additions & 0 deletions mono/profiler/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1862,9 +1862,11 @@ gc_event_name (int ev)
case MONO_GC_EVENT_RECLAIM_END: return "reclaim end";
case MONO_GC_EVENT_END: return "end";
case MONO_GC_EVENT_PRE_STOP_WORLD: return "pre stop";
case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED: return "pre stop lock";
case MONO_GC_EVENT_POST_STOP_WORLD: return "post stop";
case MONO_GC_EVENT_PRE_START_WORLD: return "pre start";
case MONO_GC_EVENT_POST_START_WORLD: return "post start";
case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED: return "post start unlock";
default:
return "unknown";
}
Expand Down
4 changes: 2 additions & 2 deletions mono/profiler/proflog.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,7 @@ gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
if (generation == mono_gc_max_generation ())
gc_count++;
break;
case MONO_GC_EVENT_PRE_STOP_WORLD:
case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
/*
* Ensure that no thread can be in the middle of writing to
* a buffer when the world stops...
Expand All @@ -1364,7 +1364,7 @@ gc_event (MonoProfiler *profiler, MonoGCEvent ev, int generation)
case MONO_GC_EVENT_PRE_START_WORLD:
heap_walk (profiler);
break;
case MONO_GC_EVENT_POST_START_WORLD:
case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
/*
* Similarly, we must now make sure that any object moves
* written to the GC thread's buffer are flushed. Otherwise,
Expand Down
3 changes: 2 additions & 1 deletion mono/profiler/proflog.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#define LOG_HEADER_ID 0x4D505A01
#define LOG_VERSION_MAJOR 0
#define LOG_VERSION_MINOR 4
#define LOG_DATA_VERSION 12
#define LOG_DATA_VERSION 13
/*
* Changes in data versions:
* version 2: added offsets in heap walk
Expand All @@ -27,6 +27,7 @@
added TYPE_GC_HANDLE_{CREATED,DESTROYED}_BT
TYPE_JIT events are no longer guaranteed to have code start/size info (can be zero)
* version 12: added MONO_COUNTER_PROFILER
* version 13: added MONO_GC_EVENT_{PRE_STOP_WORLD_LOCKED,POST_START_WORLD_UNLOCKED}
*/

enum {
Expand Down

0 comments on commit 4f62b5a

Please sign in to comment.