Esempio n. 1
0
/**
 * \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();
}
Esempio n. 2
0
/*
 * 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];
        }
      }
  }         
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}