in rts/Capability.c [334:400]
void initCapabilities (void)
{
uint32_t i;
/* Declare a couple capability sets representing the process and
clock domain. Each capability will get added to these capsets. */
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("available NUMA node set is empty");
}
}
#if defined(THREADED_RTS)
#if !defined(REG_Base)
// We can't support multiple CPUs if BaseReg is not a register
if (RtsFlags.ParFlags.nCapabilities > 1) {
errorBelch("warning: multiple CPUs not supported in this build, reverting to 1");
RtsFlags.ParFlags.nCapabilities = 1;
}
#endif
n_capabilities = 0;
moreCapabilities(0, RtsFlags.ParFlags.nCapabilities);
n_capabilities = RtsFlags.ParFlags.nCapabilities;
#else /* !THREADED_RTS */
n_capabilities = 1;
capabilities = stgMallocBytes(sizeof(Capability*), "initCapabilities");
capabilities[0] = &MainCapability;
initCapability(&MainCapability, 0);
#endif
enabled_capabilities = n_capabilities;
// 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 < n_numa_nodes; i++) {
last_free_capability[i] = capabilities[0];
}
}