Example #1
0
/* \see http://www.malcolmmclean.site11.com/www/MpiTutorial/MPIStatus.html */
int thorium_mpi1_pt2pt_transport_receive(struct thorium_transport *self, struct thorium_message *message)
{
    struct thorium_mpi1_pt2pt_transport *concrete_self;
    char *buffer;
    int count;
    int source;
    int destination;
    int tag;
    int flag;
    MPI_Status status;
    int result;

    concrete_self = thorium_transport_get_concrete_transport(self);
    source = MPI_ANY_SOURCE;
    tag = DUMMY_TAG;

    /* get return value */
    result = MPI_Iprobe(source, tag, concrete_self->comm, &flag, &status);

    if (result != MPI_SUCCESS) {
        return 0;
    }

    if (!flag) {
        return 0;
    }

    /* get return value */
    result = MPI_Get_count(&status, concrete_self->datatype, &count);

    if (result != MPI_SUCCESS) {
        return 0;
    }

    /* actually allocate (slab allocator) a buffer with count bytes ! */
    buffer = core_memory_pool_allocate(self->inbound_message_memory_pool,
                    count * sizeof(char));

    source = status.MPI_SOURCE;

    /* get return value */
    result = MPI_Recv(buffer, count, concrete_self->datatype, source, tag,
                    concrete_self->comm, &status);

    if (result != MPI_SUCCESS) {
        return 0;
    }

    destination = self->rank;

    /*
     * Prepare the message. The worker will be -1 to tell the thorium
     * code that this is not a worker buffer.
     */
    thorium_message_init_with_nodes(message, count, buffer, source, destination);

    return 1;
}
Example #2
0
/*
 * Returns 1 if the message was demultiplexed.
 *
 * This is O(1) in regard to the number of thorium nodes.
 */
int thorium_message_multiplexer_demultiplex(struct thorium_message_multiplexer *self,
                struct thorium_message *message)
{
    /*
     * Algorithm:
     *
     * get tag.
     * if tag is ACTION_MULTIPLEXER_MESSAGE
     *     for every enclosed message
     *         call thorium_node_prepare_received_message
     *         call thorium_node_dispatch_message()
     *     return 1
     *
     * return 0
     */

    int count;
    char *buffer;
    struct thorium_message new_message;
    int new_count;
    void *new_buffer;
    int position;
    struct core_memory_pool *pool;
    int messages;
    int tag;
    int source_node;
    int destination_node;
    int current_node;
    int routing_destination;

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

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

    tag = thorium_message_action(message);

    if (tag != ACTION_MULTIPLEXER_MESSAGE) {
        return 0;
    }

    /*
    thorium_printf("MULTIPLEXER demultiplex\n");
    */

    messages = 0;
    tracepoint(thorium_node, demultiplex_enter, self->node->name,
                    self->node->tick, messages);

    source_node = thorium_message_source_node(message);
    destination_node = thorium_message_destination_node(message);

    /*
     * Remove the metadata from the count.
     */
    thorium_message_remove_metadata_from_count(message);

    count = thorium_message_count(message);

    buffer = thorium_message_buffer(message);

    pool = thorium_worker_get_outbound_message_memory_pool(self->worker);

    position = 0;

    /*
     * Inject a message for each enclosed message.
     */
    while (position < count) {
        core_memory_copy(&new_count, buffer + position, sizeof(new_count));
        position += sizeof(new_count);

        new_buffer = core_memory_pool_allocate(pool, new_count);
        core_memory_copy(new_buffer, buffer + position, new_count);

        thorium_message_init_with_nodes(&new_message, new_count, new_buffer,
                        source_node, destination_node);

        thorium_node_prepare_received_message(self->node, &new_message);

        /*
         * For these demultiplexed messages, there are 2 outcomes:
         *
         * 1) the message must be delivered locally;
         * 2) the message must be forward because this is a middle node in
         *    the route.
         */
        /*
        thorium_printf("demultiplex: \n");
        thorium_message_print(&new_message);
        thorium_printf("\n");
*/
        /*
         * Mark the message for recycling.
         */
        thorium_message_set_worker(&new_message, thorium_worker_name(self->worker));

#ifdef CORE_DEBUGGER_ASSERT_ENABLED
        if (thorium_message_action(&new_message) == ACTION_INVALID) {
            thorium_printf("Error invalid action DEMUL Multiplexer position %d count %d new_count %d\n",
                            position, count, new_count);
            thorium_message_print(&new_message);
        }
#endif

        CORE_DEBUGGER_ASSERT(thorium_message_action(&new_message) != ACTION_INVALID);

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

        /*
        thorium_printf("demultiplex, local delivery: \n");
        thorium_message_print(&new_message);
        */

        current_node = self->node->name;
        routing_destination = new_message.routing_destination;

        CORE_DEBUGGER_ASSERT(routing_destination >= 0);

        /*
         * This is a local delivery, nothing to see here.
         */
        if (routing_destination == current_node) {

            thorium_worker_send_local_delivery(self->worker, &new_message);

        /*
         * Otherwise, get the next node in the route and send the
         * payload there since we can not do anything with it here.
         */
        } else {

            /*
             * Export the message to another node.
             * To do this, use an exporter worker.
             */
            thorium_worker_send_for_multiplexer(self->worker,
                            &new_message);
        }

        /*
        thorium_message_destroy(&new_message);
        */

        position += new_count;
        ++messages;
    }

    CORE_DEBUGGER_ASSERT(messages > 0);

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("thorium_message_multiplexer_demultiplex %d messages\n",
                    messages);
#endif

    tracepoint(thorium_node, demultiplex_exit, self->node->name,
                    self->node->tick, messages);

    return 1;
}