]> granicus.if.org Git - gc/commitdiff
Standalone profiling callback for threads suspend/resume
authorIvan Maidanski <ivmai@mail.ru>
Tue, 23 Jun 2015 11:39:29 +0000 (14:39 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 23 Jun 2015 11:39:29 +0000 (14:39 +0300)
* 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).

alloc.c
darwin_stop_world.c
include/gc.h
include/private/gc_priv.h
misc.c
pthread_stop_world.c
win32_threads.c

diff --git a/alloc.c b/alloc.c
index ed9cc4de71639d13334644687b07b6b68b0d7354..b22fd7dd05497a7f847c2676d04f78b347f4d3c1 100644 (file)
--- 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
index 1b6d0072df1518089faa3c7246dab95b2ce9092b..718e2f5cbe92461e38599dce951984aa824f5f68 100644 (file)
@@ -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     */
index 5ef479af12f79268bc3cc1b214c6fad6ed15caaf..80f8e63a4d376850ab34abeb4d4ff31a110166b8 100644 (file)
@@ -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  */
index eafe3e1be15e47ea33b12795a6f031e4feaf0638..223a27414a407f61bd4dc14f3b6d5e3f354f12bb 100644 (file)
@@ -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 93e8665cc12feda22785d1ec2bdc40a39fa70310..e67a76f17050bb6774d5c6c307515e942510ad51 100644 (file)
--- 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). */
index 873b575fbefbc3644b40139e3a44e757d11c76ff..9d046b4f89b59a17e7a69fb3de1790979756dadf 100644 (file)
@@ -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
 }
index 0da2d3150dc69d5acec75c6e7439f4c7eb486968..24d07f32899b6bf605dffa6607ef1b215e02c3be 100644 (file)
@@ -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));
         }
       }
     }