static void InitializeCachePool() { int cpus = CPU_GetCount(); /* Round up to the next power of two. */ if (cpus <= 1) cpus = 1; else if (cpus <= 2) cpus = 2; else if (cpus <= 4) cpus = 4; else if (cpus <= 8) cpus = 8; #ifdef PAL_64BIT else if (cpus > 16) cpus = 32; #endif else cpus = 16; /* Everyone needs to mask off higher bits in case CPU_GetCurrent ever * returns a number higher than it did now, or in case there are more than * 32 CPUs. */ s_cpuMask = cpus - 1; s_masterMask = ((ptrdiff_t)1 << cpus) - 1; PAL_Atexit(ShutdownCachePool); }
/** * Run fn on each CPU in cs, passing the CPU number and the opaque * argument, then join with all threads. If cs is NULL, fn is run on * all affinitized CPU's (all CPU's by default). If results is * non-NULL, it will be pointed to an array of *nResults results. The * caller must free this array. */ void CPU_RunOnSet(int (*fn)(int, void*), void *opaque, CPU_Set_t *cs, int **results, int *nResults) { int r; CPU_Set_t *aff = CPU_GetAffinity(); if (!cs) cs = aff; int count = CPU_GetCount(cs); int cpus = cpuSetMax(cs); struct runOnCPU roc[cpus]; pthread_t threads[cpus]; pthread_barrier_t barrier; r = pthread_barrier_init(&barrier, NULL, count + 1); if (r != 0) { errno = r; epanic("failed to create pthread barrier"); } if (results) *results = malloc(count * sizeof(*results)); if (nResults) *nResults = count; int i = 0; for (int cpu = 0; cpu < cpus; ++cpu) { if (numa_bitmask_isbitset(cs, cpu)) { roc[cpu].fn = fn; roc[cpu].cpu = cpu; roc[cpu].i = i++; roc[cpu].results = results ? *results : NULL; roc[cpu].barrier = &barrier; // Make sure the stack and such are allocated // on this core. CPU_Bind(cpu); r = pthread_create(&threads[cpu], NULL, runOnCPUThread, &roc[cpu]); if (r != 0) { errno = r; epanic("failed to spawn thread on CPU %d", cpu); } } } CPU_SetAffinity(aff); pthread_barrier_wait(&barrier); for (int cpu = 0; cpu < cpus; ++cpu) { if (numa_bitmask_isbitset(cs, cpu)) { r = pthread_join(threads[cpu], NULL); if (r != 0) { errno = r; epanic("failed to join thread on CPU %d", cpu); } } } pthread_barrier_destroy(&barrier); CPU_FreeSet(aff); }