void waitForCapability()

in rts/Capability.c [753:821]


void waitForCapability (Capability **pCap, Task *task)
{
#if !defined(THREADED_RTS)

    MainCapability.running_task = task;
    task->cap = &MainCapability;
    *pCap = &MainCapability;

#else
    uint32_t i;
    Capability *cap = *pCap;

    if (cap == NULL) {
        if (task->preferred_capability != -1) {
            cap = capabilities[task->preferred_capability %
                               enabled_capabilities];
        } else {
            // Try last_free_capability first
            cap = last_free_capability[task->node];
            if (cap->running_task) {
                // Otherwise, search for a free capability on this node.
                cap = NULL;
                for (i = task->node; i < enabled_capabilities;
                     i += n_numa_nodes) {
                    // visits all the capabilities on this node, because
                    // cap[i]->node == i % n_numa_nodes
                    if (!capabilities[i]->running_task) {
                        cap = capabilities[i];
                        break;
                    }
                }
                if (cap == NULL) {
                    // Can't find a free one, use last_free_capability.
                    cap = last_free_capability[task->node];
                }
            }
        }

        // record the Capability as the one this Task is now assocated with.
        task->cap = cap;

    } else {
        ASSERT(task->cap == cap);
    }

    debugTrace(DEBUG_sched, "returning; I want capability %d", cap->no);

    ACQUIRE_LOCK(&cap->lock);
    if (!cap->running_task) {
        // It's free; just grab it
        cap->running_task = task;
        RELEASE_LOCK(&cap->lock);
    } else {
        newReturningTask(cap,task);
        RELEASE_LOCK(&cap->lock);
        cap = waitForReturnCapability(task);
    }

#if defined(PROFILING)
    cap->r.rCCCS = CCS_SYSTEM;
#endif

    ASSERT_FULL_CAPABILITY_INVARIANTS(cap, task);

    debugTrace(DEBUG_sched, "resuming capability %d", cap->no);

    *pCap = cap;
#endif
}