ADD_TEST(tesh-simdag-par-2 ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite --cd ${CMAKE_BINARY_DIR}/teshsuite ${CMAKE_HOME_DIRECTORY}/teshsuite/simdag/partask/test_comp_only_par.tesh)
# MSG examples
+ADD_TEST(msg-file ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/ --setenv srcdir=${CMAKE_HOME_DIRECTORY}/ --cd ${CMAKE_HOME_DIRECTORY}/examples/ ${CMAKE_HOME_DIRECTORY}/examples/msg/io/io.tesh)
+
ADD_TEST(msg-sendrecv-CLM03-thread ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_CLM03.tesh)
ADD_TEST(msg-sendrecv-Vegas-thread ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Vegas.tesh)
ADD_TEST(msg-sendrecv-Reno-thread ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Reno.tesh)
a look at the following presentation first to get the basic concepts.
Afterward, you probably want to proceed to the \ref MSG_API. Of
course, if you're curious or if you know what you want, you may prefer
-to go to \ref SMPI_API, or even \ref GRAS_API.
+to go to \ref SMPI_API, or even \ref GRAS_API.
+
+The scientific bases of the SimGrid project are presented in a 3 ou 4
+hours-long tutorial. It can be found at the following locations.
+ - https://gforge.inria.fr/plugins/scmgit/cgi-bin/gitweb.cgi?p=simgrid/propaganda.git;a=blob_plain;f=tutorial/simgrid-tutorial.pdf;hb=HEAD
+ - http://webloria.loria.fr/~quinson/blog/2010/0628/Tutorial_at_HPCS/
\latexonly
\includepdf[nup=2x4,pages=1-]{../webcruft/simgrid-101.pdf}
--- /dev/null
+#! ./tesh
+
+$ ${bindir:=.}/io/file ${srcdir:=.}/examples/platforms/storage.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
+> [ 0.000000] (0:@) Configuration change: Set 'path' to '../examples/platforms/'
+> [ 0.000000] (0:@) Create resource with Bconnection '6000000000' Bread '100000000' Bwrite '30000000'
+> [ 0.000000] (0:@) Create resource with Bconnection '6000000000' Bread '100000000' Bwrite '30000000'
+> [ 0.000000] (0:@) Create resource with Bconnection '6000000000' Bread '100000000' Bwrite '30000000'
+> [ 0.000000] (0:@) Create resource with Bconnection '6000000000' Bread '100000000' Bwrite '30000000'
+> [ 0.000000] (0:@) Number of host '4'
+> [ 0.000000] (1:0@denise) Open file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml'
+> [ 0.000000] (2:1@alice) Open file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml'
+> [ 0.000000] (3:2@carl) Open file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml'
+> [ 0.000000] (4:3@bob) Open file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml'
+> [ 0.000005] (2:1@alice) Having read 482 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml
+> [ 0.000040] (4:3@bob) Having read 4028 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml
+> [ 0.000170] (1:0@denise) Having read 17028 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml
+> [ 0.000226] (3:2@carl) Having read 22645 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml
+> [ 0.003338] (2:1@alice) Having write 100000 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml
+> [ 0.003374] (4:3@bob) Having write 100000 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml
+> [ 0.003504] (1:0@denise) Having write 100000 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml
+> [ 0.003560] (3:2@carl) Having write 100000 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml
+> [ 0.004343] (2:1@alice) Having read 100482 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml
+> [ 0.004343] (2:1@alice) File /home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml Size 100482
+> [ 0.004343] (2:1@alice) Close file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/One_cluster_no_backbone.xml'
+> [ 0.004414] (4:3@bob) Having read 104028 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml
+> [ 0.004414] (4:3@bob) File /home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml Size 104028
+> [ 0.004414] (4:3@bob) Close file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/nancy.xml'
+> [ 0.004674] (1:0@denise) Having read 117028 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml
+> [ 0.004674] (1:0@denise) File /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml Size 117028
+> [ 0.004674] (1:0@denise) Close file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k.xml'
+> [ 0.004786] (3:2@carl) Having read 122645 on /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml
+> [ 0.004786] (3:2@carl) File /home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml Size 122645
+> [ 0.004786] (3:2@carl) Close file '/home/user/Install/simgrid/doc/simgrid/examples/platforms/g5k_cabinets.xml'
+> [ 0.004786] (0:@) Simulation time 0.00478623
\ No newline at end of file
static int slave(int argc, char *argv[])
{
XBT_INFO("Hello!");
- XBT_INFO("Suspend process");
+ XBT_INFO("Suspending myself");
MSG_process_suspend(MSG_process_self());
+ XBT_INFO("OK, OK. Let's work");
MSG_task_execute(MSG_task_create("toto", 1e9, 0, NULL));
XBT_INFO("Bye!");
return 0;
p Testing a simple master/slave example application
-$ $SG_TEST_EXENV masterslave/masterslave_kill$EXEEXT ${srcdir:=.}/masterslave/platform_kill.xml ${srcdir:=.}/masterslave/deployment_masterslave_kill.xml
+$ $SG_TEST_EXENV masterslave/masterslave_kill$EXEEXT ${srcdir:=.}/masterslave/platform_kill.xml ${srcdir:=.}/masterslave/deployment_masterslave_kill.xml --log=surf_maxmin.thres:error
> [alice:master:(1) 0.000000] [msg_test/INFO] Hello!
> [bob:slave:(2) 0.000000] [msg_test/INFO] Hello!
-> [bob:slave:(2) 0.000000] [msg_test/INFO] Suspend process
+> [bob:slave:(2) 0.000000] [msg_test/INFO] Suspending myself
> [alice:master:(1) 10.000000] [msg_test/INFO] Resume process
+> [bob:slave:(2) 10.000000] [msg_test/INFO] OK, OK. Let's work
> [alice:master:(1) 10.000000] [msg_test/INFO] Kill process
> [alice:master:(1) 10.000000] [msg_test/INFO] OK, goodbye now.
> [10.000000] [msg_test/INFO] Simulation time 10
\ No newline at end of file
XBT_PUBLIC(void) TRACE_link_srcdst_variable_add_with_time (double time, const char *src, const char *dst, const char *variable, double value);
XBT_PUBLIC(void) TRACE_link_srcdst_variable_sub_with_time (double time, const char *src, const char *dst, const char *variable, double value);
XBT_PUBLIC(xbt_dynar_t) TRACE_get_link_variables (void);
+XBT_PUBLIC(void) TRACE_host_state_declare (const char *state);
+XBT_PUBLIC(void) TRACE_host_state_declare_value (const char *state, const char *value, const char *color);
+XBT_PUBLIC(void) TRACE_host_set_state (const char *host, const char *state, const char *value);
+XBT_PUBLIC(void) TRACE_host_push_state (const char *host, const char *state, const char *value);
+XBT_PUBLIC(void) TRACE_host_pop_state (const char *host, const char *state);
/* for creating graph configuration files for Triva by hand */
XBT_PUBLIC(xbt_dynar_t) TRACE_get_node_types (void);
XBT_PUBLIC(int) xbt_dynar_member(xbt_dynar_t const dynar, void *elem);
XBT_PUBLIC(void) xbt_dynar_sort(xbt_dynar_t const dynar,
int_f_cpvoid_cpvoid_t compar_fn);
+XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar,
+ int_f_pvoid_t color);
XBT_PUBLIC(int) xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2,
int(*compar)(const void *, const void *));
XBT_PUBLIC(void *) xbt_dynar_to_array (xbt_dynar_t dynar);
typedef void (*void_f_void_t) (void);
typedef int (*int_f_void_t) (void);
+typedef int (*int_f_pvoid_t) (void*);
typedef int (*int_f_pvoid_pvoid_t) (void *, void *);
typedef int (*int_f_cpvoid_cpvoid_t) (const void *, const void *);
return instr_dict_to_dynar (user_link_variables);
}
+/** \ingroup TRACE_user_variables
+ * \brief Declare a new user state associated to hosts.
+ *
+ * Declare a user state that will be associated to hosts.
+ * A user host state can be used to trace application states.
+ *
+ * \param state The name of the new state to be declared.
+ *
+ * \see TRACE_host_state_declare_value
+ */
+void TRACE_host_state_declare (const char *state)
+{
+ instr_new_user_state_type("HOST", state);
+}
+
+/** \ingroup TRACE_user_variables
+ * \brief Declare a new value for a user state associated to hosts.
+ *
+ * Declare a value for a state. The color needs to be
+ * a string with three numbers separated by spaces in the range [0,1].
+ * A light-gray color can be specified using "0.7 0.7 0.7" as color.
+ *
+ * \param state The name of the new state to be declared.
+ * \param value The name of the value
+ * \param color The color of the value
+ *
+ * \see TRACE_host_state_declare
+ */
+void TRACE_host_state_declare_value (const char *state, const char *value, const char *color)
+{
+ instr_new_value_for_user_state_type (state, value, color);
+}
+
+/** \ingroup TRACE_user_variables
+ * \brief Set the user state to the given value.
+ *
+ * Change a user state previously declared to the given value.
+ *
+ * \param host The name of the host to be considered.
+ * \param state The name of the state previously declared.
+ * \param value The new value of the state.
+ *
+ * \see TRACE_host_state_declare, TRACE_host_push_state, TRACE_host_pop_state
+ */
+void TRACE_host_set_state (const char *host, const char *state, const char *value)
+{
+ container_t container = PJ_container_get(host);
+ type_t type = PJ_type_get (state, container->type);
+ val_t val = PJ_value_get (value, type);
+ if (val == NULL){
+ //if user didn't declare a value with a color, user a NULL color
+ PJ_value_new (value, NULL, type);
+ }
+ new_pajeSetState(MSG_get_clock(), container, type, val);
+}
+
+/** \ingroup TRACE_user_variables
+ * \brief Push a new value for a state of a given host.
+ *
+ * Change a user state previously declared by pushing the new value to the state.
+ *
+ * \param host The name of the host to be considered.
+ * \param state The name of the state previously declared.
+ * \param value The value to be pushed.
+ *
+ * \see TRACE_host_state_declare, TRACE_host_set_state, TRACE_host_pop_state
+ */
+void TRACE_host_push_state (const char *host, const char *state, const char *value)
+{
+ container_t container = PJ_container_get(host);
+ type_t type = PJ_type_get (state, container->type);
+ val_t val = PJ_value_get (value, type);
+ if (val == NULL){
+ //if user didn't declare a value with a color, user a NULL color
+ PJ_value_new (value, NULL, type);
+ }
+ new_pajePushState(MSG_get_clock(), container, type, val);
+}
+
+/** \ingroup TRACE_user_variables
+ * \brief Pop the last value of a state of a given host.
+ *
+ * Change a user state previously declared by removing the last value of the state.
+ *
+ * \param host The name of the host to be considered.
+ * \param state The name of the state to be popped.
+ *
+ * \see TRACE_host_state_declare, TRACE_host_set_state, TRACE_host_push_state
+ */
+void TRACE_host_pop_state (const char *host, const char *state)
+{
+ container_t container = PJ_container_get(host);
+ type_t type = PJ_type_get (state, container->type);
+ new_pajePopState(MSG_get_clock(), container, type);
+}
+
/** \ingroup TRACE_API
* \brief Get Paje container types that can be mapped to the nodes of a graph.
*
void instr_routing_define_callbacks (void);
void instr_new_variable_type (const char *new_typename, const char *color);
void instr_new_user_variable_type (const char *father_type, const char *new_typename, const char *color);
+void instr_new_user_state_type (const char *father_type, const char *new_typename);
+void instr_new_value_for_user_state_type (const char *typename, const char *value, const char *color);
int instr_platform_traced (void);
xbt_graph_t instr_routing_platform_graph (void);
void instr_routing_platform_graph_export_graphviz (xbt_graph_t g, const char *filename);
recursiveNewUserVariableType (father_type, new_typename, color, PJ_type_get_root());
}
+static void recursiveNewUserStateType (const char *father_type, const char *new_typename, type_t root)
+{
+ if (!strcmp (root->name, father_type)){
+ PJ_type_state_new (new_typename, root);
+ }
+ xbt_dict_cursor_t cursor = NULL;
+ type_t child_type;
+ char *name;
+ xbt_dict_foreach(root->children, cursor, name, child_type) {
+ recursiveNewUserStateType (father_type, new_typename, child_type);
+ }
+}
+
+void instr_new_user_state_type (const char *father_type, const char *new_typename)
+{
+ recursiveNewUserStateType (father_type, new_typename, PJ_type_get_root());
+}
+static void recursiveNewValueForUserStateType (const char *typename, const char *value, const char *color, type_t root)
+{
+ if (!strcmp (root->name, typename)){
+ PJ_value_new (value, color, root);
+ }
+ xbt_dict_cursor_t cursor = NULL;
+ type_t child_type;
+ char *name;
+ xbt_dict_foreach(root->children, cursor, name, child_type) {
+ recursiveNewValueForUserStateType (typename, value, color, child_type);
+ }
+}
+
+void instr_new_value_for_user_state_type (const char *typename, const char *value, const char *color)
+{
+ recursiveNewValueForUserStateType (typename, value, color, PJ_type_get_root());
+}
int instr_platform_traced ()
{
TRACE_msg_process_kill(process);
#endif
- /* FIXME: why do we only cancel communication actions? is this useful? */
- simdata_process_t p_simdata = simcall_process_get_data(process);
- if (p_simdata->waiting_task && p_simdata->waiting_task->simdata->comm) {
- simcall_comm_cancel(p_simdata->waiting_task->simdata->comm);
- }
+// /* FIXME: why do we only cancel communication actions? is this useful? */
+// simdata_process_t p_simdata = simcall_process_get_data(process);
+// if (p_simdata->waiting_task && p_simdata->waiting_task->simdata->comm) {
+// simcall_comm_cancel(p_simdata->waiting_task->simdata->comm);
+// }
simcall_process_kill(process);
}
}
+int process_syscall_color(void *p) {
+ e_smx_simcall_t s = (*((smx_process_t *)p))->simcall.call;
+
+ if (s == SIMCALL_NONE || s == SIMCALL_PROCESS_KILL) return 2;
+ else if (s == SIMCALL_PROCESS_RESUME) return 1;
+ else return 0;
+}
+
void SIMIX_run(void)
{
double time = 0;
XBT_DEBUG("New Sub-Schedule Round; size(queue)=%lu",
xbt_dynar_length(simix_global->process_to_run));
SIMIX_process_runall();
+ xbt_dynar_three_way_partition(simix_global->process_that_ran, process_syscall_color);
xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
if (process->simcall.call != SIMCALL_NONE) {
SIMIX_simcall_pre(&process->simcall, 0);
void SIMIX_host_execution_resume(smx_action_t action)
{
if(action->execution.surf_exec)
- surf_workstation_model->suspend(action->execution.surf_exec);
+ surf_workstation_model->resume(action->execution.surf_exec);
}
void SIMIX_execution_finish(smx_action_t action)
}
}
+int process_syscall_color(void *p);
+
void SIMIX_context_mod_init(void);
void SIMIX_context_mod_exit(void);
xbt_swag_remove(process, simix_global->process_list);
xbt_swag_remove(process, process->smx_host->process_list);
xbt_swag_insert(process, simix_global->process_to_destroy);
+ process->context->iwannadie = 0;
}
/**
break;
}
}
-
- xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+ if(!xbt_dynar_member(simix_global->process_to_run, &(process)))
+ xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
/**
{
xbt_assert((process != NULL), "Invalid parameters");
- if (!process->suspended) {
- XBT_DEBUG("Process '%s' is not suspended", process->name);
- return;
- }
-
- process->suspended = 0;
+ if(process->context->iwannadie) return;
+ process->suspended = 0;
/* If we are resuming another process, resume the action it was waiting for
if any. Otherwise add it to the list of process to run in the next round. */
}
}
else {
- xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+ if(!xbt_dynar_member(simix_global->process_to_run, &(process)))
+ xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
}
}
XBT_DEBUG("Answer simcall %s (%d) issued by %s (%p)", SIMIX_simcall_name(simcall->call), (int)simcall->call,
simcall->issuer->name, simcall->issuer);
simcall->issuer->simcall.call = SIMCALL_NONE;
- xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, simcall->issuer);
+ if(!xbt_dynar_member(simix_global->process_to_run, &(simcall->issuer)))
+ xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, simcall->issuer);
+ else
+ DIE_IMPOSSIBLE;
}
}
#include "smx_private.h"
#include "mc/mc.h"
+#include "xbt/ex.h"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
smx_mutex_t mutex,
double timeout)
{
+ xbt_ex_t e;
+
xbt_assert(isfinite(timeout), "timeout is not finite!");
smx_simcall_t simcall = SIMIX_simcall_mine();
simcall->cond_wait_timeout.mutex = mutex;
simcall->cond_wait_timeout.timeout = timeout;
- SIMIX_simcall_push(simcall->issuer);
+ TRY {
+ SIMIX_simcall_push(simcall->issuer);
+ }
+ CATCH(e) {
+ switch (e.category) {
+ case timeout_error:
+ simcall->issuer->waiting_action = NULL; // FIXME: should clean ?
+ break;
+ default:
+ break;
+ }
+ RETHROW;
+ xbt_ex_free(e);
+ }
}
void simcall_cond_broadcast(smx_cond_t cond)
xbt_swag_insert_at_head(var, &(sys->variable_set));
else
xbt_swag_insert_at_tail(var, &(sys->variable_set));
- XBT_OUT();
+
+ XBT_LOG(xbt_log_priority_trace, "<< end of %s returns %p", _XBT_FUNCTION, var);
return var;
}
_dynar_unlock(dynar);
}
+/** @brief Sorts a dynar according to their color assuming elements can have only three colors.
+ * Since there are only three colors, it is linear and much faster than a classical sort.
+ * See for example http://en.wikipedia.org/wiki/Dutch_national_flag_problem
+ *
+ * \param dynar the dynar to sort
+ * \param color the color function of type (int (compar_fn*) (void*) (void*)). The return value of color is assumed to be 0, 1, or 2.
+ *
+ * At the end of the call, elements with color 0 are at the beginning of the dynar, elements with color 2 are at the end and elements with color 1 are in the middle.
+ *
+ * Remark: if the elements stored in the dynar are structures, the color
+ * function has to retrieve the field to sort first.
+ */
+XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar,
+ int_f_pvoid_t color)
+{
+ _dynar_lock(dynar);
+ unsigned long size = xbt_dynar_length(dynar);
+ void *data = dynar->data;
+ unsigned long int i;
+ unsigned long int p = -1;
+ unsigned long int q = size;
+ unsigned long elmsize = dynar->elmsize;
+ void *tmp = xbt_malloc(elmsize);
+
+#define swap(a,b) do { \
+ memcpy(tmp, a , elmsize); \
+ memcpy( a , b , elmsize); \
+ memcpy( b , tmp, elmsize); \
+ } while(0)
+
+ for (i = 0; i < q;) {
+ unsigned long int datai = ((unsigned long int) data) + i*elmsize;
+ int colori = color((void *) datai);
+
+ if(colori==0) {
+ unsigned long int datap = ((unsigned long int) data) + (++p)*elmsize;
+ swap((void *) datai, (void *) datap);
+ ++i;
+ } else if (colori==2) {
+ unsigned long int dataq = ((unsigned long int) data) + (--q)*elmsize;
+ swap((void *) datai, (void *) dataq);
+ } else {
+ ++i;
+ }
+ }
+ _dynar_unlock(dynar);
+}
+
/** @brief Transform a dynar into a NULL terminated array
*
* \param dynar the dynar to transform
if (field->offset[GRAS_THISARCH]<= offset&&
field->offset[GRAS_THISARCH]+field->type->size[GRAS_THISARCH] >= offset) {
found = 1;
- printf("This offset is somewhere in field %s, which starts at offset %zu and is of size %zu\n",
+ printf("This offset is somewhere in field %s, which starts at offset %ld and is of size %ld\n",
field->name,field->offset[GRAS_THISARCH],field->type->size[GRAS_THISARCH]);
}
}
if (!found) {
- printf("Damnit, the structure is too short to find the the field (last field %s was at offset %zu, with size %zu). Weird.\n",
+ printf("Damnit, the structure is too short to find the the field (last field %s was at offset %ld, with size %ld). Weird.\n",
field->name,field->offset[GRAS_THISARCH],field->type->size[GRAS_THISARCH]);
}
}