Beispiel #1
0
void fiber_manager_schedule(fiber_manager_t* manager, fiber_t* the_fiber)
{
    assert(manager);
    assert(the_fiber);
    assert(the_fiber->state == FIBER_STATE_READY);
    wsd_work_stealing_deque_push_bottom(manager->schedule_from, the_fiber);
}
Beispiel #2
0
static int fiber_load_balance(fiber_manager_t* manager)
{
    size_t i = 2 * (manager->id + 1);
    const size_t end = i + 2 * (fiber_manager_num_threads - 1);
    const size_t mod = 2 * fiber_manager_num_threads;
    size_t local_count = wsd_work_stealing_deque_size(manager->schedule_from);
    for(; i < end; ++i) {
        const size_t index = i % mod;
        wsd_work_stealing_deque_t* const remote_queue = fiber_mananger_thread_queues[index];
        assert(remote_queue != manager->queue_one);
        assert(remote_queue != manager->queue_two);
        if(!remote_queue) {
            continue;
        }
        size_t remote_count = wsd_work_stealing_deque_size(remote_queue);
        while(remote_count > local_count) {
            fiber_t* const stolen = (fiber_t*)wsd_work_stealing_deque_steal(remote_queue);
            if(stolen == WSD_EMPTY || stolen == WSD_ABORT) {
                break;
            }
            assert(stolen->state == FIBER_STATE_READY);
            wsd_work_stealing_deque_push_bottom(manager->schedule_from, stolen);
            --remote_count;
            ++local_count;
        }
    }
    return 1;
}
void fiber_scheduler_load_balance(fiber_scheduler_t* sched)
{
    fiber_scheduler_wsd_t* const scheduler = (fiber_scheduler_wsd_t*)sched;
    size_t max_steal = 50;
    size_t i = 2 * (scheduler->id + 1);
    const size_t end = i + 2 * (fiber_scheduler_num_threads - 1);
    const size_t mod = 2 * fiber_scheduler_num_threads;
    size_t local_count = wsd_work_stealing_deque_size(scheduler->schedule_from);
    for(; i < end; ++i) {
        const size_t index = i % mod;
        wsd_work_stealing_deque_t* const remote_queue = fiber_scheduler_thread_queues[index];
        assert(remote_queue != scheduler->queue_one);
        assert(remote_queue != scheduler->queue_two);
        if(!remote_queue) {
            continue;
        }
        size_t remote_count = wsd_work_stealing_deque_size(remote_queue);
        while(remote_count > local_count && max_steal > 0) {
            fiber_t* const stolen = (fiber_t*)wsd_work_stealing_deque_steal(remote_queue);
            if(stolen == WSD_EMPTY || stolen == WSD_ABORT) {
                ++scheduler->failed_steal_count;
                break;
            }
            wsd_work_stealing_deque_push_bottom(scheduler->schedule_from, stolen);
            --remote_count;
            ++local_count;
            --max_steal;
            ++scheduler->steal_count;
        }
    }
}
Beispiel #4
0
void fiber_manager_do_maintenance()
{
    fiber_manager_t* const manager = fiber_manager_get();
    if(manager->to_schedule) {
        assert(manager->to_schedule->state == FIBER_STATE_READY);
        wsd_work_stealing_deque_push_bottom(manager->store_to, manager->to_schedule);
        manager->to_schedule = NULL;
    }

    if(manager->mpsc_to_push.fifo) {
        mpsc_fifo_push(manager->mpsc_to_push.fifo, manager->mpsc_to_push.node);
        memset(&manager->mpsc_to_push, 0, sizeof(manager->mpsc_to_push));
    }

    if(manager->mutex_to_unlock) {
        fiber_mutex_t* const to_unlock = manager->mutex_to_unlock;
        manager->mutex_to_unlock = NULL;
        fiber_mutex_unlock_internal(to_unlock);
    }
}
fiber_t* fiber_scheduler_next(fiber_scheduler_t* sched)
{
    fiber_scheduler_wsd_t* const scheduler = (fiber_scheduler_wsd_t*)sched;
    assert(scheduler);
    if(wsd_work_stealing_deque_size(scheduler->schedule_from) == 0) {
        wsd_work_stealing_deque_t* const temp = scheduler->schedule_from;
        scheduler->schedule_from = scheduler->store_to;
        scheduler->store_to = temp;
    }

    while(wsd_work_stealing_deque_size(scheduler->schedule_from) > 0) {
        fiber_t* const new_fiber = (fiber_t*)wsd_work_stealing_deque_pop_bottom(scheduler->schedule_from);
        if(new_fiber != WSD_EMPTY && new_fiber != WSD_ABORT) {
            if(new_fiber->state == FIBER_STATE_SAVING_STATE_TO_WAIT) {
                wsd_work_stealing_deque_push_bottom(scheduler->store_to, new_fiber);
            } else {
                return new_fiber;
            }
        }
    }
    return NULL;
}
void fiber_scheduler_schedule(fiber_scheduler_t* scheduler, fiber_t* the_fiber)
{
    assert(scheduler);
    assert(the_fiber);
    wsd_work_stealing_deque_push_bottom(((fiber_scheduler_wsd_t*)scheduler)->schedule_from, the_fiber);
}
Beispiel #7
0
int main(int argc, char* argv[])
{
    wsd_circular_array_t* wsd_a = wsd_circular_array_create(8);
    test_assert(wsd_a);
    test_assert(wsd_circular_array_size(wsd_a) == 256);
    wsd_circular_array_put(wsd_a, 1, (void*)1);
    test_assert((void*)1 == wsd_circular_array_get(wsd_a, 1));
    wsd_circular_array_destroy(wsd_a);

    wsd_work_stealing_deque_t* wsd_d = wsd_work_stealing_deque_create();
    int i;
    for(i = 0; i < 1000; ++i) {
        wsd_work_stealing_deque_push_bottom(wsd_d, (void*)(intptr_t)i);
    }
    for(i = 1000; i > 0; --i) {
        void* item = wsd_work_stealing_deque_pop_bottom(wsd_d);
        test_assert((intptr_t)item == i-1);
    }
    wsd_work_stealing_deque_destroy(wsd_d);

    wsd_d2 = wsd_work_stealing_deque_create();
    pthread_t reader[NUM_THREADS];
    for(i = 1; i < NUM_THREADS; ++i) {
        pthread_create(&reader[i], NULL, &run_func, (void*)(intptr_t)i);
    }

    for(i = 0; i < SHARED_COUNT; ++i) {
        wsd_work_stealing_deque_push_bottom(wsd_d2, (void*)(intptr_t)i);
        if((i & 7) == 0) {
            void* val = wsd_work_stealing_deque_pop_bottom(wsd_d2);
            if(val != WSD_EMPTY && val != WSD_ABORT) {
                __sync_add_and_fetch(&results[0][(intptr_t)val], 1);
                __sync_add_and_fetch(&total, (intptr_t)val);
                ++run_func_count[0];
            }
        }
    }
    void* val = 0;
    do {
        val = wsd_work_stealing_deque_pop_bottom(wsd_d2);
        if(val != WSD_EMPTY && val != WSD_ABORT) {
            __sync_add_and_fetch(&results[0][(intptr_t)val], 1);
            __sync_add_and_fetch(&total, (intptr_t)val);
            ++run_func_count[0];
        }
    } while(val != WSD_EMPTY);

    done = 1;
    for(i = 1; i < NUM_THREADS; ++i) {
        pthread_join(reader[i], NULL);
    }

    uint64_t expected_total = 0;
    for(i = 0; i < SHARED_COUNT; ++i) {
        int sum = 0;
        int j;
        for(j = 0; j < NUM_THREADS; ++j) {
            sum += results[j][i];
        }
        test_assert(sum == 1);
        expected_total += i;
    }
    test_assert(total == expected_total);
    for(i = 0; i < NUM_THREADS; ++i) {
        test_assert(run_func_count[i] > 0);
    }
    return 0;
}