Beispiel #1
0
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);
}
Beispiel #2
0
/**
 * 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);
}