summaryrefslogtreecommitdiff
path: root/rts/Capability.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Capability.c')
-rw-r--r--rts/Capability.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/rts/Capability.c b/rts/Capability.c
index 411e64dc7a..7ca220fbd9 100644
--- a/rts/Capability.c
+++ b/rts/Capability.c
@@ -26,6 +26,7 @@
#include "sm/GC.h" // for gcWorkerThread()
#include "STM.h"
#include "RtsUtils.h"
+#include "sm/OSMem.h"
#if !defined(mingw32_HOST_OS)
#include "rts/IOManager.h" // for setIOManagerControlFd()
@@ -59,6 +60,12 @@ static Capability *last_free_capability[MAX_NUMA_NODES];
*/
PendingSync * volatile pending_sync = 0;
+// Number of logical NUMA nodes
+uint32_t n_numa_nodes;
+
+// Map logical NUMA node to OS node numbers
+uint32_t numa_map[MAX_NUMA_NODES];
+
/* Let foreign code get the current Capability -- assuming there is one!
* This is useful for unsafe foreign calls because they are called with
* the current Capability held, but they are not passed it. For example,
@@ -326,6 +333,31 @@ void initCapabilities (void)
traceCapsetCreate(CAPSET_OSPROCESS_DEFAULT, CapsetTypeOsProcess);
traceCapsetCreate(CAPSET_CLOCKDOMAIN_DEFAULT, CapsetTypeClockdomain);
+ // Initialise NUMA
+ if (!RtsFlags.GcFlags.numa) {
+ n_numa_nodes = 1;
+ for (i = 0; i < MAX_NUMA_NODES; i++) {
+ numa_map[i] = 0;
+ }
+ } else {
+ uint32_t nNodes = osNumaNodes();
+ if (nNodes > MAX_NUMA_NODES) {
+ barf("Too many NUMA nodes (max %d)", MAX_NUMA_NODES);
+ }
+ StgWord mask = RtsFlags.GcFlags.numaMask & osNumaMask();
+ uint32_t logical = 0, physical = 0;
+ for (; physical < MAX_NUMA_NODES; physical++) {
+ if (mask & 1) {
+ numa_map[logical++] = physical;
+ }
+ mask = mask >> 1;
+ }
+ n_numa_nodes = logical;
+ if (logical == 0) {
+ barf("%s: available NUMA node set is empty");
+ }
+ }
+
#if defined(THREADED_RTS)
#ifndef REG_Base
@@ -355,7 +387,7 @@ void initCapabilities (void)
// There are no free capabilities to begin with. We will start
// 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 < RtsFlags.GcFlags.nNumaNodes; i++) {
+ for (i = 0; i < n_numa_nodes; i++) {
last_free_capability[i] = capabilities[0];
}
}
@@ -730,9 +762,9 @@ void waitForCapability (Capability **pCap, Task *task)
// Otherwise, search for a free capability on this node.
cap = NULL;
for (i = task->node; i < enabled_capabilities;
- i += RtsFlags.GcFlags.nNumaNodes) {
+ i += n_numa_nodes) {
// visits all the capabilities on this node, because
- // cap[i]->node == i % RtsFlags.GcFlags.nNumaNodes
+ // cap[i]->node == i % n_numa_nodes
if (!capabilities[i]->running_task) {
cap = capabilities[i];
break;