Example #1
0
/** \ingroup msg_task_usage
 * \brief Checks whether a communication is done, and if yes, finalizes it.
 * \param comm the communication to test
 * \return TRUE if the communication is finished
 * (but it may have failed, use MSG_comm_get_status() to know its status)
 * or FALSE if the communication is not finished yet
 * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
 */
int MSG_comm_test(msg_comm_t comm)
{
  xbt_ex_t e;
  int finished = 0;

  TRY {
    finished = simcall_comm_test(comm->s_comm);

    if (finished && comm->task_received != NULL) {
      /* I am the receiver */
      if (msg_global->debug_multiple_use && (*comm->task_received)->simdata->isused!=0)
        xbt_ex_free(*(xbt_ex_t*)(*comm->task_received)->simdata->isused);
      (*comm->task_received)->simdata->isused = 0;
    }
  }
  CATCH(e) {
    switch (e.category) {
      case network_error:
        comm->status = MSG_TRANSFER_FAILURE;
        finished = 1;
        break;

      case timeout_error:
        comm->status = MSG_TIMEOUT;
        finished = 1;
        break;

      default:
        RETHROW;
    }
    xbt_ex_free(e);
  }

  return finished;
}
Example #2
0
/** Victim. This process gets a lot of remote exceptions  */
static int victim(int argc, char *argv[]) {

  xbt_ex_t e;
  msg_error_t res = MSG_OK;
  
  XBT_INFO("Let's work.");
  TRY {	
    res = MSG_task_execute(MSG_task_create("Task", 1e14, 0, NULL));
    if (res != MSG_OK) {
      XBT_INFO("The MSG_task_execute caught the exception for me and returned %d)",res);
    } else {
      xbt_die("I was expecting an exception during my execution!");
    }
  } CATCH(e) {
    XBT_INFO("The received exception resumed my execution. Good. Here is it:  ----------------------->8----");
    xbt_ex_display(&e);
    XBT_INFO("(end of the first exception) ----8<------------------------");
    xbt_ex_free(e);
  }


  XBT_INFO("Let's get suspended.");
  int gotit = 0;
  TRY {
    MSG_process_suspend(MSG_process_self());
  } CATCH(e) {
    XBT_INFO("The received exception resumed my suspension. Good. Here is it:  ----------------------->8----");
    xbt_ex_display(&e);
    XBT_INFO("(end of the second exception) ----8<------------------------");
    gotit = 1;
    xbt_ex_free(e);
  }
  if(!gotit) {
    xbt_die("I was expecting an exception during my suspension!");
  }
  
  XBT_INFO("Let's sleep for 10 seconds.");
  TRY {
    res = MSG_process_sleep(10);
    if (res != MSG_OK) {
      XBT_INFO("The MSG_process_sleep caught the exception for me and returned %d)",res);
    } else {
      xbt_die("I was expecting to get an exception during my nap.");
    }
  } CATCH(e) {
    XBT_INFO("Got the second exception:   ----------------------->8----");
    xbt_ex_display(&e);
    XBT_INFO("(end of the third exception) ----8<------------------------");
    xbt_ex_free(e);
  }

  XBT_INFO("Let's try a last time to do something on something");
  MSG_process_sleep(10);

  XBT_INFO("That's enough now. I quit.");
  
  return 0;
}
Example #3
0
/** \ingroup msg_mailbox_management
 * \brief Get a task from a mailbox on a given host at a given rate
 *
 * \param mailbox The mailbox where the task was sent
 * \param task a memory location for storing a #msg_task_t.
 * \param host a #msg_host_t host from where the task was sent
 * \param timeout a timeout
 * \param rate a rate

 * \return Returns
 * #MSG_OK if the task was successfully received,
 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
 */
msg_error_t
MSG_mailbox_get_task_ext_bounded(msg_mailbox_t mailbox, msg_task_t * task,
                                 msg_host_t host, double timeout, double rate)
{
  xbt_ex_t e;
  msg_error_t ret = MSG_OK;
  /* We no longer support getting a task from a specific host */
  if (host)
    THROW_UNIMPLEMENTED;

  TRACE_msg_task_get_start();
  double start_time = MSG_get_clock();

  /* Sanity check */
  xbt_assert(task, "Null pointer for the task storage");

  if (*task)
    XBT_WARN
        ("Asked to write the received task in a non empty struct -- proceeding.");

  /* Try to receive it by calling SIMIX network layer */
  TRY {
    simcall_comm_recv(mailbox, task, NULL, NULL, NULL, NULL, timeout, rate);
    XBT_DEBUG("Got task %s from %p",(*task)->name,mailbox);
    if (msg_global->debug_multiple_use && (*task)->simdata->isused!=0)
      xbt_ex_free(*(xbt_ex_t*)(*task)->simdata->isused);
    (*task)->simdata->isused = 0;
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      ret = MSG_HOST_FAILURE;
      break;
    case network_error:
      ret = MSG_TRANSFER_FAILURE;
      break;
    case timeout_error:
      ret = MSG_TIMEOUT;
      break;
    case host_error:
      ret = MSG_HOST_FAILURE;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }

  if (ret != MSG_HOST_FAILURE &&
      ret != MSG_TRANSFER_FAILURE &&
      ret != MSG_TIMEOUT) {
    TRACE_msg_task_get_end(start_time, *task);
  }
  MSG_RETURN(ret);
}
Example #4
0
void xbt_backtrace_display(xbt_ex_t * e)
{
    xbt_ex_setup_backtrace(e);

#ifdef HAVE_BACKTRACE
    if (e->used == 0) {
        fprintf(stderr, "(backtrace not set)\n");
    } else {
        int i;

        fprintf(stderr, "Backtrace (displayed in thread %p):\n",
                (void *) xbt_thread_self());
        for (i = 1; i < e->used; i++)       /* no need to display "xbt_display_backtrace" */
            fprintf(stderr, "---> %s\n", e->bt_strings[i] + 4);
    }

    /* don't fool xbt_ex_free with uninitialized msg field */
    e->msg = NULL;
    e->remote = 0;
    xbt_ex_free(*e);
#else

    XBT_ERROR("No backtrace on this arch");
#endif
}
Example #5
0
/** \ingroup msg_task_usage
 * \brief Receives a task from a mailbox from a specific host with a given timeout.
 *
 * This is a blocking function with a timeout, the execution flow will be blocked
 * until the task is received or the timeout is achieved. See #MSG_task_irecv
 * for receiving tasks asynchronously. You can provide a -1 timeout
 * to obtain an infinite timeout.
 *
 * \param task a memory location for storing a #msg_task_t.
 * \param alias name of the mailbox to receive the task from
 * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
 * \param host a #msg_host_t host from where the task was sent
 *
 * \return Returns
 * #MSG_OK if the task was successfully received,
* #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
 */
msg_error_t
MSG_task_receive_ext(msg_task_t * task, const char *alias, double timeout,
                     msg_host_t host)
{
  xbt_ex_t e;
  msg_error_t ret = MSG_OK;
  XBT_DEBUG
      ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
       alias);
  TRY {
    ret = MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task,
                                   host, timeout);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:          /* may be thrown by MSG_mailbox_get_by_alias */
      ret = MSG_HOST_FAILURE;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }
  return ret;
}
Example #6
0
/** \ingroup msg_task_usage
 * \brief Sleep for the specified number of seconds
 *
 * Makes the current process sleep until \a time seconds have elapsed.
 *
 * \param nb_sec a number of second
 */
msg_error_t MSG_process_sleep(double nb_sec)
{
  xbt_ex_t e;
  msg_error_t status = MSG_OK;
  /*msg_process_t proc = MSG_process_self();*/

  TRACE_msg_process_sleep_in(MSG_process_self());

  TRY {
    simcall_process_sleep(nb_sec);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      XBT_DEBUG("According to the JAVA API, a sleep call should only deal with HostFailureException, WTF here ?"); 
      // adsein: MSG_TASK_CANCELED is assigned when someone kills the process that made the sleep, this is not
      // correct. For instance, when the node is turned off, the error should be MSG_HOST_FAILURE, which is by the way
      // and according to the JAVA document, the only exception that can be triggered by MSG_Process_sleep call.
      // To avoid possible impacts in the code, I just raised a host_failure exception for the moment in the JAVA code
      // and did not change anythings at the C level.
      // See comment in the jmsg_process.c file, function JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_sleep(JNIEnv *env, jclass cls, jlong jmillis, jint jnanos) 
      status = MSG_TASK_CANCELED;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }

  TRACE_msg_process_sleep_out(MSG_process_self());
  MSG_RETURN(status);
}
Example #7
0
JNIEXPORT void JNICALL Java_org_simgrid_msg_Mutex_acquire(JNIEnv * env, jobject obj) {
  xbt_mutex_t mutex;

  mutex = (xbt_mutex_t) (uintptr_t) env->GetLongField(obj, jsyncro_field_Mutex_bind);
  xbt_ex_t e;
  TRY {
    xbt_mutex_acquire(mutex);
  }
  CATCH(e) {
    xbt_ex_free(e);
  }
}
Example #8
0
int client(int argc, char *argv[])
{
  gras_socket_t mysock;         /* socket on which I listen */
  gras_socket_t toserver;       /* socket used to write to the server */

  gras_init(&argc, argv);

  message_declaration();
  mysock = gras_socket_server_range(1024, 10000, 0, 0);

  XBT_VERB("Client ready; listening on %d", gras_socket_my_port(mysock));

  gras_os_sleep(1.5);           /* sleep 1 second and half */
  toserver = gras_socket_client(argv[1], atoi(argv[2]));

  long long_to_convert = 4321;
  char *string_result;
  XBT_INFO("Ask to convert %ld", long_to_convert);
  gras_msg_rpccall(toserver, 60, "convert i2a", &long_to_convert,
                   &string_result);
  XBT_INFO("The server says that %ld is equal to \"%s\".", long_to_convert,
        string_result);
  free(string_result);

  char *string_to_convert = "1234";
  long long_result;
  XBT_INFO("Ask to convert %s", string_to_convert);
  gras_msg_rpccall(toserver, 60, "convert a2i", &string_to_convert,
                   &long_result);
  XBT_INFO("The server says that \"%s\" is equal to %d.", string_to_convert,
        long_result);

  xbt_ex_t e;
  string_to_convert = "azerty";
  TRY {
    gras_msg_rpccall(toserver, 60, "convert a2i", &string_to_convert,
                     &long_result);
  } CATCH(e) {
    XBT_INFO
        ("The server refuses to convert %s. Here is the received exception:",
         string_to_convert);
    xbt_ex_display(&e);
    xbt_ex_free(e);
    XBT_INFO("Again, previous exception was excepted");
  }

  gras_msg_send(toserver, "done", NULL);
  XBT_INFO("Stopped the server");

  gras_exit();
  return 0;
}
val_t PJ_value_get_or_new (const char *name, const char *color, type_t father)
{
  val_t ret = 0;
  xbt_ex_t e;
  TRY {
    ret = PJ_value_get(name, father);
  }
  CATCH(e) {
    xbt_ex_free(e);
    ret = PJ_value_new(name, color, father);
  }
  return ret;
}
Example #10
0
File: dynar.c Project: R7R8/simgrid
/** @brief Returns a boolean indicating whether the element is part of the dynar 
 *
 * Beware that if your dynar contains pointed values (such as strings) instead of scalar, this function is probably not
 * what you want. Check the documentation of xbt_dynar_search() for more info.
 */
int xbt_dynar_member(xbt_dynar_t const dynar, void *const elem)
{
  xbt_ex_t e;

  TRY {
    xbt_dynar_search(dynar, elem);
  } CATCH(e) {
    if (e.category == not_found_error) {
      xbt_ex_free(e);
      return 0;
    }
    RETHROW;
  }
  return 1;
}
Example #11
0
/** @brief locks on a semaphore object up until the provided timeout expires */
msg_error_t MSG_sem_acquire_timeout(msg_sem_t sem, double timeout) {
  xbt_ex_t e;
  msg_error_t res = MSG_OK;
  TRY {
    simcall_sem_acquire_timeout(sem,timeout);
  } CATCH(e) {
    if (e.category == timeout_error) {
      res = MSG_TIMEOUT;
      xbt_ex_free(e);
    } else {
      RETHROW;
    }
  }
  return res;
}
Example #12
0
/** \ingroup m_task_usage
 * \brief Cancel a #msg_task_t.
 * \param task the task to cancel. If it was executed or transfered, it
          stops the process that were working on it.
 */
msg_error_t MSG_task_cancel(msg_task_t task)
{
  xbt_assert((task != NULL), "Cannot cancel a NULL task");

  if (task->simdata->compute) {
    simcall_process_execution_cancel(task->simdata->compute);
  }
  else if (task->simdata->comm) {
    simdata_task_t simdata = task->simdata;
    simcall_comm_cancel(simdata->comm);
    if (msg_global->debug_multiple_use && simdata->isused!=0)
      xbt_ex_free(*(xbt_ex_t*)simdata->isused);
    simdata->isused = 0;
  }
  return MSG_OK;
}
Example #13
0
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Process_restart
    (JNIEnv *env, jobject jprocess) {
  msg_process_t process = jprocess_to_native_process(jprocess, env);
  xbt_ex_t e;

  if (!process) {
    jxbt_throw_notbound(env, "process", jprocess);
    return;
  }

  TRY {
    MSG_process_restart(process);
  }
  CATCH (e) {
    xbt_ex_free(e);
  }

}
Example #14
0
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Process_setAutoRestart
    (JNIEnv *env, jobject jprocess, jboolean jauto_restart) {
  msg_process_t process = jprocess_to_native_process(jprocess, env);
  xbt_ex_t e;

  int auto_restart = jauto_restart == JNI_TRUE ? 1 : 0;

  if (!process) {
    jxbt_throw_notbound(env, "process", jprocess);
    return;
  }

  TRY {
    MSG_process_auto_restart_set(process,auto_restart);
  }
  CATCH (e) {
    xbt_ex_free(e);
  }
}
Example #15
0
void
xbt_multidict_remove_ext(xbt_dict_t mdict, xbt_dynar_t keys,
                         xbt_dynar_t lens)
{
  volatile xbt_dict_t thislevel;
  volatile xbt_dict_t nextlevel = NULL;
  volatile int i;
  xbt_ex_t e;

  unsigned long int thislen;
  char *thiskey;
  int keys_len = xbt_dynar_length(keys);

  xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens));
  xbt_assert(xbt_dynar_length(keys),
              "Can't remove a zero-long key set in a multidict");

  for (i = 0, thislevel = mdict; i < keys_len - 1;
       i++, thislevel = nextlevel) {

    xbt_dynar_get_cpy(keys, i, &thiskey);
    xbt_dynar_get_cpy(lens, i, &thislen);

    /* search the dict of next level */
    TRY {
      nextlevel = xbt_dict_get_ext(thislevel, thiskey, thislen);
    }
    CATCH(e) {
      /* If non-existant entry, nothing to do */
      if (e.category == arg_error)
        xbt_ex_free(e);
      else
        RETHROW;
    }
  }

  xbt_dynar_get_cpy(keys, i, &thiskey);
  xbt_dynar_get_cpy(lens, i, &thislen);

  xbt_dict_remove_ext(thislevel, thiskey, thislen);
}
Example #16
0
int smpi_shared_known_call(const char* func, const char* input) {
   char* loc = bprintf("%s:%s", func, input);
   xbt_ex_t ex;
   int known;

   if(!calls) {
      calls = xbt_dict_new_homogeneous(NULL);
   }
   TRY {
      xbt_dict_get(calls, loc); /* Succeed or throw */
      known = 1;
   }
   CATCH(ex) {
      if(ex.category == not_found_error) {
         known = 0;
         xbt_ex_free(ex);
      } else {
         RETHROW;
      }
   }
   free(loc);
   return known;
}
Example #17
0
/** \ingroup msg_task_usage
 * \brief Sleep for the specified number of seconds
 *
 * Makes the current process sleep until \a time seconds have elapsed.
 *
 * \param nb_sec a number of second
 */
msg_error_t MSG_process_sleep(double nb_sec)
{
  xbt_ex_t e;
  msg_error_t status = MSG_OK;
  /*msg_process_t proc = MSG_process_self();*/

#ifdef HAVE_TRACING
  TRACE_msg_process_sleep_in(MSG_process_self());
#endif

  /* create action to sleep */

  /*proc->simdata->waiting_action = act_sleep;

  FIXME: check if not setting the waiting_action breaks something on msg
  
  proc->simdata->waiting_action = NULL;*/

  TRY {
    simcall_process_sleep(nb_sec);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      status = MSG_TASK_CANCELED;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }

  #ifdef HAVE_TRACING
    TRACE_msg_process_sleep_out(MSG_process_self());
  #endif
  MSG_RETURN(status);
}
Example #18
0
static int xbt_log_layout_format_doit(xbt_log_layout_t l,
                                      xbt_log_event_t ev,
                                      const char *msg_fmt)
{
  char *p = ev->buffer;
  int rem_size = ev->buffer_size;
  int precision = -1;
  int length = -1;
  char *q;

  for (q = l->data ; *q != '\0' ; q++) {
    if (*q == '%') {
      q++;
    handle_modifier:
      switch (*q) {
      case '\0':
        fprintf(stderr, "Layout format (%s) ending with %%\n", (char *)l->data);
        xbt_abort();
      case '%':
        *p = '%';
        check_overflow(1);
        break;
      case 'n':         /* platform-dependant line separator; LOG4J compliant */
        *p = '\n';
        check_overflow(1);
        break;
      case 'e':                 /* plain space; SimGrid extension */
        *p = ' ';
        check_overflow(1);
        break;
      case '.':                 /* precision specifier */
        precision = strtol(q + 1, &q, 10);
        goto handle_modifier;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':                 /* length modifier */
        length = strtol(q, &q, 10);
        goto handle_modifier;
      case 'c':                 /* category name; LOG4J compliant
                                   should accept a precision postfix to show the
                                   hierarchy */
        show_string(ev->cat->name);
        break;
      case 'p':                 /* priority name; LOG4J compliant */
        show_string(xbt_log_priority_names[ev->priority]);
        break;
      case 'h':                 /* host name; SimGrid extension */
        show_string(SIMIX_host_self_get_name());
        break;
      case 't':                 /* thread name; LOG4J compliant */
        show_string(xbt_thread_self_name());
        break;
      case 'P':                 /* process name; SimGrid extension */
        show_string(xbt_procname());
        break;
      case 'i':                 /* process PID name; SimGrid extension */
        show_int(xbt_getpid());
        break;
      case 'F':                 /* file name; LOG4J compliant */
        show_string(ev->fileName);
        break;
      case 'l': {               /* location; LOG4J compliant */
        int len, sz;
        set_sz_from_precision();
        len = snprintf(p, sz, "%s:%d", ev->fileName, ev->lineNum);
        check_overflow(MIN(sz, len));
        break;
      }
      case 'L':                 /* line number; LOG4J compliant */
        show_int(ev->lineNum);
        break;
      case 'M':                /* method (ie, function) name; LOG4J compliant */
        show_string(ev->functionName);
        break;
      case 'b':                 /* backtrace; called %throwable in LOG4J */
      case 'B':         /* short backtrace; called %throwable{short} in LOG4J */
#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
        {
          xbt_ex_t e;

          e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
          e.bt_strings = NULL;
          e.msg = NULL;
          xbt_ex_setup_backtrace(&e);
          if (*q == 'B') {
            show_string(e.bt_strings[1] + 8);
          } else {
            xbt_strbuff_t buff = xbt_strbuff_new();
            int i;
            xbt_strbuff_append(buff, e.bt_strings[1] + 8);
            for (i = 2; i < e.used; i++) {
              xbt_strbuff_append(buff, "\n");
              xbt_strbuff_append(buff, e.bt_strings[i] + 8);
            }
            show_string(buff->data);
            xbt_strbuff_free(buff);
          }
          xbt_ex_free(e);
        }
#else
        show_string("(no backtrace on this arch)");
#endif
        break;
      case 'd':                 /* date; LOG4J compliant */
        show_double(surf_get_clock());
        break;
      case 'r':                 /* application age; LOG4J compliant */
        show_double(surf_get_clock() - format_begin_of_time);
        break;
      case 'm': {               /* user-provided message; LOG4J compliant */
        int len, sz;
        set_sz_from_precision();
        len = vsnprintf(p, sz, msg_fmt, ev->ap);
        check_overflow(MIN(sz, len));
        break;
      }
      default:
        fprintf(stderr, ERRMSG, *q, (char *)l->data);
        xbt_abort();
      }
    } else {
      *p = *q;
      check_overflow(1);
    }
  }
  *p = '\0';

  return 1;
}
Example #19
0
int main(int argc, char **argv)
{
  int i;
  unsigned int ctr;
  const char *platform_file;
  const SD_workstation_t *workstations;
  const char *name1;
  const char *name2;
  double computation_amount1;
  double computation_amount2;
  double communication_amount12;
  double communication_amount21;
  const SD_link_t *route;
  int route_size;
  SD_task_t task, taskA, taskB, taskC, taskD, checkB, checkD;
  xbt_dynar_t changed_tasks;
  xbt_ex_t ex;
  const int workstation_number = 2;
  SD_workstation_t workstation_list[2];
  double computation_amount[2];
  double communication_amount[4] = { 0 };
  double rate = -1.0;
  SD_workstation_t w1, w2;

  /* initialization of SD */
  SD_init(&argc, argv);

  /*  xbt_log_control_set("sd.thres=debug"); */

  if (argc < 2) {
    XBT_INFO("Usage: %s platform_file", argv[0]);
    XBT_INFO("example: %s sd_platform.xml", argv[0]);
    exit(1);
  }

  /* creation of the environment */
  platform_file = argv[1];
  SD_create_environment(platform_file);

  /* test the estimation functions */
  workstations = SD_workstation_get_list();
  w1 = workstations[0];
  w2 = workstations[1];
  SD_workstation_set_access_mode(w2, SD_WORKSTATION_SEQUENTIAL_ACCESS);
  name1 = SD_workstation_get_name(w1);
  name2 = SD_workstation_get_name(w2);
  computation_amount1 = 2000000;
  computation_amount2 = 1000000;
  communication_amount12 = 2000000;
  communication_amount21 = 3000000;
  XBT_INFO("Computation time for %f flops on %s: %f", computation_amount1,
        name1, SD_workstation_get_computation_time(w1,
                                                   computation_amount1));
  XBT_INFO("Computation time for %f flops on %s: %f", computation_amount2,
        name2, SD_workstation_get_computation_time(w2,
                                                   computation_amount2));

  XBT_INFO("Route between %s and %s:", name1, name2);
  route = SD_route_get_list(w1, w2);
  route_size = SD_route_get_size(w1, w2);
  for (i = 0; i < route_size; i++) {
    XBT_INFO("   Link %s: latency = %f, bandwidth = %f",
          SD_link_get_name(route[i]),
          SD_link_get_current_latency(route[i]),
          SD_link_get_current_bandwidth(route[i]));
  }
  XBT_INFO("Route latency = %f, route bandwidth = %f",
        SD_route_get_current_latency(w1, w2),
        SD_route_get_current_bandwidth(w1, w2));
  XBT_INFO("Communication time for %f bytes between %s and %s: %f",
        communication_amount12, name1, name2,
        SD_route_get_communication_time(w1, w2, communication_amount12));
  XBT_INFO("Communication time for %f bytes between %s and %s: %f",
        communication_amount21, name2, name1,
        SD_route_get_communication_time(w2, w1, communication_amount21));

  /* creation of the tasks and their dependencies */
  taskA = SD_task_create("Task A", NULL, 10.0);
  taskB = SD_task_create("Task B", NULL, 40.0);
  taskC = SD_task_create("Task C", NULL, 30.0);
  taskD = SD_task_create("Task D", NULL, 60.0);

  /* try to attach and retrieve user data to a task */
  SD_task_set_data(taskA, (void*) &computation_amount1);
  if (computation_amount1 != (*((double*) SD_task_get_data(taskA))))
      XBT_ERROR("User data was corrupted by a simple set/get");

  SD_task_dependency_add(NULL, NULL, taskB, taskA);
  SD_task_dependency_add(NULL, NULL, taskC, taskA);
  SD_task_dependency_add(NULL, NULL, taskD, taskB);
  SD_task_dependency_add(NULL, NULL, taskD, taskC);
  /*  SD_task_dependency_add(NULL, NULL, taskA, taskD); /\* deadlock */



  TRY {
    SD_task_dependency_add(NULL, NULL, taskA, taskA);   /* shouldn't work and must raise an exception */
    xbt_die("Hey, I can add a dependency between Task A and Task A!");
  }
  CATCH(ex) {
    if (ex.category != arg_error)
      RETHROW;                  /* this is a serious error */
    xbt_ex_free(ex);
  }

  TRY {
    SD_task_dependency_add(NULL, NULL, taskB, taskA);   /* shouldn't work and must raise an exception */
    xbt_die("Oh oh, I can add an already existing dependency!");
  }
  CATCH(ex) {
    if (ex.category != arg_error)
      RETHROW;
    xbt_ex_free(ex);
  }

  TRY {
    SD_task_dependency_remove(taskA, taskC);    /* shouldn't work and must raise an exception */
    xbt_die("Dude, I can remove an unknown dependency!");
  }
  CATCH(ex) {
    if (ex.category != arg_error)
      RETHROW;
    xbt_ex_free(ex);
  }

  TRY {
    SD_task_dependency_remove(taskC, taskC);    /* shouldn't work and must raise an exception */
    xbt_die("Wow, I can remove a dependency between Task C and itself!");
  }
  CATCH(ex) {
    if (ex.category != arg_error)
      RETHROW;
    xbt_ex_free(ex);
  }


  /* if everything is ok, no exception is forwarded or rethrown by main() */

  /* watch points */
  SD_task_watch(taskD, SD_DONE);
  SD_task_watch(taskB, SD_DONE);
  SD_task_unwatch(taskD, SD_DONE);


  /* scheduling parameters */
  workstation_list[0] = w1;
  workstation_list[1] = w2;
  computation_amount[0] = computation_amount1;
  computation_amount[1] = computation_amount2;

  communication_amount[1] = communication_amount12;
  communication_amount[2] = communication_amount21;

  /* estimated time */
  task = taskD;
  XBT_INFO("Estimated time for '%s': %f", SD_task_get_name(task),
        SD_task_get_execution_time(task, workstation_number,
                                   workstation_list, computation_amount,
                                   communication_amount));

  /* let's launch the simulation! */

  SD_task_schedule(taskA, workstation_number, workstation_list,
                   computation_amount, communication_amount, rate);
  SD_task_schedule(taskB, workstation_number, workstation_list,
                   computation_amount, communication_amount, rate);
  SD_task_schedule(taskC, workstation_number, workstation_list,
                   computation_amount, communication_amount, rate);
  SD_task_schedule(taskD, workstation_number, workstation_list,
                   computation_amount, communication_amount, rate);

  changed_tasks = SD_simulate(-1.0);
  xbt_dynar_foreach(changed_tasks, ctr, task) {
    XBT_INFO("Task '%s' start time: %f, finish time: %f",
          SD_task_get_name(task),
          SD_task_get_start_time(task), SD_task_get_finish_time(task));
  }
Example #20
0
int main(int argc, char**argv)
{
  void *heapA;
  void *pointers[TESTSIZE];
  xbt_init(&argc,argv);

  XBT_INFO("Allocating a new heap");
  heapA = xbt_mheap_new(-1, ((char*)sbrk(0)) + BUFFSIZE);
  if (heapA == NULL) {
    perror("attach 1 failed");
    fprintf(stderr, "bye\n");
    exit(1);
  }

  XBT_INFO("HeapA allocated");

  int i, size;
  for (i = 0; i < TESTSIZE; i++) {
    size = size_of_block(i);
    pointers[i] = mmalloc(heapA, size);
    XBT_INFO("%d bytes allocated with offset %tx", size, ((char*)pointers[i])-((char*)heapA));
  }
  XBT_INFO("All blocks were correctly allocated. Free every second block");
  for (i = 0; i < TESTSIZE; i+=2) {
    size = size_of_block(i);
    mfree(heapA,pointers[i]);
  }
  XBT_INFO("Memset every second block to zero (yeah, they are not currently allocated :)");
  for (i = 0; i < TESTSIZE; i+=2) {
    size = size_of_block(i);
    memset(pointers[i],0, size);
  }
  XBT_INFO("Re-allocate every second block");
  for (i = 0; i < TESTSIZE; i+=2) {
    size = size_of_block(i);
    pointers[i] = mmalloc(heapA, size);
  }

  XBT_INFO("free all blocks (each one twice, to check that double free are correctly catched)");
  for (i = 0; i < TESTSIZE; i++) {
    xbt_ex_t e;
    int gotit = 1;

    mfree(heapA, pointers[i]);
    TRY {
      mfree(heapA, pointers[i]);
      gotit = 0;
    } CATCH(e) {
      xbt_ex_free(e);
    }
    if (!gotit)
      xbt_die("FAIL: A double-free went undetected (for size:%d)",size_of_block(i));
  }

  XBT_INFO("free again all blocks (to really check that double free are correctly catched)");
  for (i = 0; i < TESTSIZE; i++) {
    xbt_ex_t e;
    int gotit = 1;

    TRY {
      mfree(heapA, pointers[i]);
      gotit = 0;
    } CATCH(e) {
      xbt_ex_free(e);
    }
    if (!gotit)
      xbt_die("FAIL: A double-free went undetected (for size:%d)",size_of_block(i));
  }


  XBT_INFO("Damnit, I cannot break mmalloc this time. That's SO disappointing.");
  return 0;
}
Example #21
0
msg_error_t
MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
                             double timeout)
{
  msg_error_t ret = MSG_OK;
  simdata_task_t t_simdata = NULL;
  msg_process_t process = MSG_process_self();
  simdata_process_t p_simdata = SIMIX_process_self_get_data(process);

  int call_end = TRACE_msg_task_put_start(task);    //must be after CHECK_HOST()

  /* Prepare the task to send */
  t_simdata = task->simdata;
  t_simdata->sender = process;
  t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;

  if (t_simdata->isused != 0) {
    if (msg_global->debug_multiple_use){
      XBT_ERROR("This task is already used in there:");
      xbt_backtrace_display(t_simdata->isused);
      XBT_ERROR("And you try to reuse it from here:");
      xbt_backtrace_display_current();
    } else {
      xbt_assert(t_simdata->isused == 0,
                 "This task is still being used somewhere else. You cannot send it now. Go fix your code! (use --cfg=msg/debug_multiple_use:on to get the backtrace of the other process)");
    }
  }

  if (msg_global->debug_multiple_use)
    MSG_BT(t_simdata->isused, "Using Backtrace");
  else
    t_simdata->isused = (void*)1;
  t_simdata->comm = NULL;
  msg_global->sent_msg++;


  p_simdata->waiting_task = task;

  xbt_ex_t e;
  /* Try to send it by calling SIMIX network layer */
  TRY {
    smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simix call  */
    comm = simcall_comm_isend(SIMIX_process_self(), mailbox,t_simdata->bytes_amount,
                                  t_simdata->rate, task, sizeof(void *),
                                  NULL, NULL, NULL, task, 0);
    if (TRACE_is_enabled())
      simcall_set_category(comm, task->category);
     t_simdata->comm = comm;
     simcall_comm_wait(comm, timeout);
  }

  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      ret = MSG_HOST_FAILURE;
      break;
    case network_error:
      ret = MSG_TRANSFER_FAILURE;
      break;
    case timeout_error:
      ret = MSG_TIMEOUT;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);

    /* If the send failed, it is not used anymore */
    if (msg_global->debug_multiple_use && t_simdata->isused!=0)
      xbt_ex_free(*(xbt_ex_t*)t_simdata->isused);
    t_simdata->isused = 0;
  }


  p_simdata->waiting_task = NULL;
  if (call_end)
    TRACE_msg_task_put_end();
  MSG_RETURN(ret);
}
Example #22
0
/** \ingroup msg_task_usage
 * \brief Executes a parallel task and waits for its termination.
 *
 * \param task a #msg_task_t to execute on the location on which the process is running.
 *
 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
 * or #MSG_HOST_FAILURE otherwise
 */
msg_error_t MSG_parallel_task_execute(msg_task_t task)
{
  xbt_ex_t e;
  simdata_task_t simdata = task->simdata;
  msg_process_t self = SIMIX_process_self();
  simdata_process_t p_simdata = SIMIX_process_self_get_data(self);
  e_smx_state_t comp_state;
  msg_error_t status = MSG_OK;

#ifdef HAVE_TRACING
  TRACE_msg_task_execute_start(task);
#endif

  xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
             "This task is executed somewhere else. Go fix your code! %d",
             task->simdata->isused);

  XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));

  if (simdata->computation_amount == 0 && !simdata->host_nb) {
#ifdef HAVE_TRACING
    TRACE_msg_task_execute_end(task);
#endif
    return MSG_OK;
  }


  TRY {

    simdata->isused=1;

    if (simdata->host_nb > 0) {
      simdata->compute = simcall_host_parallel_execute(task->name,
                                                       simdata->host_nb,
                                                       simdata->host_list,
                                                       simdata->comp_amount,
                                                       simdata->comm_amount,
                                                       1.0, -1.0);
      XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
    } else {
      simdata->compute = simcall_host_execute(task->name,
                                              p_simdata->m_host,
                                              simdata->computation_amount,
                                              simdata->priority);

    }
#ifdef HAVE_TRACING
    simcall_set_category(simdata->compute, task->category);
#endif
    p_simdata->waiting_action = simdata->compute;
    comp_state = simcall_host_execution_wait(simdata->compute);

    p_simdata->waiting_action = NULL;

    simdata->isused=0;

    XBT_DEBUG("Execution task '%s' finished in state %d",
              task->name, (int)comp_state);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      status = MSG_TASK_CANCELED;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }
  /* action ended, set comm and compute = NULL, the actions is already destroyed
   * in the main function */
  simdata->computation_amount = 0.0;
  simdata->comm = NULL;
  simdata->compute = NULL;
#ifdef HAVE_TRACING
  TRACE_msg_task_execute_end(task);
#endif

  MSG_RETURN(status);
}
Example #23
0
static void xbt_log_layout_format_doit(xbt_log_layout_t l,
                                       xbt_log_event_t ev,
                                       const char *msg_fmt,
                                       xbt_log_appender_t app)
{
  char *p, *q;
  char tmpfmt[50];
  int precision = -1;
  int length = -1;


  p = ev->buffer;
  q = l->data;

  while (*q != '\0') {
    if (*q == '%') {
      q++;
    handle_modifier:
      switch (*q) {
      case '\0':
        fprintf(stderr, "Layout format (%s) ending with %%\n",
                (char *) l->data);
        abort();
      case '%':
        *p++ = '%';
        break;
      case 'n':                /* platform-dependant line separator (LOG4J compliant) */
        p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "\n");
        check_overflow;
        break;
      case 'e':                /* plain space (SimGrid extension) */
        p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), " ");
        check_overflow;
        break;

      case '.':                /* precision specifyier */
        q++;
        sscanf(q, "%d", &precision);
        q += (precision>9?2:1);
        goto handle_modifier;

      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9': /* length modifier */
        sscanf(q, "%d", &length);
        q += (length>9?2:1);
        goto handle_modifier;

      case 'c':                /* category name; LOG4J compliant
                                   should accept a precision postfix to show the hierarchy */
        show_string(ev->cat->name);
        break;
      case 'p':                /* priority name; LOG4J compliant */
        show_string(xbt_log_priority_names[ev->priority]);
        break;

      case 'h':                /* host name; SimGrid extension */
        show_string(gras_os_myname());
        break;
      case 't':                /* thread name; LOG4J compliant */
        show_string(xbt_thread_self_name());
        break;
      case 'P':                /* process name; SimGrid extension */
        show_string(xbt_procname());
        break;
      case 'i':                /* process PID name; SimGrid extension */
        show_int((*xbt_getpid) ());
        break;

      case 'F':                /* file name; LOG4J compliant */
        show_string(ev->fileName);
        break;
      case 'l':                /* location; LOG4J compliant */
        if (precision == -1) {
          p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s:%d",
                        ev->fileName, ev->lineNum);
          check_overflow;
        } else {
          p += snprintf(p,
                        (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
                                  precision), "%s:%d", ev->fileName,
                        ev->lineNum);
          check_overflow;
          precision = -1;
        }
        break;
      case 'L':                /* line number; LOG4J compliant */
        show_int(ev->lineNum);
        break;
      case 'M':                /* method (ie, function) name; LOG4J compliant */
        show_string(ev->functionName);
        break;
      case 'b':                /* backtrace; called %throwable in LOG4J */
      case 'B':                /* short backtrace; called %throwable{short} in LOG4J */
#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
        {
          xbt_ex_t e;
          int i;

          e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
          e.bt_strings = NULL;
          e.msg = NULL;
          e.remote = 0;
          xbt_backtrace_current(&e);
          if (*q == 'B') {
            show_string(e.bt_strings[2] + 8);
          } else {
            for (i = 2; i < e.used; i++)
              if (precision == -1) {
                p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
                              "%s\n", e.bt_strings[i] + 8);
                check_overflow;
              } else {
                p += sprintf(p, "%.*s\n",
                             (int) MIN(XBT_LOG_BUFF_SIZE -
                                       (p - ev->buffer), precision),
                             e.bt_strings[i] + 8);
                check_overflow;
                precision = -1;
              }
          }

          xbt_ex_free(e);
        }
#else
        p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
                      "(no backtrace on this arch)");
        check_overflow;
#endif
        break;

      case 'd':                /* date; LOG4J compliant */
        show_double(gras_os_time());
        break;
      case 'r':                /* application age; LOG4J compliant */
        show_double(gras_os_time() - format_begin_of_time);
        break;

      case 'm':                /* user-provided message; LOG4J compliant */
        if (precision == -1) {
          p += vsnprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), msg_fmt,
                         ev->ap);
          check_overflow;
        } else {
          p += vsnprintf(p,
                         (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
                                   precision), msg_fmt, ev->ap);
          check_overflow;
          precision = -1;
        }
        break;

      default:
        fprintf(stderr, ERRMSG, *q, (char *) l->data);
        abort();
      }
      q++;
    } else {
      *(p++) = *(q++);
      check_overflow;
    }
  }
  *p = '\0';
  app->do_append(app, ev->buffer);
}
Example #24
0
msg_error_t
MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
                             double timeout)
{
  xbt_ex_t e;
  msg_error_t ret = MSG_OK;
  simdata_task_t t_simdata = NULL;
  msg_process_t process = MSG_process_self();
  simdata_process_t p_simdata = SIMIX_process_self_get_data(process);

#ifdef HAVE_TRACING
  int call_end = TRACE_msg_task_put_start(task);    //must be after CHECK_HOST()
#endif

  /* Prepare the task to send */
  t_simdata = task->simdata;
  t_simdata->sender = process;
  t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;

  xbt_assert(t_simdata->isused == 0,
              "This task is still being used somewhere else. You cannot send it now. Go fix your code!");

  t_simdata->isused=1;
  t_simdata->comm = NULL;
  msg_global->sent_msg++;


  p_simdata->waiting_task = task;

  /* Try to send it by calling SIMIX network layer */
  TRY {
      smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
                                  t_simdata->rate, task, sizeof(void *),
                                  NULL, NULL, task, 0);
#ifdef HAVE_TRACING
    if (TRACE_is_enabled()) {
      simcall_set_category(comm, task->category);
    }
#endif
     t_simdata->comm = comm;
     simcall_comm_wait(comm, timeout);
  }

  CATCH(e) {
    switch (e.category) {
    case network_error:
      ret = MSG_TRANSFER_FAILURE;
      break;
    case timeout_error:
      ret = MSG_TIMEOUT;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);

    /* If the send failed, it is not used anymore */
    t_simdata->isused = 0;
  }


  p_simdata->waiting_task = NULL;
#ifdef HAVE_TRACING
  if (call_end)
    TRACE_msg_task_put_end();
#endif
  MSG_RETURN(ret);
}
Example #25
0
/** \ingroup msg_task_usage
 * \brief Executes a parallel task and waits for its termination.
 *
 * \param task a #msg_task_t to execute on the location on which the process is running.
 *
 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
 * or #MSG_HOST_FAILURE otherwise
 */
msg_error_t MSG_parallel_task_execute(msg_task_t task)
{
  xbt_ex_t e;
  simdata_task_t simdata = task->simdata;
  msg_process_t self = SIMIX_process_self();
  simdata_process_t p_simdata = SIMIX_process_self_get_data(self);
  e_smx_state_t comp_state;
  msg_error_t status = MSG_OK;

  TRACE_msg_task_execute_start(task);

  xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
             "This task is executed somewhere else. Go fix your code! %d",
             task->simdata->isused!=NULL);

  XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));

  if (simdata->flops_amount == 0 && !simdata->host_nb) {
    TRACE_msg_task_execute_end(task);
    return MSG_OK;
  }


  TRY {
    if (msg_global->debug_multiple_use)
      MSG_BT(simdata->isused, "Using Backtrace");
    else
      simdata->isused = (void*)1;

    if (simdata->host_nb > 0) {
      simdata->compute = simcall_process_parallel_execute(task->name,
                                                       simdata->host_nb,
                                                       simdata->host_list,
                                                       simdata->flops_parallel_amount,
                                                       simdata->bytes_parallel_amount,
                                                       1.0, -1.0);
      XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
    } else {
      unsigned long affinity_mask = (unsigned long) xbt_dict_get_or_null_ext(simdata->affinity_mask_db, (char *) p_simdata->m_host, sizeof(msg_host_t));
      XBT_DEBUG("execute %s@%s with affinity(0x%04lx)", MSG_task_get_name(task), MSG_host_get_name(p_simdata->m_host), affinity_mask);

      simdata->compute = simcall_process_execute(task->name,
                                              simdata->flops_amount,
                                              simdata->priority,
                                              simdata->bound,
                                              affinity_mask
                                              );

    }
    simcall_set_category(simdata->compute, task->category);
    p_simdata->waiting_action = simdata->compute;
    comp_state = simcall_process_execution_wait(simdata->compute);

    p_simdata->waiting_action = NULL;

    if (msg_global->debug_multiple_use && simdata->isused!=0)
      xbt_ex_free(*(xbt_ex_t*)simdata->isused);
    simdata->isused = 0;

    XBT_DEBUG("Execution task '%s' finished in state %d",
              task->name, (int)comp_state);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      status = MSG_TASK_CANCELED;
      break;
    case host_error:
      status = MSG_HOST_FAILURE;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }
  /* action ended, set comm and compute = NULL, the actions is already destroyed
   * in the main function */
  simdata->flops_amount = 0.0;
  simdata->comm = NULL;
  simdata->compute = NULL;
  TRACE_msg_task_execute_end(task);

  MSG_RETURN(status);
}
Example #26
0
int client(int argc, char *argv[])
{
  xbt_ex_t e;
  gras_socket_t toserver = NULL;        /* peer */
  int connected = 0;

  gras_socket_t from;
  int ping, pong;

  const char *host = "127.0.0.1";
  int port = 4000;

  /* 1. Init the GRAS's infrastructure */
  gras_init(&argc, argv);

  /* 2. Get the server's address. The command line override defaults when specified */
  if (argc == 3) {
    host = argv[1];
    port = atoi(argv[2]);
  }

  XBT_INFO("Launch client (server on %s:%d)", host, port);

  /* 3. Create a socket to speak to the server */
  while (!connected) {
    TRY {
      toserver = gras_socket_client(host, port);
      connected = 1;
    }
    CATCH(e) {
      if (e.category != system_error)
        /* dunno what happened, let the exception go through */
        RETHROWF("Unable to connect to the server: %s");
      xbt_ex_free(e);
      gras_os_sleep(0.05);
    }
  }

  XBT_INFO("Connected to %s:%d.", host, port);

  /* 4. Register the messages.
     See, it doesn't have to be done completely at the beginning, only before use */
  ping_register_messages();

  /* 5. Keep the user informed of what's going on */
  XBT_INFO(">>>>>>>> Connected to server which is on %s:%d <<<<<<<<",
        gras_socket_peer_name(toserver), gras_socket_peer_port(toserver));

  /* 6. Prepare and send the ping message to the server */
  ping = 1234;
  TRY {
    gras_msg_send(toserver, "ping", &ping);
  }
  CATCH(e) {
    gras_socket_close(toserver);
    RETHROWF("Failed to send PING to server: %s");
  }
  XBT_INFO(">>>>>>>> Message PING(%d) sent to %s:%d <<<<<<<<",
        ping,
        gras_socket_peer_name(toserver), gras_socket_peer_port(toserver));

  /* 7. Wait for the answer from the server, and deal with issues */
  TRY {
    gras_msg_wait(6000, "pong", &from, &pong);
  }
  CATCH(e) {
    gras_socket_close(toserver);
    RETHROWF("Why can't I get my PONG message like everyone else: %s");
  }

  /* 8. Keep the user informed of what's going on, again */
  XBT_INFO(">>>>>>>> Got PONG(%d) from %s:%d <<<<<<<<",
        pong, gras_socket_peer_name(from), gras_socket_peer_port(from));

  /* 9. Free the allocated resources, and shut GRAS down */
  gras_socket_close(toserver);
  XBT_INFO("Done.");
  gras_exit();
  return 0;
}                               /* end_of_client */
Example #27
0
static void xbt_log_layout_format_dynamic(xbt_log_layout_t l,
                                          xbt_log_event_t ev,
                                          const char *fmt,
                                          xbt_log_appender_t app)
{
  xbt_strbuff_t buff = xbt_strbuff_new();
  char tmpfmt[50];
  int precision = -1;
  int length = -1;
  char *q = l->data;
  char *tmp;
  char *tmp2;

  while (*q != '\0') {
    if (*q == '%') {
      q++;
    handle_modifier:
      switch (*q) {
      case '\0':
        fprintf(stderr, "Layout format (%s) ending with %%\n",
                (char *) l->data);
        abort();
      case '%':
        xbt_strbuff_append(buff, "%");
        break;
      case 'n':                /* platform-dependant line separator (LOG4J compliant) */
        xbt_strbuff_append(buff, "\n");
        break;
      case 'e':                /* plain space (SimGrid extension) */
        xbt_strbuff_append(buff, " ");
        break;

      case '.':                /* precision specifyier */
        q++;
        sscanf(q, "%d", &precision);
        q += (precision>9?2:1);
        goto handle_modifier;

      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9': /* length modifier */
        sscanf(q, "%d", &length);
        q += (length>9?2:1);
        goto handle_modifier;

      case 'c':                /* category name; LOG4J compliant
                                   should accept a precision postfix to show the hierarchy */
        append_string(ev->cat->name);
        break;
      case 'p':                /* priority name; LOG4J compliant */
        append_string(xbt_log_priority_names[ev->priority]);
        break;

      case 'h':                /* host name; SimGrid extension */
        append_string(gras_os_myname());
        break;
      case 't':                /* thread name; LOG4J compliant */
        append_string(xbt_thread_self_name());
        break;
      case 'P':                /* process name; SimGrid extension */
        append_string(xbt_procname());
        break;
      case 'i':                /* process PID name; SimGrid extension */
        append_int((*xbt_getpid) ());
        break;

      case 'F':                /* file name; LOG4J compliant */
        append_string(ev->fileName);
        break;
      case 'l':                /* location; LOG4J compliant */
        append2("%s:%d", ev->fileName, ev->lineNum);
        precision = -1;         /* Ignored */
        break;
      case 'L':                /* line number; LOG4J compliant */
        append_int(ev->lineNum);
        break;
      case 'M':                /* method (ie, function) name; LOG4J compliant */
        append_string(ev->functionName);
        break;
      case 'b':                /* backtrace; called %throwable in LOG4J */
      case 'B':                /* short backtrace; called %throwable{short} in LOG4J */
#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
        {
          xbt_ex_t e;
          int i;

          e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
          e.bt_strings = NULL;
          e.msg = NULL;
          e.remote = 0;
          xbt_backtrace_current(&e);
          if (*q == 'B') {
            append_string(e.bt_strings[2] + 8);
          } else {
            for (i = 2; i < e.used; i++) {
              append_string(e.bt_strings[i] + 8);
              xbt_strbuff_append(buff, "\n");
            }
          }

          xbt_ex_free(e);
        }
#else
        append_string("(no backtrace on this arch)");
#endif
        break;

      case 'd':                /* date; LOG4J compliant */
        append_double(gras_os_time());
        break;
      case 'r':                /* application age; LOG4J compliant */
        append_double(gras_os_time() - format_begin_of_time);
        break;

      case 'm':                /* user-provided message; LOG4J compliant */
        tmp2 = bvprintf(fmt, ev->ap_copy);
        append_string(tmp2);
        free(tmp2);
        break;

      default:
        fprintf(stderr, ERRMSG, *q, (char *) l->data);
        abort();
      }
      q++;
    } else {
      char tmp2[2];
      tmp2[0] = *(q++);
      tmp2[1] = '\0';
      xbt_strbuff_append(buff, tmp2);
    }
  }
  app->do_append(app, buff->data);
  xbt_strbuff_free(buff);
}