Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Meijer <lucas@unity3d.com>2014-07-01 15:07:15 +0400
committerLucas Meijer <lucas@unity3d.com>2014-07-01 15:09:50 +0400
commitfd4903870d93f44ffae042e10b5ec6975a2fe7b4 (patch)
treec1dbf6b6bb814b2b5742d1784355c7e2c1faaa6f
parent6c5a455c722172f0defcfb77aa28b2709a191e7c (diff)
Implement event callbacks to be used to profile the collectorprofiling-callbacks
-rw-r--r--alloc.c40
-rw-r--r--darwin_stop_world.c6
-rw-r--r--include/gc.h22
-rw-r--r--misc.c21
-rw-r--r--pthread_stop_world.c23
-rw-r--r--win32_threads.c10
6 files changed, 114 insertions, 8 deletions
diff --git a/alloc.c b/alloc.c
index 25bb31ea..8bc68a22 100644
--- a/alloc.c
+++ b/alloc.c
@@ -88,6 +88,8 @@ STATIC GC_bool GC_need_full_gc = FALSE;
STATIC word GC_used_heap_size_after_full = 0;
+extern GC_on_collection_event_proc GC_on_collection_event;
+
/* GC_copyright symbol is externally visible. */
char * const GC_copyright[] =
{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
@@ -429,6 +431,9 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func)
}
}
GC_notify_full_gc();
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_COLLECTION_BEGIN, NULL);
+
# ifndef SMALL_CONFIG
if (GC_print_stats) {
GET_TIME(start_time);
@@ -581,6 +586,17 @@ GC_API int GC_CALL GC_collect_a_little(void)
# define COMMA_IF_USE_MUNMAP(x) /* empty */
#endif
+static void start_world()
+{
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_STARTWORLD_BEGIN, NULL);
+
+ START_WORLD();
+
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_STARTWORLD_END, NULL);
+}
+
/*
* Assumes lock is held. We stop the world and mark from all roots.
* If stop_func() ever returns TRUE, we may fail and return FALSE.
@@ -606,7 +622,14 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
GET_TIME(start_time);
# endif
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_STOPWORLD_BEGIN, NULL);
+
STOP_WORLD();
+
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_STOPWORLD_END, NULL);
+
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = TRUE;
# endif
@@ -625,6 +648,9 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
GC_clear_a_few_frames();
GC_noop6(0,0,0,0,0,0);
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_MARK_BEGIN, NULL);
+
GC_initiate_gc();
for (i = 0;;i++) {
if ((*stop_func)()) {
@@ -634,12 +660,19 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = FALSE;
# endif
- START_WORLD();
+
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_MARK_END, NULL);
+
+ start_world();
return(FALSE);
}
if (GC_mark_some(GC_approx_sp())) break;
}
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_MARK_END, NULL);
+
GC_gc_no++;
GC_DBGLOG_PRINTF("GC #%lu freed %ld bytes, heap %lu KiB"
IF_USE_MUNMAP(" (+ %lu KiB unmapped)") "\n",
@@ -655,7 +688,7 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = FALSE;
# endif
- START_WORLD();
+ start_world();
# ifndef SMALL_CONFIG
if (GC_PRINT_STATS_FLAG) {
unsigned long time_diff;
@@ -961,6 +994,9 @@ STATIC void GC_finish_collection(void)
MS_TIME_DIFF(done_time,finalize_time));
}
# endif
+
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_COLLECTION_END, NULL);
}
/* If stop_func == 0 then GC_default_stop_func is used instead. */
diff --git a/darwin_stop_world.c b/darwin_stop_world.c
index a6b0a5c7..35a4ba7d 100644
--- a/darwin_stop_world.c
+++ b/darwin_stop_world.c
@@ -458,6 +458,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count,
#endif /* !GC_NO_THREADS_DISCOVERY */
+extern GC_on_collection_event_proc GC_on_collection_event;
+
/* Caller holds allocation lock. */
GC_INNER void GC_stop_world(void)
{
@@ -540,6 +542,8 @@ 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_UNSUSPENDED, (void *)p->stop_info.mach_thread);
}
}
}
@@ -654,6 +658,8 @@ GC_INNER void GC_start_world(void)
if ((p->flags & FINISHED) == 0 && !p->thread_blocked &&
p->stop_info.mach_thread != my_thread)
GC_thread_resume(p->stop_info.mach_thread);
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)p->stop_info.mach_thread);
}
}
diff --git a/include/gc.h b/include/gc.h
index 52c82a05..a034eb0f 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -129,6 +129,28 @@ GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void);
/* Both the supplied setter and the getter */
/* acquire the GC lock (to avoid data races). */
+typedef enum
+{
+ GC_EVENT_COLLECTION_BEGIN,
+ GC_EVENT_STOPWORLD_BEGIN,
+ GC_EVENT_STOPWORLD_END,
+ GC_EVENT_MARK_BEGIN,
+ GC_EVENT_MARK_END,
+ GC_EVENT_STARTWORLD_BEGIN,
+ GC_EVENT_STARTWORLD_END,
+ GC_EVENT_COLLECTION_END,
+ GC_EVENT_THREAD_SUSPENDED,
+ GC_EVENT_THREAD_UNSUSPENDED
+} GCEventKind;
+
+typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GCEventKind, void*);
+ /* Invoked to indicate progress through the */
+ /* collection process. */
+ /* Called with the world stopped (and the */
+ /* allocation lock held). May be 0. */
+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);
+
GC_API GC_ATTR_DEPRECATED int GC_find_leak;
/* Do not actually garbage collect, but simply */
/* report inaccessible memory that was not */
diff --git a/misc.c b/misc.c
index 68667eef..91a422b2 100644
--- a/misc.c
+++ b/misc.c
@@ -2034,6 +2034,27 @@ GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void)
return fn;
}
+GC_on_collection_event_proc GC_on_collection_event = NULL;
+
+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 a68e9222..9bce8741 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -466,7 +466,7 @@ STATIC int GC_suspend_all(void)
{
int n_live_threads = 0;
int i;
-
+ int thread_id;
# ifndef NACL
GC_thread p;
# ifndef GC_OPENBSD_UTHREADS
@@ -499,13 +499,20 @@ 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);
}
# else
# ifndef PLATFORM_ANDROID
- result = pthread_kill(p -> id, GC_sig_suspend);
+ thread_id = p -> id;
+ result = pthread_kill(thread_id, GC_sig_suspend);
# else
- result = android_thread_kill(p -> kernel_id, GC_sig_suspend);
+ thread_id = p -> kernel_id;
+ result = android_thread_kill(thread_id, GC_sig_suspend);
# endif
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, (void *)threadid);
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
@@ -825,11 +832,15 @@ GC_INNER void GC_start_world(void)
ABORT("pthread_resume_np failed");
# else
# ifndef PLATFORM_ANDROID
- result = pthread_kill(p -> id, GC_sig_thr_restart);
+ thread_id = p -> id;
+ result = pthread_kill(thread_id, GC_sig_thr_restart);
# else
- result = android_thread_kill(p -> kernel_id,
- GC_sig_thr_restart);
+ thread_id = p -> kernel_id;
+ result = android_thread_kill(thread_id, GC_sig_thr_restart);
# endif
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)thread_id);
+
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
diff --git a/win32_threads.c b/win32_threads.c
index df11a5e7..19da9cea 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -1182,6 +1182,8 @@ STATIC void GC_suspend(GC_thread t)
/* TRUE only if GC_stop_world() acquired GC_write_cs. */
#endif
+extern GC_on_collection_event_proc GC_on_collection_event;
+
GC_INNER void GC_stop_world(void)
{
DWORD thread_id = GetCurrentThreadId();
@@ -1227,6 +1229,8 @@ GC_INNER void GC_stop_world(void)
if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
&& t -> id != thread_id) {
GC_suspend((GC_thread)t);
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, (void *)THREAD_HANDLE(t));
}
}
} else
@@ -1240,6 +1244,8 @@ GC_INNER void GC_stop_world(void)
if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
&& !KNOWN_FINISHED(t) && t -> id != thread_id) {
GC_suspend(t);
+ if (GC_on_collection_event)
+ GC_on_collection_event(GC_EVENT_THREAD_SUSPENDED, (void *)THREAD_HANDLE(t));
}
}
}
@@ -1273,6 +1279,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, (void *)THREAD_HANDLE(t));
}
}
} else {
@@ -1287,6 +1295,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, (void *)THREAD_HANDLE(t));
}
}
}