[MLton-commit] r6439

spoons at mlton.org spoons at mlton.org
Mon Mar 3 07:18:41 PST 2008


Multiprocessor support for the runtime.

Added critical section and other synchronization support for multiple
processors.  These functions are used to protect access to globally
shared state.  For example, since we do not support concurrent garbage
collection, all processors must synchronize before any one begins a
collection.

----------------------------------------------------------------------

U   mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.c
U   mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.h
A   mlton/branches/shared-heap-multicore/runtime/gc/processor.c
A   mlton/branches/shared-heap-multicore/runtime/gc/processor.h
U   mlton/branches/shared-heap-multicore/runtime/gc.c

----------------------------------------------------------------------

Modified: mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.c	2008-03-03 15:15:16 UTC (rev 6438)
+++ mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.c	2008-03-03 15:18:40 UTC (rev 6439)
@@ -17,6 +17,9 @@
   /* used needs to be set because the mutator has changed s->stackTop. */
   getStackCurrent(s)->used = sizeofGCStateCurrentStackUsed (s);
   getThreadCurrent(s)->exnStack = s->exnStack;
+  Proc_beginCriticalSection(s);
+  if (DEBUG)
+    fprintf (stderr, "enter locked\n");
   if (DEBUG) 
     displayGCState (s, stderr);
   beginAtomic (s);
@@ -33,6 +36,10 @@
    */
   assert (invariantForMutator (s, FALSE, TRUE));
   endAtomic (s);
+  s->syncReason = SYNC_NONE;
   if (DEBUG)
     fprintf (stderr, "leave ok\n");
+  Proc_endCriticalSection(s);
+  if (DEBUG)
+    fprintf (stderr, "leave unlocked\n");
 }

Modified: mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.h	2008-03-03 15:15:16 UTC (rev 6438)
+++ mlton/branches/shared-heap-multicore/runtime/gc/enter_leave.h	2008-03-03 15:18:40 UTC (rev 6439)
@@ -11,4 +11,37 @@
 static inline void enter (GC_state s);
 static inline void leave (GC_state s);
 
+#define ENTER0(s) do { enter (s); } while(0)
+#define ENTER1(s, p) do { objptr roots[1]; \
+                          roots[0] = pointerToObjptr (p, s->heap->start); \
+                          s->roots = roots; \
+                          s->rootsLength = 1; \
+                          enter (s); \
+                          p = objptrToPointer (roots[0], s->heap->start); \
+                          s->roots = NULL; \
+                          s->rootsLength = 0; \
+                        } while(0)
+
+#define LEAVE0(s) do { leave (s); } while(0)
+#define LEAVE1(s, p) do { objptr roots[1]; \
+                          roots[0] = pointerToObjptr (p, s->heap->start); \
+                          s->roots = roots; \
+                          s->rootsLength = 1; \
+                          leave (s); \
+                          p = objptrToPointer (roots[0], s->heap->start); \
+                          s->roots = NULL; \
+                          s->rootsLength = 0; \
+                        } while(0)
+#define LEAVE2(s, p1, p2) do { objptr roots[2]; \
+                          roots[0] = pointerToObjptr (p1, s->heap->start); \
+                          roots[1] = pointerToObjptr (p2, s->heap->start); \
+                          s->roots = roots; \
+                          s->rootsLength = 2; \
+                          leave (s); \
+                          p1 = objptrToPointer (roots[0], s->heap->start); \
+                          p2 = objptrToPointer (roots[1], s->heap->start); \
+                          s->roots = NULL; \
+                          s->rootsLength = 0; \
+                        } while(0)
+
 #endif /* (defined (MLTON_GC_INTERNAL_FUNCS)) */

Added: mlton/branches/shared-heap-multicore/runtime/gc/processor.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc/processor.c	2008-03-03 15:15:16 UTC (rev 6438)
+++ mlton/branches/shared-heap-multicore/runtime/gc/processor.c	2008-03-03 15:18:40 UTC (rev 6439)
@@ -0,0 +1,135 @@
+
+#include <pthread.h>
+
+int32_t Proc_processorNumber (GC_state s) {
+  for (int proc = 0; proc < s->numberOfProcs; proc ++) {
+    if (s == &(s->procStates[proc])) {
+      return (int32_t)proc;
+    }
+  }
+
+  /* XXX shouldn't get here */
+  fprintf (stderr, "don't know my own processor number (signals?)\n");
+  exit (1);
+  return 0;
+}
+
+bool Proc_amPrimary (GC_state s) {
+  return Proc_processorNumber (s) == 0;
+}
+
+volatile bool Proc_beginInit = FALSE;
+volatile int32_t Proc_initialized = 0;
+volatile int32_t Proc_criticalCount;
+volatile int32_t Proc_criticalTicket;
+
+void Proc_waitForInitialization (__attribute__ ((unused)) GC_state s) {
+  int32_t unused;
+
+  while (!Proc_beginInit) { }
+
+  unused = __sync_fetch_and_add (&Proc_initialized, 1);
+
+  while (!Proc_isInitialized (s)) { }
+}
+
+void Proc_signalInitialization (GC_state s) {
+
+  Proc_criticalTicket = -1;
+  Proc_criticalCount = 0;
+
+  Proc_initialized = 1;
+  Proc_beginInit = TRUE;
+
+  while (!Proc_isInitialized (s)) { }
+}
+
+bool Proc_isInitialized (GC_state s) {
+  return Proc_initialized == s->numberOfProcs;
+}
+
+struct timeval tv_rt;
+struct timeval tv_sync;
+
+void Proc_beginCriticalSection (GC_state s) {
+  if (Proc_isInitialized (s)) {
+    int32_t myNumber = Proc_processorNumber (s);
+    int32_t p = __sync_add_and_fetch (&Proc_criticalCount, 1);
+  
+    if (p == 1) {
+      /* We are the first thread in this round. */
+      if (needGCTime (s))
+        startWallTiming (&tv_sync);
+      
+      switch (s->syncReason) {
+      case SYNC_NONE:
+        fprintf (stderr, "Got to begin without a reason?\n");
+        exit (1);
+        break;
+      case SYNC_OLD_GEN_ARRAY:
+        s->cumulativeStatistics->syncForOldGenArray++;
+        break;
+      case SYNC_NEW_GEN_ARRAY:
+        s->cumulativeStatistics->syncForNewGenArray++;
+        break;
+      case SYNC_STACK:
+        s->cumulativeStatistics->syncForStack++;
+        break;
+      case SYNC_HEAP:
+        s->cumulativeStatistics->syncForHeap++;
+        break;
+      case SYNC_FORCE:
+        s->cumulativeStatistics->syncMisc++;
+        break;
+      case SYNC_PACK:
+        s->cumulativeStatistics->syncMisc++;
+        break;
+      case SYNC_SAVE_WORLD:
+        s->cumulativeStatistics->syncMisc++;
+        break;
+      default:
+        fprintf (stderr, "Unknown sync reason?\n");
+        exit (1);
+      }
+    }
+
+    if (p == s->numberOfProcs) {
+      /* We are the last to syncronize */
+      if (needGCTime (s)) {
+        stopWallTiming (&tv_sync, &s->cumulativeStatistics->tv_sync);
+        startWallTiming (&tv_rt);
+      }
+      Proc_criticalTicket = 0;
+    }
+
+    while (Proc_criticalTicket != myNumber) {}
+  }
+  else {
+    Proc_criticalCount = 1;
+  }
+}
+
+void Proc_endCriticalSection (__attribute__ ((unused)) GC_state s) {
+  if (Proc_isInitialized (s)) {
+    int32_t p = __sync_add_and_fetch (&Proc_criticalTicket, 1);
+    if (p == s->numberOfProcs) {
+      /* We are the last to finish */
+
+      if (needGCTime (s))
+        stopWallTiming (&tv_rt, &s->cumulativeStatistics->tv_rt);
+
+      Proc_criticalCount = 0;
+      Proc_criticalTicket = -1;
+      __sync_synchronize ();
+    }
+
+    while (Proc_criticalTicket >= 0) {}
+  }
+  else {
+    Proc_criticalCount = 0;
+  }
+}
+
+bool Proc_threadInSection (__attribute__ ((unused)) GC_state s) {
+  return Proc_criticalCount > 0;
+}

Added: mlton/branches/shared-heap-multicore/runtime/gc/processor.h
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc/processor.h	2008-03-03 15:15:16 UTC (rev 6438)
+++ mlton/branches/shared-heap-multicore/runtime/gc/processor.h	2008-03-03 15:18:40 UTC (rev 6439)
@@ -0,0 +1,20 @@
+
+
+#if (defined (MLTON_GC_INTERNAL_FUNCS))
+
+/* Unique number for this thread */
+int32_t Proc_processorNumber (GC_state s);
+/* Is the current processor the primary processor? */
+bool Proc_amPrimary (GC_state s);
+
+/* Used to make sure all threads are properly initialized */
+void Proc_waitForInitialization (GC_state s);
+void Proc_signalInitialization (GC_state s);
+bool Proc_isInitialized (GC_state s);
+
+/* Synchronize all processors */
+void Proc_beginCriticalSection (GC_state s);
+void Proc_endCriticalSection (GC_state s);
+bool Proc_threadInSection (__attribute__ ((unused)) GC_state s);
+
+#endif /* (defined (MLTON_GC_INTERNAL_FUNCS)) */

Modified: mlton/branches/shared-heap-multicore/runtime/gc.c
===================================================================
--- mlton/branches/shared-heap-multicore/runtime/gc.c	2008-03-03 15:15:16 UTC (rev 6438)
+++ mlton/branches/shared-heap-multicore/runtime/gc.c	2008-03-03 15:18:40 UTC (rev 6439)
@@ -32,6 +32,7 @@
 #include "gc/foreach.c"
 #include "gc/forward.c"
 #include "gc/frame.c"
+#include "gc/processor.c"
 #include "gc/garbage-collection.c"
 #include "gc/gc_state.c"
 #include "gc/generational.c"




More information about the MLton-commit mailing list