[Git][ghc/ghc][wip/tsan/codegen] 3 commits: getCapability

Ben Gamari (@bgamari) gitlab at gitlab.haskell.org
Wed Nov 16 01:23:34 UTC 2022



Ben Gamari pushed to branch wip/tsan/codegen at Glasgow Haskell Compiler / GHC


Commits:
4d5cbb90 by Ben Gamari at 2022-11-15T17:52:32-05:00
getCapability

- - - - -
723b92f3 by Ben Gamari at 2022-11-15T17:52:33-05:00
rts: Statically allocate capabilities

This is a rather simplistic way of solving #17289.

- - - - -
526e6fb8 by Ben Gamari at 2022-11-15T20:23:26-05:00
Fix it

- - - - -


6 changed files:

- rts/Capability.c
- rts/Capability.h
- rts/IOManager.c
- rts/Schedule.c
- rts/Stats.c
- rts/include/rts/Config.h


Changes:

=====================================
rts/Capability.c
=====================================
@@ -45,7 +45,7 @@ uint32_t enabled_capabilities = 0;
 // Capabilities, because there may be pointers to them in use
 // (e.g. threads in waitForCapability(), see #8209), so this is
 // an array of Capability* rather than an array of Capability.
-Capability **capabilities = NULL;
+Capability *capabilities[MAX_N_CAPABILITIES];
 
 // Holds the Capability which last became free.  This is used so that
 // an in-call has a chance of quickly finding a free Capability.
@@ -388,6 +388,12 @@ void initCapabilities (void)
     }
 #endif
 
+    if (RtsFlags.ParFlags.nCapabilities > MAX_N_CAPABILITIES) {
+        errorBelch("warning: this GHC runtime system only supports up to %d capabilities",
+                   MAX_N_CAPABILITIES);
+        RtsFlags.ParFlags.nCapabilities = MAX_N_CAPABILITIES;
+    }
+
     n_capabilities = 0;
     moreCapabilities(0, RtsFlags.ParFlags.nCapabilities);
     n_capabilities = RtsFlags.ParFlags.nCapabilities;
@@ -395,7 +401,6 @@ void initCapabilities (void)
 #else /* !THREADED_RTS */
 
     n_capabilities = 1;
-    capabilities = stgMallocBytes(sizeof(Capability*), "initCapabilities");
     capabilities[0] = &MainCapability;
 
     initCapability(&MainCapability, 0);
@@ -408,7 +413,7 @@ void initCapabilities (void)
     // a worker Task to each Capability, which will quickly put the
     // Capability on the free list when it finds nothing to do.
     for (i = 0; i < n_numa_nodes; i++) {
-        last_free_capability[i] = capabilities[0];
+        last_free_capability[i] = getCapability(0);
     }
 }
 
@@ -416,8 +421,6 @@ void
 moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
 {
 #if defined(THREADED_RTS)
-    Capability **new_capabilities = stgMallocBytes(to * sizeof(Capability*), "moreCapabilities");
-
     // We must disable the timer while we do this since the tick handler may
     // call contextSwitchAllCapabilities, which may see the capabilities array
     // as we free it. The alternative would be to protect the capabilities
@@ -429,30 +432,22 @@ moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
         // THREADED_RTS must work on builds that don't have a mutable
         // BaseReg (eg. unregisterised), so in this case
         // capabilities[0] must coincide with &MainCapability.
-        new_capabilities[0] = &MainCapability;
+        capabilities[0] = &MainCapability;
         initCapability(&MainCapability, 0);
     }
     else
     {
         for (uint32_t i = 0; i < to; i++) {
-            if (i < from) {
-                new_capabilities[i] = capabilities[i];
-            } else {
-                new_capabilities[i] = stgMallocBytes(sizeof(Capability),
+            if (i >= from) {
+                capabilities[i] = stgMallocBytes(sizeof(Capability),
                                                      "moreCapabilities");
-                initCapability(new_capabilities[i], i);
+                initCapability(capabilities[i], i);
             }
         }
     }
 
     debugTrace(DEBUG_sched, "allocated %d more capabilities", to - from);
 
-    Capability **old_capabilities = ACQUIRE_LOAD(&capabilities);
-    RELEASE_STORE(&capabilities, new_capabilities);
-    if (old_capabilities != NULL) {
-        stgFree(old_capabilities);
-    }
-
     startTimer();
 #endif
 }
@@ -828,8 +823,7 @@ static Capability * find_capability_for_task(const Task * task)
 {
     if (task->preferred_capability != -1) {
         // Does the task have a preferred capability? If so, use it
-        return capabilities[task->preferred_capability %
-                            enabled_capabilities];
+        return getCapability(task->preferred_capability % enabled_capabilities);
     } else {
         // Try last_free_capability first
         Capability *cap = RELAXED_LOAD(&last_free_capability[task->node]);


=====================================
rts/Capability.h
=====================================
@@ -261,11 +261,11 @@ INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED,
 // extern uint32_t enabled_capabilities;
 
 // Array of all the capabilities
-extern Capability **capabilities;
+extern Capability *capabilities[MAX_N_CAPABILITIES];
 
 INLINE_HEADER Capability *getCapability(uint32_t i)
 {
-    return RELAXED_LOAD(&capabilities)[i];
+    return RELAXED_LOAD(&capabilities[i]);
 }
 
 //


=====================================
rts/IOManager.c
=====================================
@@ -140,7 +140,7 @@ void
 setIOManagerControlFd(uint32_t cap_no USED_IF_THREADS, int fd USED_IF_THREADS) {
 #if defined(THREADED_RTS)
     if (cap_no < n_capabilities) {
-        RELAXED_STORE(&capabilities[cap_no]->io_manager_control_wr_fd, fd);
+        RELAXED_STORE(&getCapability(cap_no)->io_manager_control_wr_fd, fd);
     } else {
         errorBelch("warning: setIOManagerControlFd called with illegal capability number.");
     }


=====================================
rts/Schedule.c
=====================================
@@ -1839,7 +1839,7 @@ delete_threads_and_gc:
         tmp_cap = getCapability(i);
         ASSERT(tmp_cap->disabled);
         if (i != cap->no) {
-            dest_cap = capabilities[i % enabled_capabilities];
+            dest_cap = getCapability(i % enabled_capabilities);
             while (!emptyRunQueue(tmp_cap)) {
                 tso = popRunQueue(tmp_cap);
                 migrateThread(tmp_cap, tso, dest_cap);
@@ -2600,9 +2600,9 @@ scheduleThreadOn(Capability *cap, StgWord cpu USED_IF_THREADS, StgTSO *tso)
     if (cpu == cap->no) {
         appendToRunQueue(cap,tso);
     } else {
-        migrateThread(cap, tso, capabilities[cpu]);
+        migrateThread(cap, tso, getCapability(cpu));
     }
-    contextSwitchCapability(capabilities[cpu], false);
+    contextSwitchCapability(getCapability(cpu), false);
 #else
     appendToRunQueue(cap,tso);
     contextSwitchCapability(cap, false);


=====================================
rts/Stats.c
=====================================
@@ -1351,14 +1351,14 @@ stat_exitReport (void)
             sum.bound_task_count = taskCount - workerCount;
 
             for (uint32_t i = 0; i < getNumCapabilities(); i++) {
-                sum.sparks.created   += capabilities[i]->spark_stats.created;
-                sum.sparks.dud       += capabilities[i]->spark_stats.dud;
+                sum.sparks.created   += getCapability(i)->spark_stats.created;
+                sum.sparks.dud       += getCapability(i)->spark_stats.dud;
                 sum.sparks.overflowed+=
-                  capabilities[i]->spark_stats.overflowed;
+                  getCapability(i)->spark_stats.overflowed;
                 sum.sparks.converted +=
-                  capabilities[i]->spark_stats.converted;
-                sum.sparks.gcd       += capabilities[i]->spark_stats.gcd;
-                sum.sparks.fizzled   += capabilities[i]->spark_stats.fizzled;
+                  getCapability(i)->spark_stats.converted;
+                sum.sparks.gcd       += getCapability(i)->spark_stats.gcd;
+                sum.sparks.fizzled   += getCapability(i)->spark_stats.fizzled;
             }
 
             sum.sparks_count = sum.sparks.created
@@ -1650,10 +1650,10 @@ statDescribeGens(void)
 
       mut = 0;
       for (i = 0; i < getNumCapabilities(); i++) {
-          mut += countOccupied(capabilities[i]->mut_lists[g]);
+          mut += countOccupied(getCapability(i)->mut_lists[g]);
 
           // Add the pinned object block.
-          bd = capabilities[i]->pinned_object_block;
+          bd = getCapability(i)->pinned_object_block;
           if (bd != NULL) {
               gen_live   += bd->free - bd->start;
               gen_blocks += bd->blocks;


=====================================
rts/include/rts/Config.h
=====================================
@@ -76,3 +76,9 @@ code.
 #if defined(DEBUG)
 #define PROF_SPIN
 #endif
+
+#if defined(THREADED_RTS)
+#define MAX_N_CAPABILITIES 256
+#else
+#define MAX_N_CAPABILITIES 1
+#endif



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/de0a6eff379bc2c92717aec5e3513296b631305f...526e6fb85f29270337ad5b4d6761347a996bea03

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/de0a6eff379bc2c92717aec5e3513296b631305f...526e6fb85f29270337ad5b4d6761347a996bea03
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20221115/1a441214/attachment-0001.html>


More information about the ghc-commits mailing list