/** * \brief Blocks the current process until a communication is finished. * \param L a Lua state * \return number of values returned to Lua * * - Argument 1 (comm): a comm (previously created by isend or irecv) * - Argument 2 (number, optional): timeout (default is no timeout) * - Return values (task or nil + string): in case of success, returns the task * received if you are the receiver and nil if you are the sender. In case of * failure, returns nil plus an error string. */ static int l_comm_wait(lua_State* L) { msg_comm_t comm = sglua_check_comm(L, 1); double timeout = -1; if (lua_gettop(L) >= 2) { timeout = luaL_checknumber(L, 2); } /* comm ... */ msg_error_t res = MSG_comm_wait(comm, timeout); if (res == MSG_OK) { msg_task_t task = MSG_comm_get_task(comm); if (MSG_task_get_sender(task) == MSG_process_self()) { /* I'm the sender */ return 0; } else { /* I'm the receiver: find the Lua task from the C task */ sglua_task_unregister(L, task); /* comm ... task */ return 1; } } else { /* the communication has failed */ lua_pushnil(L); /* comm ... nil */ lua_pushstring(L, sglua_get_msg_error(res)); /* comm ... nil error */ return 2; } }
msg_error_t peer_wait_for_message(peer_t peer) { msg_error_t status; msg_comm_t comm = NULL; msg_task_t task = NULL; int idx = -1; int done = 0; while (!done) { comm = MSG_task_irecv(&task, peer->me); queue_pending_connection(comm, peer->pending_recvs); if ((idx = MSG_comm_waitany(peer->pending_recvs)) != -1) { comm = xbt_dynar_get_as(peer->pending_recvs, idx, msg_comm_t); status = MSG_comm_get_status(comm); XBT_DEBUG("peer_wait_for_message: error code = %d", status); xbt_assert(status == MSG_OK, "peer_wait_for_message() failed"); task = MSG_comm_get_task(comm); MSG_comm_destroy(comm); xbt_dynar_cursor_rm(peer->pending_recvs, (unsigned int*)&idx); done = peer_execute_task(peer, task); task_message_delete(task); task = NULL; } process_pending_connections(peer->pending_sends); } return status; }
/** Receiver function */ int receiver(int argc, char *argv[]) { int id = -1; int i; char mailbox[80]; xbt_dynar_t comms = xbt_dynar_new(sizeof(msg_comm_t), NULL); int tasks = atof(argv[2]); msg_task_t *task = xbt_new(msg_task_t, tasks); _XBT_GNUC_UNUSED int read; read = sscanf(argv[1], "%d", &id); xbt_assert(read, "Invalid argument %s\n", argv[1]); sprintf(mailbox, "receiver-%d", id); MSG_process_sleep(10); msg_comm_t res_irecv; for (i = 0; i < tasks; i++) { XBT_INFO("Wait to receive task %d", i); task[i] = NULL; res_irecv = MSG_task_irecv(&task[i], mailbox); xbt_dynar_push_as(comms, msg_comm_t, res_irecv); } /* Here we are waiting for the receiving of all communications */ msg_task_t task_com; while (!xbt_dynar_is_empty(comms)) { _XBT_GNUC_UNUSED msg_error_t err; xbt_dynar_remove_at(comms, MSG_comm_waitany(comms), &res_irecv); task_com = MSG_comm_get_task(res_irecv); MSG_comm_destroy(res_irecv); XBT_INFO("Processing \"%s\"", MSG_task_get_name(task_com)); MSG_task_execute(task_com); XBT_INFO("\"%s\" done", MSG_task_get_name(task_com)); err = MSG_task_destroy(task_com); xbt_assert(err == MSG_OK, "MSG_task_destroy failed"); } xbt_dynar_free(&comms); xbt_free(task); /* Here we tell to sender that all tasks are done */ sprintf(mailbox, "finalize"); res_irecv = MSG_task_isend(MSG_task_create(NULL, 0, 0, NULL), mailbox); MSG_comm_wait(res_irecv, -1); MSG_comm_destroy(res_irecv); XBT_INFO("I'm done. See you!"); return 0; } /* end_of_receiver */
static int receiver(int argc, char *argv[]) { xbt_assert(argc==3, "This function expects 2 parameters from the XML deployment file"); int id = xbt_str_parse_int(argv[1], "ID should be numerical, not %s"); int task_amount = xbt_str_parse_int(argv[2], "Invalid amount of tasks: %s"); msg_task_t *tasks = xbt_new(msg_task_t, task_amount); xbt_dynar_t comms = xbt_dynar_new(sizeof(msg_comm_t), NULL); char mailbox[80]; snprintf(mailbox,79, "receiver-%d", id); MSG_process_sleep(10); for (int i = 0; i < task_amount; i++) { XBT_INFO("Wait to receive task %d", i); tasks[i] = NULL; msg_comm_t comm = MSG_task_irecv(&tasks[i], mailbox); xbt_dynar_push_as(comms, msg_comm_t, comm); } /* Here we are waiting for the receiving of all communications */ while (!xbt_dynar_is_empty(comms)) { msg_comm_t comm; // MSG_comm_waitany returns the rank of the comm that just ended. Remove it. xbt_dynar_remove_at(comms, MSG_comm_waitany(comms), &comm); msg_task_t task = MSG_comm_get_task(comm); MSG_comm_destroy(comm); XBT_INFO("Processing \"%s\"", MSG_task_get_name(task)); MSG_task_execute(task); XBT_INFO("\"%s\" done", MSG_task_get_name(task)); msg_error_t err = MSG_task_destroy(task); xbt_assert(err == MSG_OK, "MSG_task_destroy failed"); } xbt_dynar_free(&comms); xbt_free(tasks); /* Here we tell to sender that all tasks are done */ MSG_task_send(MSG_task_create(NULL, 0, 0, NULL), "finalize"); XBT_INFO("I'm done. See you!"); return 0; }
/** * @brief Returns whether a communication is finished. * * Unlike wait(), This function always returns immediately. * * - Argument 1 (comm): a comm (previously created by isend or irecv) * - Return values (task/boolean or nil + string): if the communication is not * finished, return false. If the communication is finished and was successful, * returns the task received if you are the receiver or true if you are the * sender. If the communication is finished and has failed, returns nil * plus an error string. */ static int l_comm_test(lua_State* L) { msg_comm_t comm = sglua_check_comm(L, 1); /* comm ... */ if (!MSG_comm_test(comm)) { /* not finished yet */ lua_pushboolean(L, 0); /* comm ... false */ return 1; } else { /* finished but may have failed */ msg_error_t res = MSG_comm_get_status(comm); if (res == MSG_OK) { msg_task_t task = MSG_comm_get_task(comm); if (MSG_task_get_sender(task) == MSG_process_self()) { /* I'm the sender */ lua_pushboolean(L, 1); /* comm ... true */ return 1; } else { /* I'm the receiver: find the Lua task from the C task*/ sglua_task_unregister(L, task); /* comm ... task */ return 1; } } else { /* the communication has failed */ lua_pushnil(L); /* comm ... nil */ lua_pushstring(L, sglua_get_msg_error(res)); /* comm ... nil error */ return 2; } } }
void jcomm_bind_task(JNIEnv *env, jobject jcomm) { msg_comm_t comm = (msg_comm_t) (uintptr_t) env->GetLongField(jcomm, jcomm_field_Comm_bind); //test if we are receiving or sending a task. jboolean jreceiving = env->GetBooleanField(jcomm, jcomm_field_Comm_receiving); if (jreceiving == JNI_TRUE) { //bind the task object. msg_task_t task = MSG_comm_get_task(comm); xbt_assert(task != nullptr, "Task is nullptr"); jobject jtask_global = static_cast<jobject>(MSG_task_get_data(task)); //case where the data has already been retrieved if (jtask_global == nullptr) { return; } //Make sure the data will be correctly gc. jobject jtask_local = env->NewLocalRef(jtask_global); env->DeleteGlobalRef(jtask_global); env->SetObjectField(jcomm, jtask_field_Comm_task, jtask_local); MSG_task_set_data(task, nullptr); } }
/** * \brief Node Function * Arguments: * - my id * - the id of a guy I know in the system (except for the first node) * - the time to sleep before I join (except for the first node) * - the deadline time */ static int node(int argc, char *argv[]) { double init_time = MSG_get_clock(); msg_task_t task_received = NULL; int join_success = 0; double deadline; xbt_assert(argc == 3 || argc == 5, "Wrong number of arguments for this node"); s_node_t node = {0}; node.id = xbt_str_parse_int(argv[1], "Invalid ID: %s"); node.known_id = -1; node.ready = -1; node.pending_tasks = xbt_dynar_new(sizeof(msg_task_t), NULL); get_mailbox(node.id, node.mailbox); XBT_DEBUG("New node with id %s (%08x)", node.mailbox, (unsigned)node.id); for (int i=0; i<LEVELS_COUNT; i++){ int d = domain(node.id, i); for (int j=0; j<LEVEL_SIZE; j++) node.routing_table[i][j] = (d==j) ? node.id : -1; } for (int i=0; i<NEIGHBORHOOD_SIZE; i++) node.neighborhood_set[i] = -1; for (int i=0; i<NAMESPACE_SIZE; i++) node.namespace_set[i] = -1; if (argc == 3) { // first ring XBT_DEBUG("Hey! Let's create the system."); deadline = xbt_str_parse_double(argv[2], "Invalid deadline: %s"); node.ready = 0; XBT_DEBUG("Create a new Pastry ring..."); join_success = 1; } else { node.known_id = xbt_str_parse_int(argv[2], "Invalid known ID: %s"); double sleep_time = xbt_str_parse_double(argv[3], "Invalid sleep time: %s"); deadline = xbt_str_parse_double(argv[4], "Invalid deadline: %s"); // sleep before starting XBT_DEBUG("Let's sleep during %f", sleep_time); MSG_process_sleep(sleep_time); XBT_DEBUG("Hey! Let's join the system."); join_success = join(&node); } if (join_success) { XBT_DEBUG("Waiting …."); while (MSG_get_clock() < init_time + deadline // && MSG_get_clock() < node.last_change_date + 1000 && MSG_get_clock() < max_simulation_time) { if (node.comm_receive == NULL) { task_received = NULL; node.comm_receive = MSG_task_irecv(&task_received, node.mailbox); // FIXME: do not make MSG_task_irecv() calls from several functions } if (!MSG_comm_test(node.comm_receive)) { MSG_process_sleep(5); } else { // a transfer has occurred msg_error_t status = MSG_comm_get_status(node.comm_receive); if (status != MSG_OK) { XBT_DEBUG("Failed to receive a task. Nevermind."); MSG_comm_destroy(node.comm_receive); node.comm_receive = NULL; } else { // the task was successfully received MSG_comm_destroy(node.comm_receive); node.comm_receive = NULL; handle_task(&node, task_received); } } } //Cleanup the receiving communication. if (node.comm_receive != NULL) { if (MSG_comm_test(node.comm_receive) && MSG_comm_get_status(node.comm_receive) == MSG_OK) { task_free(MSG_comm_get_task(node.comm_receive)); } MSG_comm_destroy(node.comm_receive); } } xbt_dynar_free(&node.pending_tasks); return 1; }
/* Master Process */ int master(int argc, char *argv[]) { char * key; struct HdmsgHost *hdmsg_host; xbt_dict_cursor_t cursor = NULL; int i = 0; long remaining_inits = 0; long remaining_mappers = 0; long remaining_shufflers = 0; long remaining_reducers = 0; long expected_messages = 0; msg_comm_t res_irecv; msg_task_t task_com; msg_task_t *tasks = xbt_new(msg_task_t, number_of_workers); xbt_dynar_t comms = xbt_dynar_new(sizeof(msg_comm_t), NULL); XBT_INFO("INITIALIZATION BEGIN"); // Initialize processes (mappers, shufflers, and reducers) on each host xbt_dict_foreach(hosts, cursor, key, hdmsg_host) { if (hdmsg_host->is_worker) { MSG_process_create("Init", initializeProcs, NULL, hdmsg_host->host); tasks[remaining_inits] = NULL; res_irecv = MSG_task_irecv(&tasks[remaining_inits], "master"); xbt_dynar_push_as(comms, msg_comm_t, res_irecv); remaining_inits++; } } while (!xbt_dynar_is_empty(comms)) { xbt_dynar_remove_at(comms, MSG_comm_waitany(comms), &res_irecv); task_com = MSG_comm_get_task(res_irecv); if (!strcmp(MSG_task_get_name(task_com), "init_exit")) { msg_host_t h = MSG_task_get_source(task_com); MSG_task_destroy(task_com); const char *host_name = MSG_host_get_name(h); struct HdmsgHost *hdmsg_host = xbt_dict_get(hosts, host_name); remaining_mappers += get_mapper_count(hdmsg_host); remaining_shufflers += get_shuffler_count(hdmsg_host); remaining_reducers += get_reducer_count(hdmsg_host); remaining_inits--; if (remaining_inits == 0) { XBT_INFO("INITIALIZATION COMPLETE"); // Add an extra message to account for the message sent when the shuffle phase begins expected_messages = 1 + remaining_mappers + remaining_shufflers + remaining_reducers; free(tasks); tasks = xbt_new(msg_task_t, expected_messages); for (i = 0; i < expected_messages; i++) { tasks[i] = NULL; res_irecv = MSG_task_irecv(&tasks[i], "master"); xbt_dynar_push_as(comms, msg_comm_t, res_irecv); } XBT_INFO("MAP PHASE BEGIN"); // Activate Mappers xbt_dict_foreach(hosts, cursor, key, hdmsg_host) { activate_mappers(hdmsg_host); } }