/** @brief Get and remove the last element of the dynar */ XBT_INLINE void xbt_dynar_pop(xbt_dynar_t const dynar, void *const dst) { /* sanity checks done by remove_at */ XBT_CDEBUG(xbt_dyn, "Pop %p", (void *) dynar); xbt_dynar_remove_at(dynar, dynar->used - 1, dst); }
/** * \brief Destroys a task. * * The user data (if any) should have been destroyed first. * * \param task the task you want to destroy * \see SD_task_create() */ void SD_task_destroy(SD_task_t task) { XBT_DEBUG("Destroying task %s...", SD_task_get_name(task)); /* First Remove all dependencies associated with the task. */ while (!task->predecessors->empty()) SD_task_dependency_remove(*(task->predecessors->begin()), task); while (!task->inputs->empty()) SD_task_dependency_remove(*(task->inputs->begin()), task); while (!task->successors->empty()) SD_task_dependency_remove(task, *(task->successors->begin())); while (!task->outputs->empty()) SD_task_dependency_remove(task, *(task->outputs->begin())); if (task->state == SD_SCHEDULED || task->state == SD_RUNNABLE) __SD_task_destroy_scheduling_data(task); int idx = xbt_dynar_search_or_negative(sd_global->return_set, &task); if (idx >=0) { xbt_dynar_remove_at(sd_global->return_set, idx, nullptr); } xbt_free(task->name); if (task->surf_action != nullptr) task->surf_action->unref(); xbt_free(task->host_list); xbt_free(task->bytes_amount); xbt_free(task->flops_amount); xbt_mallocator_release(sd_global->task_mallocator,task); XBT_DEBUG("Task destroyed."); }
/** * \brief Cleans the MSG data of a process. * \param smx_proc a SIMIX process */ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc) { simdata_process_t msg_proc; // get the MSG process from the SIMIX process if (smx_proc == SIMIX_process_self()) { /* avoid a SIMIX request if this function is called by the process itself */ msg_proc = SIMIX_process_self_get_data(smx_proc); SIMIX_process_self_set_data(smx_proc, NULL); } else { msg_proc = simcall_process_get_data(smx_proc); simcall_process_set_data(smx_proc, NULL); } #ifdef HAVE_TRACING TRACE_msg_process_end(smx_proc); #endif // free the data if a function was provided if (msg_proc->data && msg_global->process_data_cleanup) { msg_global->process_data_cleanup(msg_proc->data); } // remove the process from its virtual machine if (msg_proc->vm) { int pos = xbt_dynar_search(msg_proc->vm->processes,&smx_proc); xbt_dynar_remove_at(msg_proc->vm->processes,pos, NULL); } // free the MSG process xbt_free(msg_proc); }
/* Randomly select a host in an array. Rely on the rand function provided by math.h * Remark: This function actually removes the selected element from the array. */ sg_host_t select_random(xbt_dynar_t hosts){ unsigned long i; sg_host_t host=NULL; int nhosts = xbt_dynar_length(hosts); i = (unsigned long) ((nhosts-1.)*rand()/(RAND_MAX+1.0)); xbt_dynar_remove_at(hosts, i, &host); return host; }
/** Sender function */ int sender(int argc, char *argv[]) { long number_of_tasks = atol(argv[1]); double task_comp_size = atof(argv[2]); double task_comm_size = atof(argv[3]); long receivers_count = atol(argv[4]); int diff_com = atol(argv[5]); double coef = 0; xbt_dynar_t d = xbt_dynar_new(sizeof(msg_comm_t), NULL); int i; msg_task_t task; char mailbox[256]; char sprintf_buffer[256]; msg_comm_t comm; for (i = 0; i < number_of_tasks; i++) { if (diff_com == 0) coef = 1; else coef = (i + 1); sprintf(mailbox, "receiver-%ld", (i % receivers_count)); sprintf(sprintf_buffer, "Task_%d", i); task = MSG_task_create(sprintf_buffer, task_comp_size, task_comm_size / coef, NULL); comm = MSG_task_isend(task, mailbox); xbt_dynar_push_as(d, msg_comm_t, comm); XBT_INFO("Send to receiver-%ld %s comm_size %f", i % receivers_count, sprintf_buffer, task_comm_size / coef); } /* Here we are waiting for the completion of all communications */ while (!xbt_dynar_is_empty(d)) { xbt_dynar_remove_at(d, MSG_comm_waitany(d), &comm); MSG_comm_destroy(comm); } xbt_dynar_free(&d); /* Here we are waiting for the completion of all tasks */ sprintf(mailbox, "finalize"); msg_comm_t res_irecv; _XBT_GNUC_UNUSED msg_error_t res_wait; for (i = 0; i < receivers_count; i++) { task = NULL; res_irecv = MSG_task_irecv(&(task), mailbox); res_wait = MSG_comm_wait(res_irecv, -1); xbt_assert(res_wait == MSG_OK, "MSG_comm_wait failed"); MSG_comm_destroy(res_irecv); MSG_task_destroy(task); } XBT_INFO("Goodbye now!"); return 0; } /* end_of_sender */
/** @brief helper function to close a file descriptor */ void process_close_call(process_descriptor_t * proc, int fd) { fd_descriptor_t *file_desc = process_descriptor_get_fd(proc, fd); if (file_desc != NULL) { file_desc->refcount++; if (file_desc->type == FD_SOCKET) socket_close(proc, fd); else { if (file_desc->type == FD_PIPE) { pipe_t *pipe = file_desc->pipe; xbt_assert(pipe != NULL); unsigned int cpt_in; pipe_end_t end_in; xbt_dynar_t read_end = pipe->read_end; xbt_dynar_foreach(read_end, cpt_in, end_in) { if (end_in->fd == fd && end_in->proc->pid == proc->pid) { xbt_dynar_remove_at(read_end, cpt_in, NULL); cpt_in--; } } unsigned int cpt_out; pipe_end_t end_out; xbt_dynar_t write_end = pipe->write_end; xbt_dynar_foreach(write_end, cpt_out, end_out) { if (end_out->fd == fd && end_out->proc->pid == proc->pid) { xbt_dynar_remove_at(write_end, cpt_out, NULL); cpt_out--; } } // if both sides are closed we can free the pipe if (xbt_dynar_is_empty(read_end) && xbt_dynar_is_empty(write_end)) { xbt_dynar_free(&read_end); xbt_dynar_free(&write_end); free(pipe); } } }
static char *TRACE_smpi_get_key(int src, int dst, char *key, int n) { char aux[INSTR_DEFAULT_STR_SIZE]; snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d", src, dst); xbt_dynar_t d = xbt_dict_get_or_null(keys, aux); xbt_assert(!xbt_dynar_is_empty(d), "Trying to get a link key (for message reception) that has no corresponding send (%s).", __FUNCTION__); char *s = xbt_dynar_get_as (d, 0, char *); snprintf (key, n, "%s", s); xbt_dynar_remove_at (d, 0, NULL); return key; }
static void asynchronous_cleanup(void) { process_globals_t globals = (process_globals_t) MSG_process_get_data(MSG_process_self()); /* Destroy any isend which correspond to completed communications */ int found; msg_comm_t comm; while ((found = MSG_comm_testany(globals->isends)) != -1) { xbt_dynar_remove_at(globals->isends, found, &comm); MSG_comm_destroy(comm); } }
/** 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 sender(int argc, char *argv[]) { xbt_assert(argc==6, "This function expects 5 parameters from the XML deployment file"); long number_of_tasks = xbt_str_parse_int(argv[1], "Invalid amount of tasks: %s"); double task_comp_size = xbt_str_parse_double(argv[2], "Invalid computational size: %s"); double task_comm_size = xbt_str_parse_double(argv[3], "Invalid communication size: %s"); long receivers_count = xbt_str_parse_int(argv[4], "Invalid amount of receivers: %s"); int diff_com = xbt_str_parse_int(argv[5], "Invalid value for diff_comm: %s"); xbt_dynar_t comms = xbt_dynar_new(sizeof(msg_comm_t), NULL); /* First pack the communications in the dynar */ for (int i = 0; i < number_of_tasks; i++) { double coef = (diff_com == 0) ? 1 : (i + 1); char mailbox[80]; char taskname[80]; snprintf(mailbox,79, "receiver-%ld", (i % receivers_count)); snprintf(taskname,79, "Task_%d", i); msg_task_t task = MSG_task_create(taskname, task_comp_size, task_comm_size / coef, NULL); msg_comm_t comm = MSG_task_isend(task, mailbox); xbt_dynar_push_as(comms, msg_comm_t, comm); XBT_INFO("Send to receiver-%ld %s comm_size %f", i % receivers_count, taskname, task_comm_size / coef); } /* Here we are waiting for the completion of all communications */ while (xbt_dynar_is_empty(comms) == 0) { msg_comm_t comm; xbt_dynar_remove_at(comms, MSG_comm_waitany(comms), &comm); MSG_comm_destroy(comm); } xbt_dynar_free(&comms); /* Here we are waiting for the completion of all tasks */ for (int i = 0; i < receivers_count; i++) { msg_task_t task = NULL; msg_comm_t comm = MSG_task_irecv(&task, "finalize"); msg_error_t res_wait = MSG_comm_wait(comm, -1); xbt_assert(res_wait == MSG_OK, "MSG_comm_wait failed"); MSG_comm_destroy(comm); MSG_task_destroy(task); } XBT_INFO("Goodbye now!"); return 0; }
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 Removes and free the entry pointed by the cursor * * This function can be used while traversing without problem. */ inline void xbt_dynar_cursor_rm(xbt_dynar_t dynar, unsigned int *const cursor) { xbt_dynar_remove_at(dynar, (*cursor)--, NULL); }
/** @brief Get and remove the first element of the dynar. * * This is less efficient than xbt_dynar_pop() */ inline void xbt_dynar_shift(xbt_dynar_t const dynar, void *const dst) { /* sanity checks done by remove_at */ xbt_dynar_remove_at(dynar, 0, dst); }
/* 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); } }
static int is_visited_state(){ if(_sg_mc_visited == 0) return -1; int raw_mem_set = (mmalloc_get_current_heap() == raw_heap); MC_SET_RAW_MEM; mc_visited_state_t new_state = visited_state_new(); MC_UNSET_RAW_MEM; if(xbt_dynar_is_empty(visited_states)){ MC_SET_RAW_MEM; xbt_dynar_push(visited_states, &new_state); MC_UNSET_RAW_MEM; if(raw_mem_set) MC_SET_RAW_MEM; return -1; }else{ MC_SET_RAW_MEM; size_t current_bytes_used = new_state->heap_bytes_used; int current_nb_processes = new_state->nb_processes; unsigned int cursor = 0; int previous_cursor = 0, next_cursor = 0; int start = 0; int end = xbt_dynar_length(visited_states) - 1; mc_visited_state_t state_test = NULL; size_t bytes_used_test; int nb_processes_test; int same_processes_and_bytes_not_found = 1; while(start <= end && same_processes_and_bytes_not_found){ cursor = (start + end) / 2; state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, cursor, mc_visited_state_t); bytes_used_test = state_test->heap_bytes_used; nb_processes_test = state_test->nb_processes; if(nb_processes_test < current_nb_processes){ start = cursor + 1; }else if(nb_processes_test > current_nb_processes){ end = cursor - 1; }else if(nb_processes_test == current_nb_processes){ if(bytes_used_test < current_bytes_used) start = cursor + 1; if(bytes_used_test > current_bytes_used) end = cursor - 1; if(bytes_used_test == current_bytes_used){ same_processes_and_bytes_not_found = 0; if(snapshot_compare(new_state->system_state, state_test->system_state) == 0){ XBT_DEBUG("State %d already visited ! (equal to state %d)", new_state->num, state_test->num); if(raw_mem_set) MC_SET_RAW_MEM; else MC_UNSET_RAW_MEM; return state_test->num; }else{ /* Search another state with same number of bytes used in std_heap */ previous_cursor = cursor - 1; while(previous_cursor >= 0){ state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, previous_cursor, mc_visited_state_t); bytes_used_test = state_test->system_state->heap_bytes_used; if(bytes_used_test != current_bytes_used) break; if(snapshot_compare(new_state->system_state, state_test->system_state) == 0){ XBT_DEBUG("State %d already visited ! (equal to state %d)", new_state->num, state_test->num); if(raw_mem_set) MC_SET_RAW_MEM; else MC_UNSET_RAW_MEM; return state_test->num; } previous_cursor--; } next_cursor = cursor + 1; while(next_cursor < xbt_dynar_length(visited_states)){ state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, next_cursor, mc_visited_state_t); bytes_used_test = state_test->system_state->heap_bytes_used; if(bytes_used_test != current_bytes_used) break; if(snapshot_compare(new_state->system_state, state_test->system_state) == 0){ XBT_DEBUG("State %d already visited ! (equal to state %d)", new_state->num, state_test->num); if(raw_mem_set) MC_SET_RAW_MEM; else MC_UNSET_RAW_MEM; return state_test->num; } next_cursor++; } } } } } state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, cursor, mc_visited_state_t); bytes_used_test = state_test->heap_bytes_used; if(bytes_used_test < current_bytes_used) xbt_dynar_insert_at(visited_states, cursor + 1, &new_state); else xbt_dynar_insert_at(visited_states, cursor, &new_state); if(xbt_dynar_length(visited_states) > _sg_mc_visited){ int min = mc_stats->expanded_states; unsigned int cursor2 = 0; unsigned int index = 0; xbt_dynar_foreach(visited_states, cursor2, state_test){ if(state_test->num < min){ index = cursor2; min = state_test->num; } } xbt_dynar_remove_at(visited_states, index, NULL); } MC_UNSET_RAW_MEM; if(raw_mem_set) MC_SET_RAW_MEM; return -1; }
static void free_comm(int comm) { xbt_dynar_remove_at(comm_lookup, comm, NULL); }
static void free_datatype(int datatype) { xbt_dynar_remove_at(datatype_lookup, datatype, NULL); }
/** @brief Removes and free the entry pointed by the cursor * * This function can be used while traversing without problem. */ void xbt_dynar_cursor_rm(xbt_dynar_t dynar, unsigned int* const cursor) { xbt_dynar_remove_at(dynar, *cursor, nullptr); *cursor -= 1; }