/** * \brief Handles a mutex lock simcall. * \param simcall the simcall */ void SIMIX_pre_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex) { XBT_IN("(%p)",simcall); /* FIXME: check where to validate the arguments */ smx_action_t sync_act = NULL; smx_process_t process = simcall->issuer; if (mutex->locked) { /* FIXME: check if the host is active ? */ /* Somebody using the mutex, use a synchro action to get host failures */ sync_act = SIMIX_synchro_wait(process->smx_host, -1); xbt_fifo_push(sync_act->simcalls, simcall); simcall->issuer->waiting_action = sync_act; xbt_swag_insert(simcall->issuer, mutex->sleeping); } else { /* mutex free */ mutex->locked = 1; mutex->owner = simcall->issuer; SIMIX_simcall_answer(simcall); } XBT_OUT(); }
/* * Handle a given task */ static void handle_task(node_t node, msg_task_t task) { XBT_DEBUG("Handling task %p", task); char mailbox[MAILBOX_NAME_SIZE]; int i, j, min, max, d; msg_task_t task_sent; task_data_t req_data; task_data_t task_data = (task_data_t) MSG_task_get_data(task); e_task_type_t type = task_data->type; // If the node is not ready keep the task for later if (node->ready != 0 && !(type==TASK_JOIN_LAST_REPLY || type==TASK_JOIN_REPLY)) { XBT_DEBUG("Task pending %i", type); xbt_fifo_push(node->pending_tasks, task); return; } switch (type) { /* * Try to join the ring */ case TASK_JOIN: { int next = routing_next(node, task_data->answer_id); XBT_DEBUG("Join request from %08x forwarding to %08x", task_data->answer_id, next); type = TASK_JOIN_LAST_REPLY; req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = task_data->sender_id; req_data->steps = task_data->steps + 1; // if next different from current node forward the join if (next!=node->id) { get_mailbox(next, mailbox); task_data->sender_id = node->id; task_data->steps++; task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, task_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); type = TASK_JOIN_REPLY; } // send back the current node state to the joining node req_data->type = type; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, task_data->answer_to, timeout); break; } /* * Join reply from all the node touched by the join */ case TASK_JOIN_LAST_REPLY: // if last node touched reply, copy its namespace set // TODO: it's work only if the two nodes are side to side (is it really the case ?) j = (task_data->sender_id < node->id) ? -1 : 0; for (i=0; i<NAMESPACE_SIZE/2; i++) { node->namespace_set[i] = task_data->state->namespace_set[i-j]; node->namespace_set[NAMESPACE_SIZE-1-i] = task_data->state->namespace_set[NAMESPACE_SIZE-1-i-j-1]; } node->namespace_set[NAMESPACE_SIZE/2+j] = task_data->sender_id; node->ready += task_data->steps + 1; case TASK_JOIN_REPLY: XBT_DEBUG("Joining Reply"); // if first node touched reply, copy its neighborood set if (task_data->sender_id == node->known_id) { node->neighborhood_set[0] = task_data->sender_id; for (i=1; i<NEIGHBORHOOD_SIZE; i++) node->neighborhood_set[i] = task_data->state->neighborhood_set[i-1]; } // copy the corresponding routing table levels min = (node->id==task_data->answer_id) ? 0 : shl(node->id, task_data->answer_id); max = shl(node->id, task_data->sender_id)+1; for (i=min;i<max;i++) { d = domain(node->id, i); for (j=0; j<LEVEL_SIZE; j++) if (d!=j) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } node->ready--; // if the node is ready, do all the pending tasks and send update to known nodes if (node->ready==0) { XBT_DEBUG("Node %i is ready!!!", node->id); while(xbt_fifo_size(node->pending_tasks)) handle_task(node, xbt_fifo_pop(node->pending_tasks)); for (i=0; i<NAMESPACE_SIZE; i++) { j = node->namespace_set[i]; if (j!=-1) { XBT_DEBUG("Send update to %i", j); get_mailbox(j, mailbox); req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = node->id; req_data->steps = 0; req_data->type = TASK_UPDATE; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); } } } break; /* * Recieved an update of state */ case TASK_UPDATE: XBT_DEBUG("Task update %i !!!", node->id); /* Update namespace ses */ printf("Task update from %i !!!\n", task_data->sender_id); print_node_id(node); print_node_namespace_set(node); int curr_namespace_set[NAMESPACE_SIZE]; int task_namespace_set[NAMESPACE_SIZE+1]; // Copy the current namedspace // and the task state namespace with state->id in the middle i=0; for (; i<NAMESPACE_SIZE/2; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i] = task_data->state->namespace_set[i]; } task_namespace_set[i] = task_data->state->id; for (; i<NAMESPACE_SIZE; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i+1] = task_data->state->namespace_set[i]; } // get the index of values before and after node->id in task_namespace min = -1; max = -1; for (i=0; i<=NAMESPACE_SIZE; i++) { j = task_namespace_set[i]; if (i<NAMESPACE_SIZE) printf("%08x %08x | ", j, curr_namespace_set[i]); if (j != -1 && j < node->id) min = i; if (j != -1 && max == -1 && j > node->id) max = i; } printf("\n"); // add lower elements j = NAMESPACE_SIZE/2-1; for (i=NAMESPACE_SIZE/2-1; i>=0; i--) { printf("i:%i, j:%i, min:%i, currj:%08x, taskmin:%08x\n", i, j, min, curr_namespace_set[j], task_namespace_set[min]); if (min<0) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else if (curr_namespace_set[j] == task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; min--; } else if (curr_namespace_set[j] > task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else { node->namespace_set[i] = task_namespace_set[min]; min--; } } // add greater elements j = NAMESPACE_SIZE/2; for (i=NAMESPACE_SIZE/2; i<NAMESPACE_SIZE; i++) { printf("i:%i, j:%i, max:%i, currj:%08x, taskmax:%08x\n", i, j, max, curr_namespace_set[j], task_namespace_set[max]); if (min<0 || max>=NAMESPACE_SIZE) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else if (curr_namespace_set[j] == -1) { node->namespace_set[i] = task_namespace_set[max]; max++; } else if (curr_namespace_set[j] == task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; max++; } else if (curr_namespace_set[j] < task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else { node->namespace_set[i] = task_namespace_set[max]; max++; } } print_node_namespace_set(node); /* Update routing table */ for (i=shl(node->id, task_data->state->id); i<LEVELS_COUNT; i++) { for (j=0; j<LEVEL_SIZE; j++) { if (node->routing_table[i][j]==-1 && task_data->state->routing_table[i][j]==-1) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } } } }
XBT_PRIVATE smx_activity_t simcall_HANDLER_comm_isend(smx_simcall_t simcall, smx_actor_t src_proc, smx_mailbox_t mbox, double task_size, double rate, void *src_buff, size_t src_buff_size, int (*match_fun)(void *, void *,smx_activity_t), void (*clean_fun)(void *), // used to free the synchro in case of problem after a detached send void (*copy_data_fun)(smx_activity_t, void*, size_t),// used to copy data if not default one void *data, int detached) { XBT_DEBUG("send from %p", mbox); /* Prepare a synchro describing us, so that it gets passed to the user-provided filter of other side */ simgrid::kernel::activity::Comm* this_synchro = new simgrid::kernel::activity::Comm(SIMIX_COMM_SEND); /* Look for communication synchro matching our needs. We also provide a description of * ourself so that the other side also gets a chance of choosing if it wants to match with us. * * If it is not found then push our communication into the rendez-vous point */ smx_activity_t other_synchro = _find_matching_comm(&mbox->comm_queue, SIMIX_COMM_RECEIVE, match_fun, data, this_synchro, /*remove_matching*/true); simgrid::kernel::activity::Comm *other_comm = static_cast<simgrid::kernel::activity::Comm*>(other_synchro); if (!other_synchro) { other_synchro = this_synchro; other_comm = static_cast<simgrid::kernel::activity::Comm*>(other_synchro); if (mbox->permanent_receiver!=nullptr){ //this mailbox is for small messages, which have to be sent right now other_synchro->state = SIMIX_READY; other_comm->dst_proc=mbox->permanent_receiver.get(); other_comm->ref(); mbox->done_comm_queue.push_back(other_synchro); XBT_DEBUG("pushing a message into the permanent receive fifo %p, comm %p", mbox, &(other_comm)); }else{ SIMIX_mbox_push(mbox, this_synchro); } } else { XBT_DEBUG("Receive already pushed"); this_synchro->unref(); other_comm->state = SIMIX_READY; other_comm->type = SIMIX_COMM_READY; } xbt_fifo_push(src_proc->comms, other_synchro); if (detached) { other_comm->detached = true; other_comm->clean_fun = clean_fun; } else { other_comm->clean_fun = nullptr; } /* Setup the communication synchro */ other_comm->src_proc = src_proc; other_comm->task_size = task_size; other_comm->rate = rate; other_comm->src_buff = src_buff; other_comm->src_buff_size = src_buff_size; other_comm->src_data = data; other_comm->match_fun = match_fun; other_comm->copy_data_fun = copy_data_fun; if (MC_is_active() || MC_record_replay_is_active()) { other_comm->state = SIMIX_RUNNING; return (detached ? nullptr : other_comm); } SIMIX_comm_start(other_comm); return (detached ? nullptr : other_comm); }
smx_activity_t SIMIX_comm_irecv(smx_actor_t dst_proc, smx_mailbox_t mbox, void *dst_buff, size_t *dst_buff_size, int (*match_fun)(void *, void *, smx_activity_t), void (*copy_data_fun)(smx_activity_t, void*, size_t), // used to copy data if not default one void *data, double rate) { XBT_DEBUG("recv from %p %p", mbox, &mbox->comm_queue); simgrid::kernel::activity::Comm* this_synchro = new simgrid::kernel::activity::Comm(SIMIX_COMM_RECEIVE); smx_activity_t other_synchro; //communication already done, get it inside the fifo of completed comms if (mbox->permanent_receiver != nullptr && ! mbox->done_comm_queue.empty()) { XBT_DEBUG("We have a comm that has probably already been received, trying to match it, to skip the communication"); //find a match in the already received fifo other_synchro = _find_matching_comm(&mbox->done_comm_queue, SIMIX_COMM_SEND, match_fun, data, this_synchro,/*remove_matching*/true); //if not found, assume the receiver came first, register it to the mailbox in the classical way if (!other_synchro) { XBT_DEBUG("We have messages in the permanent receive list, but not the one we are looking for, pushing request into fifo"); other_synchro = this_synchro; SIMIX_mbox_push(mbox, this_synchro); } else { simgrid::kernel::activity::Comm *other_comm = static_cast<simgrid::kernel::activity::Comm*>(other_synchro); if(other_comm->surf_comm && other_comm->remains() < 1e-12) { XBT_DEBUG("comm %p has been already sent, and is finished, destroy it",other_comm); other_comm->state = SIMIX_DONE; other_comm->type = SIMIX_COMM_DONE; other_comm->mbox = nullptr; } other_comm->unref(); static_cast<simgrid::kernel::activity::Comm*>(this_synchro)->unref(); } } else { /* Prepare a synchro describing us, so that it gets passed to the user-provided filter of other side */ /* Look for communication synchro matching our needs. We also provide a description of * ourself so that the other side also gets a chance of choosing if it wants to match with us. * * If it is not found then push our communication into the rendez-vous point */ other_synchro = _find_matching_comm(&mbox->comm_queue, SIMIX_COMM_SEND, match_fun, data, this_synchro,/*remove_matching*/true); if (!other_synchro) { XBT_DEBUG("Receive pushed first %zu", mbox->comm_queue.size()); other_synchro = this_synchro; SIMIX_mbox_push(mbox, this_synchro); } else { this_synchro->unref(); simgrid::kernel::activity::Comm *other_comm = static_cast<simgrid::kernel::activity::Comm*>(other_synchro); other_comm->state = SIMIX_READY; other_comm->type = SIMIX_COMM_READY; } xbt_fifo_push(dst_proc->comms, other_synchro); } /* Setup communication synchro */ simgrid::kernel::activity::Comm *other_comm = static_cast<simgrid::kernel::activity::Comm*>(other_synchro); other_comm->dst_proc = dst_proc; other_comm->dst_buff = dst_buff; other_comm->dst_buff_size = dst_buff_size; other_comm->dst_data = data; if (rate > -1.0 && (other_comm->rate < 0.0 || rate < other_comm->rate)) other_comm->rate = rate; other_comm->match_fun = match_fun; other_comm->copy_data_fun = copy_data_fun; if (MC_is_active() || MC_record_replay_is_active()) { other_synchro->state = SIMIX_RUNNING; return other_synchro; } SIMIX_comm_start(other_synchro); return other_synchro; }
task_t new_task(task_type_t e_type, msched_args_t ps_args, task_t p_ancestor, unsigned int ui_a1, unsigned int ui_a2, unsigned int ui_a3, unsigned int ui_a4) { task_t p_task = (task_t)xbt_new(s_task_t,1); p_task->uc_done = 0; p_task->p_proc_map = NULL; p_task->e_type = e_type; p_task->ui_tile_size = ps_args->ui_tile_size; p_task->a_ancestors = xbt_dynar_new(sizeof(task_t),NULL); switch (e_type) { case F: p_task->task.F.ui_i = ui_a1; p_task->task.F.ui_j = ui_a2; if (ps_args->uc_coarse) { p_task->f_unit_cost = 0; } else { p_task->f_unit_cost = 4; } sprintf(p_task->name,"F(%u,%u)",ui_a1,ui_a2); xbt_fifo_push(ps_args->a_tile_updates[p_task->task.F.ui_i*ps_args->ui_q+p_task->task.F.ui_j], p_task); break; case H: p_task->task.H.ui_i = ui_a1; p_task->task.H.ui_j = ui_a2; p_task->task.H.ui_k = ui_a3; if (ps_args->uc_coarse) { p_task->f_unit_cost = 0; }else{ p_task->f_unit_cost = 6; } sprintf(p_task->name,"H(%u,%u,%u)",ui_a1,ui_a2,ui_a3); /*place the update in the tile fifo*/ xbt_fifo_push(ps_args->a_tile_updates[p_task->task.H.ui_i*ps_args->ui_q+p_task->task.H.ui_k], p_task); xbt_dynar_push_as(p_task->a_ancestors,task_t,p_ancestor); break; case Z: p_task->task.Z.ui_i = ui_a1; p_task->task.Z.ui_ii = ui_a2; p_task->task.Z.ui_j = ui_a3; if (ps_args->uc_coarse) { p_task->f_unit_cost = 1; }else{ p_task->f_unit_cost = 2; } xbt_fifo_push(ps_args->a_tile_updates[p_task->task.Z.ui_i*ps_args->ui_q+p_task->task.Z.ui_j], p_task); xbt_fifo_push(ps_args->a_tile_updates[p_task->task.Z.ui_ii*ps_args->ui_q+p_task->task.Z.ui_j], p_task); sprintf(p_task->name,"Z(%u,%u,%u)",ui_a1,ui_a2,ui_a3); break; case ZS: p_task->task.Z.ui_i = ui_a1; p_task->task.Z.ui_ii = ui_a2; p_task->task.Z.ui_j = ui_a3; if (ps_args->uc_coarse) { p_task->f_unit_cost = 1; }else{ p_task->f_unit_cost = 6; } /*place the update in the tile fifo*/ xbt_fifo_push(ps_args->a_tile_updates[p_task->task.Z.ui_i*ps_args->ui_q+p_task->task.Z.ui_j], p_task); xbt_fifo_push(ps_args->a_tile_updates[p_task->task.Z.ui_ii*ps_args->ui_q+p_task->task.Z.ui_j], p_task); sprintf(p_task->name,"ZS(%u,%u,%u)",ui_a1,ui_a2,ui_a3); break; case V: p_task->task.V.ui_i = ui_a1; p_task->task.V.ui_ii = ui_a2; p_task->task.V.ui_j = ui_a3; p_task->task.V.ui_k = ui_a4; if (ps_args->uc_coarse) { if(ps_args->fptr_handle_finish!=NULL){ p_task->f_unit_cost = 0; } else{ p_task->f_unit_cost = 1; } }else{ p_task->f_unit_cost = 6; } xbt_dynar_push_as(p_task->a_ancestors,task_t,p_ancestor); /*place the update in the tile fifo*/ xbt_fifo_push(ps_args->a_tile_updates[p_task->task.V.ui_i*ps_args->ui_q+p_task->task.V.ui_k], p_task); xbt_fifo_push(ps_args->a_tile_updates[p_task->task.V.ui_ii*ps_args->ui_q+p_task->task.V.ui_k], p_task); sprintf(p_task->name,"V(%u,%u,%u,%u)",ui_a1,ui_a2,ui_a3,ui_a4); break; case VS: p_task->task.V.ui_i = ui_a1; p_task->task.V.ui_ii = ui_a2; p_task->task.V.ui_j = ui_a3; p_task->task.V.ui_k = ui_a4; if (ps_args->uc_coarse) { if(ps_args->fptr_handle_finish!=NULL){ p_task->f_unit_cost = 0; } else{ p_task->f_unit_cost = 1; } }else{ p_task->f_unit_cost = 12; } xbt_dynar_push_as(p_task->a_ancestors,task_t,p_ancestor); /*place the update in the tile fifo*/ xbt_fifo_push(ps_args->a_tile_updates[p_task->task.V.ui_i*ps_args->ui_q+p_task->task.V.ui_k], p_task); xbt_fifo_push(ps_args->a_tile_updates[p_task->task.V.ui_ii*ps_args->ui_q+p_task->task.V.ui_k], p_task); sprintf(p_task->name,"VS(%u,%u,%u,%u)",ui_a1,ui_a2,ui_a3,ui_a4); break; default: exit(-1); break; } operation_cnt+=ceil(p_task->f_unit_cost); xbt_dynar_push_as(ps_args->a_ET, task_t,p_task); xbt_fifo_push(ps_args->a_general_workqueue, p_task); return p_task; }