Ejemplo n.º 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);
}
Ejemplo n.º 2
0
/*
 * Returns 1 if the message was multiplexed.
 *
 * This is O(1) in regard to the number of thorium nodes.
 */
int thorium_message_multiplexer_multiplex(struct thorium_message_multiplexer *self,
                struct thorium_message *message)
{
    /*
     * If buffer is full, use thorium_node_send_with_transport
     *
     * get count
     *
     * if count is below or equal to the threshold
     *      multiplex the message.
     *      return 1
     *
     * return 0
     */

    int count;
    int current_size;
    int maximum_size;
    int action;
    struct core_memory_pool *pool;
    void *new_buffer;
    int new_count;
    void *buffer;
    int destination_node;
    int destination_actor;
    int new_size;
    int required_size;
    struct thorium_multiplexed_buffer *real_multiplexed_buffer;
    uint64_t time;
    int next_node_in_route;
    int source_node;
    int current_node;

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("multiplex\n");
    thorium_message_print(message);
#endif

    if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) {
        return 0;
    }

    action = thorium_message_action(message);

    CORE_DEBUGGER_ASSERT(action != ACTION_INVALID);

#ifdef THORIUM_MULTIPLEXER_USE_ACTIONS_TO_SKIP
    /*
     * Don't multiplex already-multiplexed messages.
     */
    if (thorium_multiplexer_policy_is_action_to_skip(self->policy, action)) {
        return 0;
    }
#endif

#ifdef CONFIG_MULTIPLEXER_USE_DECISION_MAKER
    thorium_message_multiplexer_update_timeout(self);
#endif

    ++self->original_message_count;

    count = thorium_message_count(message);

    destination_node = thorium_message_destination_node(message);

    source_node = message->routing_source;
    current_node = self->node->name;
    next_node_in_route = thorium_router_get_next_rank_in_route(&self->router,
                    source_node, current_node, destination_node);

    /*
    thorium_message_print(message);
    thorium_printf("router: source_node %d current_node %d next_node_in_route %d"
                    " destination_node %d\n",
                    source_node, current_node,
                    next_node_in_route, destination_node);
                    */

#ifdef CONFIG_USE_TOPOLOGY_AWARE_AGGREGATION
    /*
     * The next node in the route for this message is
     * next_node_in_route.
     */
    destination_node = next_node_in_route;
#endif

    CORE_DEBUGGER_ASSERT(source_node >= 0);

    real_multiplexed_buffer = core_vector_at(&self->buffers, destination_node);

    CORE_DEBUGGER_ASSERT(real_multiplexed_buffer != NULL);

    required_size = thorium_multiplexed_buffer_required_size(real_multiplexed_buffer, count);

    buffer = thorium_message_buffer(message);
    destination_actor = thorium_message_destination(message);

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("DEBUG multiplex count %d required_size %d action %x\n",
                    count, required_size, action);
#endif

    /*
     * Don't multiplex non-actor messages.
     */
    if (destination_actor == THORIUM_ACTOR_NOBODY) {
        return 0;
    }

#ifdef CORE_DEBUGGER_ASSERT
    if (real_multiplexed_buffer == NULL) {
        thorium_printf("Error action %d destination_node %d destination_actor %d\n", action, destination_node,
                        destination_actor);
    }
#endif

    current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer);
    maximum_size = thorium_multiplexed_buffer_maximum_size(real_multiplexed_buffer);

    /*
     * Don't multiplex large messages.
     */
    if (required_size > maximum_size) {

#ifdef DEBUG_MULTIPLEXER
        thorium_printf("too large required_size %d maximum_size %d\n", required_size, maximum_size);
#endif
        return 0;
    }

    /*
    thorium_printf("MULTIPLEX_MESSAGE\n");
    */

    new_size = current_size + required_size;

    /*
     * Flush now if there is no space left for the <required_size> bytes
     */
    if (new_size > maximum_size) {

#ifdef DEBUG_MULTIPLEXER
        thorium_printf("thorium_message_multiplexer: must FLUSH thorium_message_multiplexer_multiplex required_size %d new_size %d maximum_size %d\n",
                    required_size, new_size, maximum_size);
#endif

        thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE);
        current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer);

        CORE_DEBUGGER_ASSERT(current_size == 0);
    }

    time = core_timer_get_nanoseconds(&self->timer);

    /*
     * If the buffer is empty before adding the data, it means that it is not
     * in the list of buffers with content and it must be added.
     */
    if (current_size == 0) {

        thorium_multiplexed_buffer_set_time(real_multiplexed_buffer, time);

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
        core_set_add(&self->buffers_with_content, &destination_node);
#endif

        /*
         * Add it to the timeline.
         */

#ifdef THORIUM_MULTIPLEXER_USE_TREE
        core_red_black_tree_add_key_and_value(&self->timeline, &time, &destination_node);

#elif defined(THORIUM_MULTIPLEXER_USE_HEAP)
        core_binary_heap_insert(&self->timeline, &time, &destination_node);
#elif defined(THORIUM_MULTIPLEXER_USE_QUEUE)
        core_queue_enqueue(&self->timeline, &destination_node);
#endif

    }

    /*
     * The allocation of buffer is lazy.
     * The current worker is an exporter of small message for the destination
     * "destination_node".
     */
    if (thorium_multiplexed_buffer_buffer(real_multiplexed_buffer) == NULL) {
        pool = thorium_worker_get_outbound_message_memory_pool(self->worker);

        new_count = self->buffer_size_in_bytes + THORIUM_MESSAGE_METADATA_SIZE;
        new_buffer = core_memory_pool_allocate(pool, new_count);

        thorium_multiplexed_buffer_set_buffer(real_multiplexed_buffer, new_buffer);
    }

    /*
    thorium_printf("DEBUG worker_latency %d ns\n",
                    thorium_worker_latency(self->worker));
                    */

    thorium_multiplexed_buffer_append(real_multiplexed_buffer, count, buffer, time);

    /*
     * Try to flush. This only flushes something if the buffer is full.
     */

    if (thorium_message_multiplexer_buffer_is_ready(self, real_multiplexed_buffer)) {

        /*
         * Try to flush here too. This is required in order to satisfy the
         * technical requirement of a DOA limit.
         *
         * Obviously, don't flush if there is some outbound traffic congestion.
         * Otherwise, there will be too many messages on the network.
         */
        if (!thorium_worker_has_outbound_traffic_congestion(self->worker)) {
            thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE);
        }
    }

    /*
     * Verify invariant.
     */
    CORE_DEBUGGER_ASSERT(thorium_multiplexed_buffer_current_size(real_multiplexed_buffer)<= maximum_size);

    /*
     * Inject the buffer into the worker too.
     */
    return 1;
}