From: Ivan Maidanski Date: Tue, 23 Jun 2015 11:39:29 +0000 (+0300) Subject: Standalone profiling callback for threads suspend/resume X-Git-Tag: gc7_6_0~190 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9aaeaa329b4c6eb28b259b28887f8f779fc28591;p=gc Standalone profiling callback for threads suspend/resume * alloc.c (GC_on_collection_event, GC_set_on_collection_event, GC_get_on_collection_event): Move from misc.c. * alloc.c (GC_on_collection_event): Make STATIC. * include/private/gc_priv.h (GC_on_collection_event): Remove declaration. * include/gc.h (GC_on_collection_event_proc): Remove 2nd argument of the callback. * alloc.c (GC_try_to_collect_inner, GC_stopped_mark): Likewise. * darwin_stop_world.c (GC_suspend_thread_list, GC_stop_world, GC_thread_resume): Use GC_on_thread_event instead of GC_on_collection_event. * pthread_stop_world.c (GC_suspend_all, GC_start_world): Likewise. * win32_threads.c (GC_suspend, GC_start_world): Likewise. * include/gc.h (GC_on_collection_event_proc): Update comment. * include/gc.h (GC_set_on_collection_event, GC_get_on_collection_event): Add comment. * include/gc.h (GC_on_thread_event_proc): New callback type (only if GC_THREADS). * include/gc.h (GC_set_on_thread_event, GC_get_on_thread_event): New API function declaration (only if GC_THREADS). * include/private/gc_priv.h (GC_on_thread_event): New variable declaration (only if THREADS). * misc.c (GC_on_thread_event): New global variable (only if THREADS). * misc.c (GC_set_on_thread_event, GC_get_on_thread_event): New API function (only if THREADS). --- diff --git a/alloc.c b/alloc.c index ed9cc4de..b22fd7dd 100644 --- a/alloc.c +++ b/alloc.c @@ -407,6 +407,26 @@ STATIC void GC_maybe_gc(void) } } +STATIC GC_on_collection_event_proc GC_on_collection_event = 0; + +GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc fn) +{ + /* fn may be 0 (means no event notifier). */ + DCL_LOCK_STATE; + LOCK(); + GC_on_collection_event = fn; + UNLOCK(); +} + +GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void) +{ + GC_on_collection_event_proc fn; + DCL_LOCK_STATE; + LOCK(); + fn = GC_on_collection_event; + UNLOCK(); + return fn; +} /* * Stop the world garbage collection. Assumes lock held. If stop_func is @@ -422,7 +442,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) ASSERT_CANCEL_DISABLED(); if (GC_dont_gc || (*stop_func)()) return FALSE; if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_START, NULL); + GC_on_collection_event(GC_EVENT_START); if (GC_incremental && GC_collection_in_progress()) { GC_COND_LOG_PRINTF( "GC_try_to_collect_inner: finishing collection in progress\n"); @@ -485,7 +505,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) } # endif if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_END, NULL); + GC_on_collection_event(GC_EVENT_END); return(TRUE); } @@ -619,14 +639,14 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_PRE_STOP_WORLD, NULL); + GC_on_collection_event(GC_EVENT_PRE_STOP_WORLD); # endif STOP_WORLD(); # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_POST_STOP_WORLD, NULL); + GC_on_collection_event(GC_EVENT_POST_STOP_WORLD); # endif # ifdef THREAD_LOCAL_ALLOC @@ -644,7 +664,7 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) /* Mark from all roots. */ if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_MARK_START, NULL); + GC_on_collection_event(GC_EVENT_MARK_START); /* Minimize junk left in my registers and on the stack */ GC_clear_a_few_frames(); @@ -662,14 +682,14 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_PRE_START_WORLD, NULL); + GC_on_collection_event(GC_EVENT_PRE_START_WORLD); # endif START_WORLD(); # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_POST_START_WORLD, NULL); + GC_on_collection_event(GC_EVENT_POST_START_WORLD); # endif /* TODO: Notify GC_EVENT_MARK_ABANDON */ @@ -690,7 +710,7 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) (*GC_check_heap)(); } if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_MARK_END, NULL); + GC_on_collection_event(GC_EVENT_MARK_END); # ifdef THREAD_LOCAL_ALLOC GC_world_stopped = FALSE; @@ -698,14 +718,14 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_PRE_START_WORLD, NULL); + GC_on_collection_event(GC_EVENT_PRE_START_WORLD); # endif START_WORLD(); # ifdef THREADS if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_POST_START_WORLD, NULL); + GC_on_collection_event(GC_EVENT_POST_START_WORLD); # endif # ifndef SMALL_CONFIG diff --git a/darwin_stop_world.c b/darwin_stop_world.c index 1b6d0072..718e2f5c 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -495,8 +495,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, } if (!found) GC_mach_threads_count++; - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, (void *)thread); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, (void *)thread); } return changed; } @@ -585,9 +585,9 @@ GC_INNER void GC_stop_world(void) kern_result = thread_suspend(p->stop_info.mach_thread); if (kern_result != KERN_SUCCESS) ABORT("thread_suspend failed"); - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, - (void *)p->stop_info.mach_thread); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)p->stop_info.mach_thread); } } } @@ -628,8 +628,8 @@ GC_INLINE void GC_thread_resume(thread_act_t thread) kern_result = thread_resume(thread); if (kern_result != KERN_SUCCESS) ABORT("thread_resume failed"); - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)thread); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)thread); } /* Caller holds allocation lock, and has held it continuously since */ diff --git a/include/gc.h b/include/gc.h index 5ef479af..80f8e63a 100644 --- a/include/gc.h +++ b/include/gc.h @@ -147,13 +147,29 @@ typedef enum { GC_EVENT_THREAD_UNSUSPENDED } GC_EventType; -typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GC_EventType, void*); +typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GC_EventType); /* Invoked to indicate progress through the */ - /* collection process. */ - /* Called with the world stopped (and the */ - /* allocation lock held). May be 0. */ + /* collection process. Not used for thread */ + /* suspend/resume notifications. Called with */ + /* the GC lock held (or, even, the world */ + /* stopped). May be 0 (means no notifier). */ GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc); GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void); + /* Both the supplied setter and the getter */ + /* acquire the GC lock (to avoid data races). */ + +#ifdef GC_THREADS + typedef void (GC_CALLBACK * GC_on_thread_event_proc)(GC_EventType, + void * /* thread_id */); + /* Invoked when a thread is suspended or */ + /* resumed during collection. Called with the */ + /* GC lock held (and the world stopped */ + /* partially). May be 0 (means no notifier). */ + GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc); + GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void); + /* Both the supplied setter and the getter */ + /* acquire the GC lock (to avoid data races). */ +#endif GC_API GC_ATTR_DEPRECATED int GC_find_leak; /* Do not actually garbage collect, but simply */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index eafe3e1b..223a2741 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -460,6 +460,10 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # endif # endif +#ifdef THREADS + GC_EXTERN GC_on_thread_event_proc GC_on_thread_event; +#endif + /* Abandon ship */ # ifdef PCR # define ABORT(s) PCR_Base_Panic(s) @@ -1949,8 +1953,6 @@ GC_EXTERN void (*GC_print_heap_obj)(ptr_t p); /* Print an address map of the process. */ #endif -GC_EXTERN GC_on_collection_event_proc GC_on_collection_event; - #ifndef SHORT_DBG_HDRS GC_EXTERN GC_bool GC_findleak_delay_free; /* Do not immediately deallocate object on */ diff --git a/misc.c b/misc.c index 93e8665c..e67a76f1 100644 --- a/misc.c +++ b/misc.c @@ -2030,7 +2030,28 @@ GC_API GC_word GC_CALL GC_get_gc_no(void) /* GC_parallel is initialized at start-up. */ return GC_parallel; } -#endif + + GC_INNER GC_on_thread_event_proc GC_on_thread_event = 0; + + GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc fn) + { + /* fn may be 0 (means no event notifier). */ + DCL_LOCK_STATE; + LOCK(); + GC_on_thread_event = fn; + UNLOCK(); + } + + GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void) + { + GC_on_thread_event_proc fn; + DCL_LOCK_STATE; + LOCK(); + fn = GC_on_thread_event; + UNLOCK(); + return fn; + } +#endif /* THREADS */ /* Setter and getter functions for the public R/W function variables. */ /* These functions are synchronized (like GC_set_warn_proc() and */ @@ -2074,27 +2095,6 @@ GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void) return fn; } -GC_INNER GC_on_collection_event_proc GC_on_collection_event = 0; - -GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc fn) -{ - /* fn may be 0 (means no event notifier). */ - DCL_LOCK_STATE; - LOCK(); - GC_on_collection_event = fn; - UNLOCK(); -} - -GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void) -{ - GC_on_collection_event_proc fn; - DCL_LOCK_STATE; - LOCK(); - fn = GC_on_collection_event; - UNLOCK(); - return fn; -} - GC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc fn) { /* fn may be 0 (means no finalizer notifier). */ diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 873b575f..9d046b4f 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -503,10 +503,9 @@ STATIC int GC_suspend_all(void) if (pthread_stackseg_np(p->id, &stack)) ABORT("pthread_stackseg_np failed"); p -> stop_info.stack_ptr = (ptr_t)stack.ss_sp - stack.ss_size; - - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, - (void *)p->id); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)p->id); } # else # ifndef PLATFORM_ANDROID @@ -522,9 +521,9 @@ STATIC int GC_suspend_all(void) n_live_threads--; break; case 0: - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, - (void *)thread_id); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)thread_id); break; default: ABORT_ARG1("pthread_kill failed at suspend", @@ -565,9 +564,8 @@ STATIC int GC_suspend_all(void) num_used++; if (GC_nacl_thread_parked[i] == 1) { num_threads_parked++; - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, - (void *)(word)i); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, (void *)(word)i); } } } @@ -844,9 +842,8 @@ GC_INNER void GC_start_world(void) # ifdef GC_OPENBSD_UTHREADS if (pthread_resume_np(p -> id) != 0) ABORT("pthread_resume_np failed"); - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, - (void *)p->id); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)p->id); # else # ifndef PLATFORM_ANDROID thread_id = p -> id; @@ -861,9 +858,9 @@ GC_INNER void GC_start_world(void) n_live_threads--; break; case 0: - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, - (void *)thread_id); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, + (void *)thread_id); break; default: ABORT_ARG1("pthread_kill failed at resume", @@ -891,8 +888,8 @@ GC_INNER void GC_start_world(void) GC_log_printf("World starting...\n"); # endif GC_nacl_park_threads_now = 0; - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, NULL); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, NULL); /* TODO: Send event for every unsuspended thread. */ # endif } diff --git a/win32_threads.c b/win32_threads.c index 0da2d315..24d07f32 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -1182,8 +1182,8 @@ STATIC void GC_suspend(GC_thread t) # if defined(MPROTECT_VDB) AO_CLEAR(&GC_fault_handler_lock); # endif - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, THREAD_HANDLE(t)); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, THREAD_HANDLE(t)); } #if defined(GC_ASSERTIONS) && !defined(CYGWIN32) @@ -1282,9 +1282,8 @@ GC_INNER void GC_start_world(void) if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1) ABORT("ResumeThread failed"); t -> suspended = FALSE; - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, - THREAD_HANDLE(t)); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t)); } } } else { @@ -1299,9 +1298,8 @@ GC_INNER void GC_start_world(void) ABORT("ResumeThread failed"); UNPROTECT_THREAD(t); t -> suspended = FALSE; - if (GC_on_collection_event) - GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, - THREAD_HANDLE(t)); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t)); } } }