Beispiel #1
0
void thorium_worker_evict_actor(struct thorium_worker *worker, int actor_name)
{
    struct thorium_actor *actor;
    int name;
    struct core_fast_queue saved_actors;
    int count;
    int value;

    core_set_add(&worker->evicted_actors, &actor_name);
    core_map_delete(&worker->actors, &actor_name);
    core_fast_queue_init(&saved_actors, sizeof(struct thorium_actor *));

    /* evict the actor from the scheduling queue
     */
    while (thorium_scheduler_dequeue(&worker->scheduler, &actor)) {

        name = thorium_actor_name(actor);

        if (name != actor_name) {

            core_fast_queue_enqueue(&saved_actors,
                            &actor);
        }
    }

    while (core_fast_queue_dequeue(&saved_actors, &actor)) {
        thorium_scheduler_enqueue(&worker->scheduler, actor);
    }

    core_fast_queue_destroy(&saved_actors);

    /* Evict the actor from the ring
     */

    count = core_fast_ring_size_from_consumer(&worker->actors_to_schedule);

    while (count-- && core_fast_ring_pop_from_consumer(&worker->actors_to_schedule,
                            &actor)) {

        name = thorium_actor_name(actor);

        if (name != actor_name) {

            /*
             * This can not fail logically.
             */
            value = core_fast_ring_push_from_producer(&worker->actors_to_schedule,
                            &actor);

            CORE_DEBUGGER_ASSERT(value);
        }
    }

    core_map_iterator_destroy(&worker->actor_iterator);
    core_map_iterator_init(&worker->actor_iterator, &worker->actors);
}
Beispiel #2
0
int thorium_worker_dequeue_message(struct thorium_worker *worker, struct thorium_message *message)
{
    int answer;

    answer = core_fast_ring_pop_from_consumer(&worker->outbound_message_queue, message);

    if (answer) {
        thorium_message_set_worker(message, worker->name);
    }

    return answer;
}
Beispiel #3
0
int thorium_worker_dequeue_message_for_triage(struct thorium_worker *worker, struct thorium_message *message)
{
    int value;

    value = core_fast_ring_pop_from_consumer(&worker->clean_message_ring_for_triage, message);

#ifdef CORE_DEBUGGER_ENABLE_ASSERT
    if (value) {
        CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL);
    }
#endif

    return value;
}
Beispiel #4
0
int main(int argc, char **argv)
{
    BEGIN_TESTS();

    struct core_fast_ring ring;
    int capacity = 64;
    int i;
    int value;
    int elements;

    elements = 0;

#if 0
    printf("Required %d\n", capacity);
#endif
    core_fast_ring_init(&ring, capacity, sizeof(int));

    capacity = core_fast_ring_capacity(&ring);

#if 0
    printf("Provided %d\n", capacity);
#endif

    TEST_BOOLEAN_EQUALS(core_fast_ring_is_empty_from_consumer(&ring), 1);

    for (i = 0; i < capacity; i++) {
        TEST_BOOLEAN_EQUALS(core_fast_ring_push_from_producer(&ring, &i), 1);
        elements++;

        TEST_INT_EQUALS(core_fast_ring_size_from_producer(&ring), elements);
        TEST_INT_EQUALS(core_fast_ring_size_from_consumer(&ring), elements);
    }

    TEST_BOOLEAN_EQUALS(core_fast_ring_is_full_from_producer(&ring), 1);

    for (i = 0; i < capacity; i++) {
        TEST_BOOLEAN_EQUALS(core_fast_ring_pop_from_consumer(&ring, &value), 1);
        elements--;
        TEST_INT_EQUALS(value, i);
        TEST_INT_EQUALS(core_fast_ring_size_from_producer(&ring), elements);
        TEST_INT_EQUALS(core_fast_ring_size_from_consumer(&ring), elements);
    }
    core_fast_ring_destroy(&ring);

    {
        struct core_fast_ring ring;
        int capacity = 64;
        struct thorium_message message;
        int action;
        int count;
        void *buffer;
        int inserted;
        int pulled;

        action = 1234;
        count = 0;
        buffer = NULL;

        thorium_message_init(&message, action, count, buffer);

        core_fast_ring_init(&ring, capacity, sizeof(struct thorium_message));
        core_fast_ring_use_multiple_producers(&ring);

        inserted = 0;

        while (core_fast_ring_push_from_producer(&ring, &message)) {
            ++inserted;
        }

        /*
         * 64 + 1 = 65, 128 is the next power of 2 for the mask.
         */
        /*
        TEST_INT_EQUALS(inserted, capacity);
        */

        pulled = 0;

        while (core_fast_ring_pop_from_consumer(&ring, &message)) {
            ++pulled;
        }

        TEST_INT_EQUALS(inserted, pulled);

        core_fast_ring_destroy(&ring);

        thorium_message_destroy(&message);
    }

    END_TESTS();

    return 0;
}
Beispiel #5
0
/* This can only be called from the CONSUMER
 */
int thorium_worker_dequeue_actor(struct thorium_worker *worker, struct thorium_actor **actor)
{
    int value;
    int name;
    struct thorium_actor *other_actor;
    int other_name;
    int operations;
    int status;
    int mailbox_size;

    operations = 4;
    other_actor = NULL;

    /* Move an actor from the ring to the real actor scheduling queue
     */
    while (operations--
                    && core_fast_ring_pop_from_consumer(&worker->actors_to_schedule, &other_actor)) {

#ifdef CORE_DEBUGGER_ENABLE_ASSERT
        if (other_actor == NULL) {
            printf("NULL pointer pulled from ring, operations %d ring size %d\n",
                            operations, core_fast_ring_size_from_consumer(&worker->actors_to_schedule));
        }
#endif

        CORE_DEBUGGER_ASSERT(other_actor != NULL);

        other_name = thorium_actor_name(other_actor);

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
        printf("ring.DEQUEUE %d\n", other_name);
#endif

        if (core_set_find(&worker->evicted_actors, &other_name)) {

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
            printf("ALREADY EVICTED\n");
#endif
            continue;
        }

        if (!core_map_get_value(&worker->actors, &other_name, &status)) {
            /* Add the actor to the list of actors.
             * This does nothing if it is already in the list.
             */

            status = STATUS_IDLE;
            core_map_add_value(&worker->actors, &other_name, &status);

            core_map_iterator_destroy(&worker->actor_iterator);
            core_map_iterator_init(&worker->actor_iterator, &worker->actors);
        }

        /* If the actor is not queued, queue it
         */
        if (status == STATUS_IDLE) {
            status = STATUS_QUEUED;

            core_map_update_value(&worker->actors, &other_name, &status);

            thorium_scheduler_enqueue(&worker->scheduler, other_actor);
        } else {

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
            printf("SCHEDULER %d already scheduled to run, scheduled: %d\n", other_name,
                            (int)core_set_size(&worker->queued_actors));
#endif
        }
    }

    /* Now, dequeue an actor from the real queue.
     * If it has more than 1 message, re-enqueue it
     */
    value = thorium_scheduler_dequeue(&worker->scheduler, actor);

    /* Setting name to nobody;
     * check_production at the end uses the value and the name;
     * if value is false, check_production is not using name anyway.
     */
    name = THORIUM_ACTOR_NOBODY;

    /* an actor is ready to be run and it was dequeued from the scheduling queue.
     */
    if (value) {
        name = thorium_actor_name(*actor);

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
        printf("scheduler.DEQUEUE actor %d, removed from queued actors...\n", name);
#endif

        mailbox_size = thorium_actor_get_mailbox_size(*actor);

        /* The actor has only one message and it is going to
         * be processed now.
         */
        if (mailbox_size == 1) {
#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
            printf("SCHEDULER %d has no message to schedule...\n", name);
#endif
            /* Set the status of the worker to STATUS_IDLE
             *
             * TODO: the ring new tail might not be visible too.
             * That could possibly be a problem...
             */
            status = STATUS_IDLE;
            core_map_update_value(&worker->actors, &name, &status);

        /* The actor still has a lot of messages
         * to process. Keep them coming.
         */
        } else if (mailbox_size >= 2) {

            /* Add the actor to the scheduling queue if it
             * still has messages
             */

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
            printf("Scheduling actor %d again, messages: %d\n",
                        name,
                        thorium_actor_get_mailbox_size(*actor));
#endif

            /* The status is still STATUS_QUEUED
             */
            thorium_scheduler_enqueue(&worker->scheduler, *actor);


        /* The actor is scheduled to run, but the new tail is not
         * yet visible apparently.
         *
         * Solution, push back the actor in the scheduler queue, it can take a few cycles to see cache changes across cores. (MESIF protocol)
         *
         * This is done below.
         */
        } else /* if (mailbox_size == 0) */ {

            status = STATUS_IDLE;
            core_map_update_value(&worker->actors, &name, &status);

            value = 0;
        }

    }

    thorium_worker_check_production(worker, value, name);

    return value;
}
Beispiel #6
0
int thorium_worker_fetch_clean_outbound_buffer(struct thorium_worker *self, void **buffer)
{
    return core_fast_ring_pop_from_consumer(&self->injected_clean_outbound_buffers,
                    buffer);
}