CHECK_FUNCTION_EXISTS(vasprintf HAVE_VASPRINTF)
CHECK_FUNCTION_EXISTS(makecontext HAVE_MAKECONTEXT)
CHECK_FUNCTION_EXISTS(mmap HAVE_MMAP)
+CHECK_FUNCTION_EXISTS(process_vm_readv HAVE_PROCESS_VM_READV)
#Check if __thread is defined
execute_process(
)
set(MC_SRC
+ src/mc/mc_address_space.h
+ src/mc/mc_address_space.c
src/mc/mc_forward.h
+ src/mc/mc_process.h
+ src/mc/mc_process.c
+ src/mc/mc_unw.h
+ src/mc/mc_unw.c
+ src/mc/mc_unw_vmread.c
src/mc/mc_mmalloc.h
src/mc/mc_model_checker.h
+ src/mc/mc_model_checker.c
src/mc/mc_object_info.h
+ src/mc/mc_object_info.c
src/mc/mc_checkpoint.c
src/mc/mc_snapshot.h
src/mc/mc_snapshot.c
src/mc/mc_visited.c
src/mc/mc_memory_map.h
src/mc/memory_map.c
+ src/mc/mc_client.c
+ src/mc/mc_client_api.c
+ src/mc/mc_client.h
+ src/mc/mc_protocol.h
+ src/mc/mc_protocol.c
+ src/mc/mc_server.cpp
+ src/mc/mc_server.h
)
+set(MC_SIMGRID_MC_SRC
+ src/mc/simgrid_mc.cpp)
+
set(headers_to_install
include/instr/instr.h
include/msg/datatypes.h
${LUA_SRC}
${MC_SRC_BASE}
${MC_SRC}
+ ${MC_SIMGRID_MC_SRC}
${MSG_SRC}
${NS3_SRC}
${RNGSTREAM_SRC}
set(warnCFLAGS "")
set(optCFLAGS "")
+include(CheckCXXCompilerFlag)
+
+if(NOT __VISUALC__ AND NOT __BORLANDC__)
+ CHECK_CXX_COMPILER_FLAG("-std=c++11" HAVE_CXX11)
+ CHECK_CXX_COMPILER_FLAG("-std=c++0x" HAVE_CXX0X)
+ if(HAVE_CXX11)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ elseif(HAVE_CXX0X)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ else()
+ message(STATUS "Missing support for C++11.")
+ endif()
+endif()
+
if(NOT __VISUALC__ AND NOT __BORLANDC__)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}-std=gnu99 -g3")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}-g3")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -g3")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}/Zi")
set(optCFLAGS "-O0 ")
# But you can still optimize this:
foreach(s
- # src/xbt/mmalloc/mm.c
- # src/xbt/snprintf.c src/xbt/log.c
- # src/xbt/dynar.c
- # src/xbt/set.c src/xbt/setset.c
- # src/xbt/backtrace_linux.c
- src/mc/mc_dwarf_expression.c src/mc/mc_dwarf.c src/mc/mc_member.c
- src/mc/mc_snapshot.c src/mc/mc_page_store.cpp src/mc/mc_page_snapshot.cpp
- src/mc/mc_compare.cpp src/mc/mc_diff.c
- src/mc/mc_dwarf.c src/mc/mc_dwarf_attrnames.h src/mc/mc_dwarf_expression.c src/mc/mc_dwarf_tagnames.h
- src/mc/mc_set.cpp)
+ src/xbt/mmalloc/mm.c
+ src/xbt/log.c src/xbt/xbt_log_appender_file.c
+ src/xbt/xbt_log_layout_format.c src/xbt/xbt_log_layout_simple.c
+ src/xbt/dict.c src/xbt/dict_elm.c src/xbt/dict_multi.c src/xbt/dict_cursor.c
+ src/xbt/set.c src/xbt/setset.c
+ src/xbt/dynar.c src/xbt/fifo.c src/xbt/heap.c src/xbt/swag.c
+ src/xbt/str.c src/xbt/strbuff.c src/xbt/snprintf.c
+ src/xbt/queue.c
+ src/xbt/xbt_os_time.c src/xbt/xbt_os_thread.c
+ src/xbt/sha.c
+ src/xbt/matrix.c
+ src/xbt/backtrace_linux.c
+ ${MC_SRC_BASE} ${MC_SRC})
set (mcCFLAGS "-O3 -funroll-loops -fno-strict-aliasing")
if(CMAKE_COMPILER_IS_GNUCC)
set (mcCFLAGS "${mcCFLAGS} -finline-functions")
add_dependencies(simgrid maintainer_files)
+if(enable_model-checking)
+ add_executable(simgrid-mc ${MC_SIMGRID_MC_SRC})
+ target_link_libraries(simgrid-mc simgrid)
+ set_target_properties(simgrid-mc
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+endif()
+
# Compute the dependencies of SimGrid
#####################################
set(SIMGRID_DEP "-lm")
# The availability of libunwind was checked in CompleteInFiles.cmake
# (that includes FindLibunwind.cmake), so simply load it now.
- SET(SIMGRID_DEP "${SIMGRID_DEP} -lunwind")
+ SET(SIMGRID_DEP "${SIMGRID_DEP} -lunwind -lunwind-ptrace")
# Same for libdw
SET(SIMGRID_DEP "${SIMGRID_DEP} -ldw")
message("HAVE_ASPRINTF ...............: ${HAVE_ASPRINTF}")
message("HAVE_VASPRINTF ..............: ${HAVE_VASPRINTF}")
message("HAVE_MMAP ...................: ${HAVE_MMAP}")
+ message("HAVE_PROCESS_VM_READV .......: ${HAVE_PROCESS_VM_READV}")
message("HAVE_THREAD_LOCAL_STORAGE ...: ${HAVE_THREAD_LOCAL_STORAGE}")
message("HAVE_MMALLOC ................: ${HAVE_MMALLOC}")
message("")
/* Define to 1 if mmap is available */
#cmakedefine HAVE_MMAP @HAVE_MMAP@
+/* Define to 1 if process_vm_readv is available */
+#cmakedefine HAVE_PROCESS_VM_READV @HAVE_PROCESS_VM_READV@
+
/* Define to 1 if you have the `getdtablesize' function. */
#cmakedefine HAVE_GETDTABLESIZE @HAVE_GETDTABLESIZE@
! expect signal SIGABRT
! timeout 20
-$ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check a safety property
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@HostB) Sent!
> [ 0.000000] (3:client@HostC) Sent!
> [ 0.000000] (1:server@HostA) OK
> [ 0.000000] (1:server@HostA) Expanded states = 22
> [ 0.000000] (1:server@HostA) Visited states = 56
> [ 0.000000] (1:server@HostA) Executed transitions = 52
-
int r=0;
int cs=0;
-int predR(){
- return r;
-}
-
-int predCS(){
- return cs;
-}
-
#ifdef GARBAGE_STACK
/** Do not use a clean stack */
static void garbage_stack(void) {
char **options = &argv[1];
MSG_config("model-check/property","promela_bugged1_liveness");
- MC_automaton_new_propositional_symbol("r", &predR);
- MC_automaton_new_propositional_symbol("cs", &predCS);
+ MC_automaton_new_propositional_symbol_pointer("r", &r);
+ MC_automaton_new_propositional_symbol_pointer("cs", &cs);
const char* platform_file = options[0];
const char* application_file = options[1];
! expect signal SIGABRT
! timeout 20
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check the liveness property promela_bugged1_liveness
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@Boivin) Ask the request
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (2:client@Boivin) Propositions changed : r=1, cs=0
! expect signal SIGABRT
! timeout 60
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/sparse-checkpoint' to 'yes'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
> [ 0.000000] (0:@) Check the liveness property promela_bugged1_liveness
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@Boivin) Ask the request
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (2:client@Boivin) Propositions changed : r=1, cs=0
! expect signal SIGABRT
! timeout 90
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/visited' to '100'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check the liveness property promela_bugged1_liveness
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@Boivin) Ask the request
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
! expect signal SIGABRT
! timeout 90
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/visited' to '100'
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/sparse-checkpoint' to 'yes'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
> [ 0.000000] (0:@) Check the liveness property promela_bugged1_liveness
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@Boivin) Ask the request
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
! expect signal SIGABRT
! timeout 20
-$ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check a safety property
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@HostB) Send 1!
> [ 0.000000] (3:client@HostC) Send 2!
> [ 0.000000] (1:server@HostA) Received 1
> [ 0.000000] (1:server@HostA) Expanded states = 461
> [ 0.000000] (1:server@HostA) Visited states = 2271
> [ 0.000000] (1:server@HostA) Executed transitions = 2117
-
int cs = 0;
-int predCS(){
- return cs;
-}
-
-
int coordinator(int argc, char **argv);
int client(int argc, char **argv);
MSG_init(&argc, argv);
MSG_config("model-check/property","promela_bugged2_liveness");
- MC_automaton_new_propositional_symbol("cs", &predCS);
+ MC_automaton_new_propositional_symbol_pointer("cs", &cs);
MSG_create_environment("../msg_platform.xml");
MSG_function_register("coordinator", coordinator);
int r, cs;
-static int predR(){
- return r;
-}
-
-static int predCS(){
- return cs;
-}
-
-
int main(int argc, char **argv){
int err, size, rank;
exit(1);
}
- MC_automaton_new_propositional_symbol("r", &predR);
- MC_automaton_new_propositional_symbol("cs", &predCS);
+ MC_automaton_new_propositional_symbol_pointer("r", &r);
+ MC_automaton_new_propositional_symbol_pointer("cs", &cs);
MC_ignore(&(status.count), sizeof(status.count));
#! ./tesh
! timeout 60
-$ ../../../smpi_script/bin/smpirun -hostfile ${srcdir:=.}/hostfile_non_deterministic -platform ${srcdir:=.}/../../platforms/cluster.xml --cfg=model-check:1 --cfg=model-check/communications_determinism:1 --cfg=smpi/send_is_detached_thres:0 --cfg=smpi/running_power:1e9 ./smpi_non_deterministic
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check/communications_determinism' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/send_is_detached_thres' to '0'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
+$ ../../../smpi_script/bin/smpirun -wrapper ${bindir:=.}/../../../bin/simgrid-mc -hostfile ${srcdir:=.}/hostfile_non_deterministic -platform ${srcdir:=.}/../../platforms/cluster.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 --cfg=model-check/communications_determinism:1 --cfg=smpi/send_is_detached_thres:0 --cfg=smpi/running_power:1e9 ./smpi_non_deterministic
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check communication determinism
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> [0.000000] [mc_comm_determinism/INFO] The communications pattern of the process 1 is different! (Different communication : 1)
> [0.000000] [mc_comm_determinism/INFO] ****************************************************
> [0.000000] [mc_comm_determinism/INFO] ***** Non-deterministic communications pattern *****
#! ./tesh
! timeout 60
-$ ../../../smpi_script/bin/smpirun -hostfile ${srcdir:=.}/hostfile_send_deterministic -platform ${srcdir:=.}/../../platforms/cluster.xml --cfg=model-check:1 --cfg=model-check/send_determinism:1 --cfg=smpi/send_is_detached_thres:0 --cfg=smpi/running_power:1e9 ./smpi_send_deterministic
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check/send_determinism' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/send_is_detached_thres' to '0'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
+$ ../../../smpi_script/bin/smpirun -wrapper "${bindir:=.}/../../../bin/simgrid-mc" -hostfile ${srcdir:=.}/hostfile_send_deterministic -platform ${srcdir:=.}/../../platforms/cluster.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 --cfg=model-check/send_determinism:1 --cfg=smpi/send_is_detached_thres:0 --cfg=smpi/running_power:1e9 ./smpi_send_deterministic
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check communication determinism
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> [0.000000] [mc_global/INFO] Expanded states = 520
> [0.000000] [mc_global/INFO] Visited states = 1476
> [0.000000] [mc_global/INFO] Executed transitions = 1312
SG_BEGIN_DECL()
+/** Replay path (if any) in string representation
+ *
+ * This is a path as generated by `MC_record_stack_to_string()`.
+ */
+XBT_PUBLIC_DATA(char*) MC_record_path;
+
+/** Whether the replay mode is enabled */
+static inline bool MC_record_replay_is_active(void) {
+ return MC_record_path;
+}
+
XBT_PUBLIC(int) MC_random(int min, int max);
#ifdef HAVE_MC
#define MC_visited_reduction() _sg_mc_visited
XBT_PUBLIC(void) MC_assert(int);
-XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, void* fct);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, int(*fct)(void));
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_pointer(const char *id, int* value);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_callback(const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
XBT_PUBLIC(void *) MC_snapshot(void);
XBT_PUBLIC(int) MC_compare_snapshots(void *s1, void *s2);
XBT_PUBLIC(void) MC_cut(void);
#define MC_assert(a) xbt_assert(a)
#define MC_automaton_new_propositional_symbol(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_pointer(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_callback(id,callback,data,free_function) \
+ if(free_function) free_function(data);
#define MC_snapshot() ((void*)0)
#define MC_compare_snapshots(a, b) 0
#define MC_cut() ((void)0)
#endif
-/** Replay path (if any) in string representation
- *
- * This is a path as generated by `MC_record_stack_to_string()`.
- */
-XBT_PUBLIC_DATA(char*) MC_record_path;
-
-/** Whether the replay mode is enabled */
-static inline bool MC_record_replay_is_active(void) {
- return MC_record_path;
-}
-
SG_END_DECL()
#endif /* SIMGRID_MODELCHECKER_H */
typedef struct xbt_automaton_transition* xbt_automaton_transition_t;
-typedef struct xbt_automaton_propositional_symbol{
- char* pred;
- void* function;
-} s_xbt_automaton_propositional_symbol;
-
+typedef struct xbt_automaton_propositional_symbol s_xbt_automaton_propositional_symbol;
typedef struct xbt_automaton_propositional_symbol* xbt_automaton_propositional_symbol_t;
+typedef int (*xbt_automaton_propositional_symbol_callback_type)(void*);
+typedef void (*xbt_automaton_propositional_symbol_free_function_type)(void*);
XBT_PUBLIC(xbt_automaton_t) xbt_automaton_new(void);
XBT_PUBLIC(void) xbt_automaton_exp_label_display(xbt_automaton_exp_label_t l);
-XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct);
+// xbt_automaton_propositional_symbol constructors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void));
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value);
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+ xbt_automaton_t a, const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
+
+// xbt_automaton_propositional_symbol accessors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol);
+
+// xbt_automaton_propositional_symbol methods!
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol);
XBT_PUBLIC(xbt_automaton_state_t) xbt_automaton_get_current_state(xbt_automaton_t a);
XBT_PUBLIC( xbt_mheap_t ) mmalloc_get_default_md(void);
/* To change the heap used when using the legacy version malloc/free/realloc and such */
-void mmalloc_set_current_heap(xbt_mheap_t new_heap);
+xbt_mheap_t mmalloc_set_current_heap(xbt_mheap_t new_heap);
xbt_mheap_t mmalloc_get_current_heap(void);
struct s_mc_snapshot;
int mmalloc_compare_heap(struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2);
int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2);
int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t to_ignore1, xbt_dynar_t to_ignore2);
-int compare_heap_area(int process_index, void *area1, void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
+int compare_heap_area(int process_index, const void *area1, const void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
void reset_heap_information(void);
size_t mmalloc_get_bytes_used(xbt_mheap_t);
ssize_t mmalloc_get_busy_size(xbt_mheap_t, void *ptr);
+void* malloc_no_memset(size_t n);
+
SG_END_DECL()
#endif
#ifndef MC_DATATYPE_H
#define MC_DATATYPE_H
-#define UNW_LOCAL_ONLY
-
#include "xbt/misc.h"
#include "xbt/swag.h"
#include "xbt/fifo.h"
typedef struct s_stack_region{
void *address;
- char *process_name;
void *context;
size_t size;
int block;
extern int _sg_mc_send_determinism;
extern int _sg_mc_safety;
extern int _sg_mc_liveness;
+extern int _sg_mc_snapshot_fds;
extern xbt_dynar_t mc_heap_comparison_ignore;
extern xbt_dynar_t stacks_areas;
-extern void *maestro_stack_start;
-extern void *maestro_stack_end;
/********************************* Global *************************************/
void _mc_cfg_cb_reduce(const char *name, int pos);
void _mc_cfg_cb_property(const char *name, int pos);
void _mc_cfg_cb_timeout(const char *name, int pos);
void _mc_cfg_cb_hash(const char *name, int pos);
+void _mc_cfg_cb_snapshot_fds(const char *name, int pos);
void _mc_cfg_cb_max_depth(const char *name, int pos);
void _mc_cfg_cb_visited(const char *name, int pos);
void _mc_cfg_cb_dot_output(const char *name, int pos);
/********************************* Memory *************************************/
XBT_PUBLIC(void) MC_memory_init(void); /* Initialize the memory subsystem */
XBT_PUBLIC(void) MC_memory_exit(void);
+XBT_PUBLIC(void) MC_memory_init_server(void);
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "mc_address_space.h"
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_ADDRESS_SPACE_H
+#define MC_ADDRESS_SPACE_H
+
+#include <stdint.h>
+
+#include "mc_forward.h"
+
+// ***** Data types
+
+typedef enum e_adress_space_read_flags {
+ MC_ADDRESS_SPACE_READ_FLAGS_NONE = 0,
+
+ /** Avoid a copy for when the data is available in the current process.
+ *
+ * In this case, the return value of a MC_address_space_read might
+ * be different from the provided buffer.
+ */
+ MC_ADDRESS_SPACE_READ_FLAGS_LAZY = 1
+} e_adress_space_read_flags_t;
+
+/** Process index used when no process is available
+ *
+ * The expected behaviour is that if a process index is needed it will fail.
+ * */
+#define MC_PROCESS_INDEX_MISSING -1
+
+#define MC_PROCESS_INDEX_DISABLED -2
+
+/** Process index when any process is suitable
+ *
+ * We could use a special negative value in the future.
+ */
+#define MC_PROCESS_INDEX_ANY 0
+
+// ***** Class definition
+
+typedef struct s_mc_address_space s_mc_address_space_t, *mc_address_space_t;
+typedef struct s_mc_address_space_class s_mc_address_space_class_t, *mc_address_space_class_t;
+
+/** Abstract base class for an address space
+ *
+ * This is the base class for all virtual address spaces (process, snapshot).
+ * It uses dynamic dispatch based on a vtable (`address_space_class`).
+ */
+struct s_mc_address_space {
+ const s_mc_address_space_class_t* address_space_class;
+};
+
+/** Class object (vtable) for the virtual address spaces
+ */
+struct s_mc_address_space_class {
+ const void* (*read)(
+ mc_address_space_t address_space, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size,
+ int process_index);
+ mc_process_t (*get_process)(mc_address_space_t address_space);
+};
+
+// ***** Virtual/non-final methods
+
+/** Read data from the given address space
+ *
+ * Dynamic dispatch.
+ */
+static inline __attribute__((always_inline))
+const void* MC_address_space_read(
+ mc_address_space_t address_space, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size,
+ int process_index)
+{
+ return address_space->address_space_class->read(
+ address_space, flags, target, addr, size,
+ process_index);
+}
+
+static inline __attribute__((always_inline))
+const void* MC_address_space_get_process(mc_address_space_t address_space)
+{
+ return address_space->address_space_class->get_process(address_space);
+}
+
+
+#endif
#include "../simix/smx_private.h"
#include "mc_record.h"
+#ifdef HAVE_MC
+#include "mc_process.h"
+#include "mc_model_checker.h"
+#endif
+
XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
-/**
- * \brief Schedules all the process that are ready to run
- */
void MC_wait_for_requests(void)
{
smx_process_t process;
SG_BEGIN_DECL()
+/** Check if the given simcall can be resolved
+ *
+ * \return `TRUE` or `FALSE`
+ */
int MC_request_is_enabled(smx_simcall_t req);
+
+/** Check if the given simcall is visible
+ *
+ * \return `TRUE` or `FALSE`
+ */
int MC_request_is_visible(smx_simcall_t req);
+
+/** Execute everything which is invisible
+ *
+ * Execute all the processes that are ready to run and all invisible simcalls
+ * iteratively until there doesn't remain any. At this point, the function
+ * returns to the caller which can handle the visible (and ready) simcalls.
+ */
void MC_wait_for_requests(void);
extern double *mc_time;
* under the terms of the license (GNU LGPL) which comes with this package. */
#define _GNU_SOURCE
-#define UNW_LOCAL_ONLY
#include <unistd.h>
#include "../simix/smx_private.h"
-#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <libelf.h>
#include "mc_snapshot.h"
#include "mc_object_info.h"
#include "mc_mmu.h"
+#include "mc_unw.h"
+#include "mc_protocol.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc,
"Logging specific to mc_checkpoint");
-char *libsimgrid_path;
-
/************************************ Free functions **************************************/
/*****************************************************************************************/
if (s) {
xbt_dynar_free(&(s->local_variables));
xbt_dynar_free(&(s->stack_frames));
+ mc_unw_destroy_context(s->context);
+ xbt_free(s->context);
xbt_free(s);
}
}
static void MC_snapshot_stack_free_voidp(void *s)
{
- MC_snapshot_stack_free((mc_snapshot_stack_t) * (void **) s);
+ mc_snapshot_stack_t stack = (mc_snapshot_stack_t) * (void **) s;
+ MC_snapshot_stack_free(stack);
}
static void local_variable_free(local_variable_t v)
local_variable_free((local_variable_t) * (void **) v);
}
-void MC_region_destroy(mc_mem_region_t reg)
+void MC_region_destroy(mc_mem_region_t region)
{
- if (!reg)
+ if (!region)
return;
-
- //munmap(reg->data, reg->size);
- xbt_free(reg->data);
- if (reg->page_numbers) {
- mc_free_page_snapshot_region(reg->page_numbers, mc_page_count(reg->size));
+ switch(region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ break;
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ xbt_free(region->flat.data);
+ break;
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
+ mc_free_page_snapshot_region(region->chunked.page_numbers, mc_page_count(region->size));
+ xbt_free(region->chunked.page_numbers);
+ break;
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ {
+ size_t regions_count = region->privatized.regions_count;
+ for (size_t i=0; i!=regions_count; ++i) {
+ MC_region_destroy(region->privatized.regions[i]);
+ }
+ free(region->privatized.regions);
+ break;
+ }
}
- xbt_free(reg);
+ xbt_free(region);
}
void MC_free_snapshot(mc_snapshot_t snapshot)
{
- unsigned int i;
- for (i = 0; i < NB_REGIONS; i++) {
- MC_region_destroy(snapshot->regions[i]);
+ for (size_t i = 0; i < snapshot->snapshot_regions_count; i++) {
+ MC_region_destroy(snapshot->snapshot_regions[i]);
}
-
+ xbt_free(snapshot->snapshot_regions);
xbt_free(snapshot->stack_sizes);
xbt_dynar_free(&(snapshot->stacks));
xbt_dynar_free(&(snapshot->to_ignore));
xbt_dynar_free(&snapshot->ignored_data);
-
- if (snapshot->privatization_regions) {
- size_t n = xbt_dynar_length(snapshot->enabled_processes);
- for (i = 0; i != n; ++i) {
- MC_region_destroy(snapshot->privatization_regions[i]);
- }
- xbt_free(snapshot->privatization_regions);
- }
-
xbt_free(snapshot);
}
/******************************* Snapshot regions ********************************/
/*********************************************************************************/
-static mc_mem_region_t mc_region_new_dense(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+static mc_mem_region_t mc_region_new_dense(
+ mc_region_type_t region_type,
+ void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
{
- mc_mem_region_t new_reg = xbt_new(s_mc_mem_region_t, 1);
- new_reg->start_addr = start_addr;
- new_reg->permanent_addr = permanent_addr;
- new_reg->data = NULL;
- new_reg->size = size;
- new_reg->page_numbers = NULL;
- new_reg->data = xbt_malloc(size);
- memcpy(new_reg->data, permanent_addr, size);
+ mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ region->region_type = region_type;
+ region->storage_type = MC_REGION_STORAGE_TYPE_FLAT;
+ region->start_addr = start_addr;
+ region->permanent_addr = permanent_addr;
+ region->size = size;
+ region->flat.data = xbt_malloc(size);
+ MC_process_read(&mc_model_checker->process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ region->flat.data, permanent_addr, size,
+ MC_PROCESS_INDEX_DISABLED);
XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu",
- type, new_reg->data, permanent_addr, size);
- return new_reg;
-
+ region_type, region->flat.data, permanent_addr, size);
+ return region;
}
/** @brief Take a snapshot of a given region
* @param size Size of the data*
* @param ref_reg Reference corresponding region
*/
-static mc_mem_region_t MC_region_new(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+static mc_mem_region_t MC_region_new(mc_region_type_t type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
{
if (_sg_mc_sparse_checkpoint) {
return mc_region_new_sparse(type, start_addr, permanent_addr, size, ref_reg);
* @param reg Target region
* @param reg_reg Current region (if not NULL), used for lazy per page restoration
*/
-static void MC_region_restore(mc_mem_region_t reg, mc_mem_region_t ref_reg)
+static void MC_region_restore(mc_mem_region_t region, mc_mem_region_t ref_region)
{
- /*FIXME: check if start_addr is still mapped, if it is not, then map it
- before copying the data */
- if (!reg->page_numbers) {
- memcpy(reg->permanent_addr, reg->data, reg->size);
- } else {
- mc_region_restore_sparse(reg, ref_reg);
+ switch(region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ default:
+ xbt_die("Storage type not supported");
+ break;
+
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ MC_process_write(&mc_model_checker->process, region->flat.data,
+ region->permanent_addr, region->size);
+ break;
+
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
+ mc_region_restore_sparse(&mc_model_checker->process, region, ref_region);
+ break;
+
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ {
+ bool has_ref_regions = ref_region &&
+ ref_region->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED;
+ size_t process_count = region->privatized.regions_count;
+ for (size_t i = 0; i < process_count; i++) {
+ MC_region_restore(region->privatized.regions[i],
+ has_ref_regions ? ref_region->privatized.regions[i] : NULL);
+ }
+ break;
+ }
}
- return;
}
-static void MC_snapshot_add_region(mc_snapshot_t snapshot, int type,
- void *start_addr, void* permanent_addr, size_t size)
+// FIXME, multiple privatisation regions
+// FIXME, cross-process
+static inline
+void* MC_privatization_address(mc_process_t process, int process_index)
+{
+ xbt_assert(process_index >= 0);
+ return smpi_privatisation_regions[process_index].address;
+}
+
+static mc_mem_region_t MC_region_new_privatized(
+ mc_region_type_t region_type, void *start_addr, void* permanent_addr, size_t size,
+ mc_mem_region_t ref_reg)
+{
+ size_t process_count = smpi_process_count();
+ mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ region->region_type = region_type;
+ region->storage_type = MC_REGION_STORAGE_TYPE_PRIVATIZED;
+ region->start_addr = start_addr;
+ region->permanent_addr = permanent_addr;
+ region->size = size;
+ region->privatized.regions_count = process_count;
+ region->privatized.regions = xbt_new(mc_mem_region_t, process_count);
+
+ for (size_t i = 0; i < process_count; i++) {
+ mc_mem_region_t ref_subreg = NULL;
+ if (ref_reg && ref_reg->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED)
+ ref_subreg = ref_reg->privatized.regions[i];
+ region->privatized.regions[i] =
+ MC_region_new(region_type, start_addr,
+ MC_privatization_address(&mc_model_checker->process, i), size,
+ ref_subreg);
+ }
+
+ return region;
+}
+static void MC_snapshot_add_region(int index, mc_snapshot_t snapshot, mc_region_type_t type,
+ mc_object_info_t object_info,
+ void *start_addr, void* permanent_addr, size_t size)
{
- mc_mem_region_t ref_reg =
- mc_model_checker->parent_snapshot ? mc_model_checker->parent_snapshot->regions[type] : NULL;
- mc_mem_region_t new_reg = MC_region_new(type, start_addr, permanent_addr, size, ref_reg);
- snapshot->regions[type] = new_reg;
+ if (type == MC_REGION_TYPE_DATA)
+ xbt_assert(object_info, "Missing object info for object.");
+ else if (type == MC_REGION_TYPE_HEAP)
+ xbt_assert(!object_info, "Unexpected object info for heap region.");
+
+ mc_mem_region_t ref_reg = NULL;
+ if (mc_model_checker->parent_snapshot)
+ ref_reg = mc_model_checker->parent_snapshot->snapshot_regions[index];
+
+ mc_mem_region_t region;
+ const bool privatization_aware = MC_object_info_is_privatized(object_info);
+ if (privatization_aware && smpi_process_count())
+ region = MC_region_new_privatized(type, start_addr, permanent_addr, size, ref_reg);
+ else
+ region = MC_region_new(type, start_addr, permanent_addr, size, ref_reg);
+
+ region->object_info = object_info;
+ snapshot->snapshot_regions[index] = region;
return;
}
-static void MC_get_memory_regions(mc_snapshot_t snapshot)
+static void MC_get_memory_regions(mc_process_t process, mc_snapshot_t snapshot)
{
+ const size_t n = process->object_infos_size;
+ snapshot->snapshot_regions_count = n + 1;
+ snapshot->snapshot_regions = xbt_new0(mc_mem_region_t, n + 1);
+
+ for (size_t i = 0; i!=n; ++i) {
+ mc_object_info_t object_info = process->object_infos[i];
+ MC_snapshot_add_region(i, snapshot, MC_REGION_TYPE_DATA, object_info,
+ object_info->start_rw, object_info->start_rw,
+ object_info->end_rw - object_info->start_rw);
+ }
- void *start_heap = std_heap->base;
- void *end_heap = std_heap->breakval;
- MC_snapshot_add_region(snapshot, 0, start_heap, start_heap,
- (char *) end_heap - (char *) start_heap);
- snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
- snapshot->privatization_regions = NULL;
+ xbt_mheap_t heap = MC_process_get_heap(process);
+ void *start_heap = heap->base;
+ void *end_heap = heap->breakval;
- MC_snapshot_add_region(snapshot, 1,
- mc_libsimgrid_info->start_rw, mc_libsimgrid_info->start_rw,
- mc_libsimgrid_info->end_rw - mc_libsimgrid_info->start_rw);
+ MC_snapshot_add_region(n, snapshot, MC_REGION_TYPE_HEAP, NULL,
+ start_heap, start_heap,
+ (char *) end_heap - (char *) start_heap);
+ snapshot->heap_bytes_used = mmalloc_get_bytes_used_remote(
+ heap->heaplimit,
+ MC_process_get_malloc_info(process));
#ifdef HAVE_SMPI
- size_t i;
if (smpi_privatize_global_variables && smpi_process_count()) {
- // Snapshot the global variable of the application separately for each
- // simulated process:
- snapshot->privatization_regions =
- xbt_new(mc_mem_region_t, smpi_process_count());
- for (i = 0; i < smpi_process_count(); i++) {
- mc_mem_region_t ref_reg =
- mc_model_checker->parent_snapshot ? mc_model_checker->parent_snapshot->privatization_regions[i] : NULL;
- snapshot->privatization_regions[i] =
- MC_region_new(-1, mc_binary_info->start_rw, smpi_privatisation_regions[i].address, size_data_exe, ref_reg);
- }
+ // FIXME, cross-process
snapshot->privatization_index = smpi_loaded_page;
- snapshot->regions[2] = NULL;
} else
#endif
{
- MC_snapshot_add_region(snapshot, 2,
- mc_binary_info->start_rw, mc_binary_info->start_rw,
- mc_binary_info->end_rw - mc_binary_info->start_rw);
- snapshot->privatization_regions = NULL;
- snapshot->privatization_index = -1;
- }
-}
-
-/** @brief Finds the range of the different memory segments and binary paths */
-void MC_init_memory_map_info()
-{
-
- unsigned int i = 0;
- s_map_region_t reg;
- memory_map_t maps = MC_get_memory_map();
-
- maestro_stack_start = NULL;
- maestro_stack_end = NULL;
- libsimgrid_path = NULL;
-
- while (i < maps->mapsize) {
- reg = maps->regions[i];
- if (maps->regions[i].pathname == NULL) {
- // Nothing to do
- } else if ((reg.prot & PROT_WRITE)
- && !memcmp(maps->regions[i].pathname, "[stack]", 7)) {
- maestro_stack_start = reg.start_addr;
- maestro_stack_end = reg.end_addr;
- } else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)
- && !memcmp(basename(maps->regions[i].pathname), "libsimgrid",
- 10)) {
- if (libsimgrid_path == NULL)
- libsimgrid_path = strdup(maps->regions[i].pathname);
- }
- i++;
+ snapshot->privatization_index = MC_PROCESS_INDEX_MISSING;
}
-
- xbt_assert(maestro_stack_start, "maestro_stack_start");
- xbt_assert(maestro_stack_end, "maestro_stack_end");
- xbt_assert(libsimgrid_path, "libsimgrid_path&");
-
- MC_free_memory_map(maps);
-
}
/** \brief Fills the position of the segments (executable, read-only, read/write).
*
- * TODO, use dl_iterate_phdr to be more robust
+ * `dl_iterate_phdr` would be more robust but would not work in cross-process.
* */
void MC_find_object_address(memory_map_t maps, mc_object_info_t result)
{
-
unsigned int i = 0;
s_map_region_t reg;
const char *name = basename(result->file_name);
i++;
}
+ result->start = result->start_rw;
+ if ((const void*) result->start_ro > result->start)
+ result->start = result->start_ro;
+ if ((const void*) result->start_exec > result->start)
+ result->start = result->start_exec;
+
+ result->end = result->end_rw;
+ if (result->end_ro && (const void*) result->end_ro < result->end)
+ result->end = result->end_ro;
+ if (result->end_exec && (const void*) result->end_exec > result->end)
+ result->end = result->end_exec;
+
xbt_assert(result->file_name);
xbt_assert(result->start_rw);
xbt_assert(result->start_exec);
static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
dw_frame_t scope, int process_index, xbt_dynar_t result)
{
+ mc_process_t process = &mc_model_checker->process;
+
void *ip = (void *) stack_frame->ip;
if (ip < scope->low_pc || ip >= scope->high_pc)
return;
continue;
int region_type;
- if ((long) stack_frame->ip > (long) mc_libsimgrid_info->start_exec)
+ // FIXME, get rid of `region_type`
+ if ((long) stack_frame->ip > (long) process->libsimgrid_info->start_exec)
region_type = 1;
else
region_type = 2;
new_var->address = current_variable->address;
} else if (current_variable->locations.size != 0) {
s_mc_location_t location;
+ // FIXME, cross-process support
mc_dwarf_resolve_locations(&location, ¤t_variable->locations,
current_variable->object_info,
&(stack_frame->unw_cursor),
}
}
-static xbt_dynar_t MC_unwind_stack_frames(void *stack_context)
+static xbt_dynar_t MC_unwind_stack_frames(mc_unw_context_t stack_context)
{
+ mc_process_t process = &mc_model_checker->process;
xbt_dynar_t result =
xbt_dynar_new(sizeof(mc_stack_frame_t), MC_stack_frame_free_voipd);
unw_cursor_t c;
// TODO, check condition check (unw_init_local==0 means end of frame)
- if (unw_init_local(&c, (unw_context_t *) stack_context) != 0) {
+ if (mc_unw_init_cursor(&c, stack_context) != 0) {
xbt_die("Could not initialize stack unwinding");
// TODO, use real addresses in frame_t instead of fixing it here
- dw_frame_t frame = MC_find_function_by_ip((void *) ip);
+ dw_frame_t frame = MC_process_find_function(process, (void *) ip);
stack_frame->frame = frame;
if (frame) {
&& !strcmp(frame->name, "smx_ctx_sysv_wrapper"))
break;
- int ret = ret = unw_step(&c);
+ int ret = unw_step(&c);
if (ret == 0) {
xbt_die("Unexpected end of stack.");
} else if (ret < 0) {
- xbt_die("Error while unwinding stack.");
+ xbt_die("Error while unwinding stack");
}
}
unsigned int cursor = 0;
stack_region_t current_stack;
+ // FIXME, cross-process support (stack_areas)
xbt_dynar_foreach(stacks_areas, cursor, current_stack) {
mc_snapshot_stack_t st = xbt_new(s_mc_snapshot_stack_t, 1);
- st->stack_frames = MC_unwind_stack_frames(current_stack->context);
+
+ unw_context_t* original_context = (unw_context_t*) current_stack->context;
+
+ st->context = xbt_new0(s_mc_unw_context_t, 1);
+ if (mc_unw_init_context(st->context, &mc_model_checker->process,
+ original_context) < 0) {
+ xbt_die("Could not initialise the libunwind context.");
+ }
+
+ st->stack_frames = MC_unwind_stack_frames(st->context);
st->local_variables = MC_get_local_variables_values(st->stack_frames, current_stack->process_index);
st->process_index = current_stack->process_index;
}
+// FIXME, cross-process support (mc_heap_comparison_ignore)
static xbt_dynar_t MC_take_snapshot_ignore()
{
static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot)
{
+ xbt_assert(snapshot->process);
snapshot->ignored_data = xbt_dynar_new(sizeof(s_mc_snapshot_ignored_data_t), mc_free_snapshot_ignored_data_pvoid);
// Copy the memory:
unsigned int cursor = 0;
mc_checkpoint_ignore_region_t region;
- xbt_dynar_foreach (mc_checkpoint_ignore, cursor, region) {
+ // FIXME, cross-process support (mc_checkpoint_ignore)
+ xbt_dynar_foreach (mc_model_checker->process.checkpoint_ignore, cursor, region) {
s_mc_snapshot_ignored_data_t ignored_data;
ignored_data.start = region->addr;
ignored_data.size = region->size;
ignored_data.data = malloc(region->size);
- memcpy(ignored_data.data, region->addr, region->size);
+ // TODO, we should do this once per privatization segment:
+ MC_process_read(snapshot->process,
+ MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ ignored_data.data, region->addr, region->size, MC_PROCESS_INDEX_DISABLED);
xbt_dynar_push(snapshot->ignored_data, &ignored_data);
}
// Zero the memory:
- xbt_dynar_foreach (mc_checkpoint_ignore, cursor, region) {
- memset(region->addr, 0, region->size);
+ xbt_dynar_foreach (mc_model_checker->process.checkpoint_ignore, cursor, region) {
+ MC_process_clear_memory(snapshot->process, region->addr, region->size);
}
}
unsigned int cursor = 0;
s_mc_snapshot_ignored_data_t ignored_data;
xbt_dynar_foreach (snapshot->ignored_data, cursor, ignored_data) {
- memcpy(ignored_data.start, ignored_data.data, ignored_data.size);
+ MC_process_write(snapshot->process,
+ ignored_data.data, ignored_data.start, ignored_data.size);
}
}
return false;
}
-static void MC_get_current_fd(mc_snapshot_t snapshot){
+static void MC_get_current_fd(mc_snapshot_t snapshot)
+{
snapshot->total_fd = 0;
const size_t fd_dir_path_size = 20;
char fd_dir_path[fd_dir_path_size];
if (snprintf(fd_dir_path, fd_dir_path_size,
- "/proc/%lli/fd", (long long int) getpid()) > fd_dir_path_size)
+ "/proc/%lli/fd", (long long int) snapshot->process->pid) > fd_dir_path_size)
xbt_die("Unexpected buffer is too small for fd_dir_path");
- DIR* fd_dir = opendir (fd_dir_path);
+ DIR* fd_dir = opendir(fd_dir_path);
if (fd_dir == NULL)
xbt_die("Cannot open directory '/proc/self/fd'\n");
const size_t source_size = 25;
char source[25];
- if (snprintf(source, source_size, "/proc/self/fd/%s", fd_number->d_name) > source_size)
+ if (snprintf(source, source_size, "/proc/%lli/fd/%s",
+ (long long int) snapshot->process->pid, fd_number->d_name) > source_size)
xbt_die("Unexpected buffer is too small for fd %s", fd_number->d_name);
const size_t link_size = 200;
closedir (fd_dir);
}
+static s_mc_address_space_class_t mc_snapshot_class = {
+ .read = (void*) &MC_snapshot_read
+};
+
mc_snapshot_t MC_take_snapshot(int num_state)
{
-
+ mc_process_t mc_process = &mc_model_checker->process;
mc_snapshot_t snapshot = xbt_new0(s_mc_snapshot_t, 1);
+ snapshot->process = mc_process;
+ snapshot->address_space.address_space_class = &mc_snapshot_class;
+
snapshot->enabled_processes = xbt_dynar_new(sizeof(int), NULL);
smx_process_t process;
+ // FIXME, cross-process support (simix_global->process_list)
xbt_swag_foreach(process, simix_global->process_list) {
xbt_dynar_push_as(snapshot->enabled_processes, int, (int)process->pid);
}
MC_snapshot_handle_ignore(snapshot);
- MC_get_current_fd(snapshot);
+ if (_sg_mc_snapshot_fds)
+ MC_get_current_fd(snapshot);
+
+ const bool use_soft_dirty = _sg_mc_sparse_checkpoint
+ && _sg_mc_soft_dirty
+ && MC_process_is_self(mc_process);
/* Save the std heap and the writable mapped pages of libsimgrid and binary */
- MC_get_memory_regions(snapshot);
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
+ MC_get_memory_regions(mc_process, snapshot);
+ if (use_soft_dirty)
mc_softdirty_reset();
- }
snapshot->to_ignore = MC_take_snapshot_ignore();
}
MC_snapshot_ignore_restore(snapshot);
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
+ if (use_soft_dirty)
mc_model_checker->parent_snapshot = snapshot;
- }
return snapshot;
}
-void MC_restore_snapshot(mc_snapshot_t snapshot)
+static inline
+void MC_restore_snapshot_regions(mc_snapshot_t snapshot)
{
mc_snapshot_t parent_snapshot = mc_model_checker->parent_snapshot;
- int new_fd;
- unsigned int i;
- for (i = 0; i < NB_REGIONS; i++) {
+ const size_t n = snapshot->snapshot_regions_count;
+ for (size_t i = 0; i < n; i++) {
// For privatized, variables we decided it was not necessary to take the snapshot:
- if (snapshot->regions[i])
- MC_region_restore(snapshot->regions[i],
- parent_snapshot ? parent_snapshot->regions[i] : NULL);
+ if (snapshot->snapshot_regions[i])
+ MC_region_restore(snapshot->snapshot_regions[i],
+ parent_snapshot ? parent_snapshot->snapshot_regions[i] : NULL);
}
#ifdef HAVE_SMPI
- if (snapshot->privatization_regions) {
- // Restore the global variables of the application separately for each
- // simulated process:
- for (i = 0; i < smpi_process_count(); i++) {
- if (snapshot->privatization_regions[i]) {
- MC_region_restore(snapshot->privatization_regions[i],
- parent_snapshot ? parent_snapshot->privatization_regions[i] : NULL);
- }
- }
- }
if(snapshot->privatization_index >= 0) {
// We just rewrote the global variables.
// The privatisation segment SMPI thinks
smpi_really_switch_data_segment(snapshot->privatization_index);
}
#endif
+}
+
+static inline
+void MC_restore_snapshot_fds(mc_snapshot_t snapshot)
+{
+ if (mc_mode == MC_MODE_SERVER)
+ xbt_die("FD snapshot not implemented in client/server mode.");
+ int new_fd;
+ size_t i;
for(i=0; i < snapshot->total_fd; i++){
new_fd = open(snapshot->current_fd[i]->filename, snapshot->current_fd[i]->flags);
};
lseek(snapshot->current_fd[i]->number, snapshot->current_fd[i]->current_position, SEEK_SET);
}
+}
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
+void MC_restore_snapshot(mc_snapshot_t snapshot)
+{
+ const bool use_soft_dirty = _sg_mc_sparse_checkpoint
+ && _sg_mc_soft_dirty
+ && MC_process_is_self(&mc_model_checker->process);
+
+ MC_restore_snapshot_regions(snapshot);
+ if (_sg_mc_snapshot_fds)
+ MC_restore_snapshot_fds(snapshot);
+ if (use_soft_dirty) {
mc_softdirty_reset();
}
-
MC_snapshot_ignore_restore(snapshot);
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
+ if (use_soft_dirty) {
mc_model_checker->parent_snapshot = snapshot;
}
+ mc_model_checker->process.cache_flags = 0;
}
mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)
{
return MC_take_snapshot(1);
}
-
-void *MC_snapshot(void)
-{
- return simcall_mc_snapshot();
-}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <xbt/log.h>
+#include <xbt/sysdep.h>
+#include <xbt/mmalloc.h>
+
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+// We won't need those once the separation MCer/MCed is complete:
+#include "mc_mmalloc.h"
+#include "mc_ignore.h"
+#include "mc_model_checker.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client, mc, "MC client logic");
+
+mc_client_t mc_client;
+
+void MC_client_init(void)
+{
+ if (mc_client) {
+ XBT_WARN("MC_client_init called more than once.");
+ return;
+ }
+
+ char* fd_env = getenv(MC_ENV_SOCKET_FD);
+ if (!fd_env)
+ xbt_die("MC socket not found");
+
+ int fd = atoi(fd_env);
+ XBT_DEBUG("Model-checked application found socket FD %i", fd);
+
+ int type;
+ socklen_t socklen = sizeof(type);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) != 0)
+ xbt_die("Could not check socket type: %s", strerror(errno));
+ if (type != SOCK_DGRAM)
+ xbt_die("Unexpected socket type %i", type);
+ XBT_DEBUG("Model-checked application found expected socket type");
+
+ mc_client = xbt_new0(s_mc_client_t, 1);
+ mc_client->fd = fd;
+ mc_client->active = 1;
+}
+
+void MC_client_hello(void)
+{
+ XBT_DEBUG("Greeting the MC server");
+ if (MC_protocol_hello(mc_client->fd) != 0)
+ xbt_die("Could not say hello the MC server");
+ XBT_DEBUG("Greeted the MC server");
+}
+
+void MC_client_send_message(void* message, size_t size)
+{
+ if (MC_protocol_send(mc_client->fd, message, size))
+ xbt_die("Could not send message %i", (int) ((mc_message_t)message)->type);
+}
+
+void MC_client_handle_messages(void)
+{
+ while (1) {
+ XBT_DEBUG("Waiting messages from model-checker");
+
+ char message_buffer[MC_MESSAGE_LENGTH];
+ size_t s;
+ if ((s = recv(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) == -1)
+ xbt_die("Could not receive commands from the model-checker: %s",
+ strerror(errno));
+
+ XBT_DEBUG("Receive message from model-checker");
+ s_mc_message_t message;
+ if (s < sizeof(message))
+ xbt_die("Message is too short");
+ memcpy(&message, message_buffer, sizeof(message));
+ switch (message.type) {
+ case MC_MESSAGE_CONTINUE:
+ return;
+ default:
+ xbt_die("Unexpected message from model-checker %i", message.type);
+ }
+ }
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_CLIENT_H
+#define MC_CLIENT_H
+
+#include <xbt/misc.h>
+
+SG_BEGIN_DECL()
+
+typedef struct s_mc_client {
+ int active;
+ int fd;
+} s_mc_client_t, *mc_client_t;
+
+extern mc_client_t mc_client;
+
+void MC_client_init(void);
+void MC_client_hello(void);
+void MC_client_handle_messages(void);
+void MC_client_send_message(void* message, size_t size);
+
+void MC_ignore(void* addr, size_t size);
+
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+/* Copyright (c) 2008-2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/log.h>
+#include <xbt/fifo.h>
+#include <xbt/sysdep.h>
+#include <simgrid/modelchecker.h>
+
+#include "mc_record.h"
+#include "mc_private.h"
+#include "mc_mmalloc.h"
+#include "mc_model_checker.h"
+#include "mc_ignore.h"
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client_api, mc,
+ "Public API for the model-checked application");
+
+void MC_assert(int prop)
+{
+ if (MC_is_active() && !prop) {
+ XBT_INFO("**************************");
+ XBT_INFO("*** PROPERTY NOT VALID ***");
+ XBT_INFO("**************************");
+ XBT_INFO("Counter-example execution trace:");
+ MC_record_dump_path(mc_stack);
+ MC_dump_stack_safety(mc_stack);
+ MC_print_statistics(mc_stats);
+ xbt_abort();
+ }
+}
+
+// TODO, MC_automaton_new_propositional_symbol
+
+void *MC_snapshot(void)
+{
+ return simcall_mc_snapshot();
+}
+
+int simcall_HANDLER_mc_compare_snapshots(smx_simcall_t simcall,
+ mc_snapshot_t s1, mc_snapshot_t s2)
+{
+ return snapshot_compare(s1, s2);
+}
+
+int MC_compare_snapshots(void *s1, void *s2)
+{
+ return simcall_mc_compare_snapshots(s1, s2);
+}
+
+void MC_cut(void)
+{
+ user_max_depth_reached = 1;
+}
+
+void MC_ignore(void* addr, size_t size)
+{
+ if (mc_mode == MC_MODE_CLIENT) {
+ s_mc_ignore_memory_message_t message;
+ message.type = MC_MESSAGE_IGNORE_MEMORY;
+ message.addr = addr;
+ message.size = size;
+ MC_client_send_message(&message, sizeof(message));
+ }
+
+ // TODO, remove this once the migration has been completed
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+ MC_process_ignore_memory(&mc_model_checker->process, addr, size);
+ mmalloc_set_current_heap(heap);
+}
static void update_comm_pattern(mc_comm_pattern_t comm_pattern, smx_synchro_t comm)
{
+ mc_process_t process = &mc_model_checker->process;
void *addr_pointed;
comm_pattern->src_proc = comm->comm.src_proc->pid;
comm_pattern->dst_proc = comm->comm.dst_proc->pid;
comm_pattern->data_size = *(comm->comm.dst_buff_size);
comm_pattern->data = xbt_malloc0(comm_pattern->data_size);
addr_pointed = *(void **) comm->comm.src_buff;
- if (addr_pointed > (void*) std_heap && addr_pointed < std_heap->breakval)
+ if (addr_pointed > (void*) process->heap_address
+ && addr_pointed < MC_process_get_heap(process)->breakval)
memcpy(comm_pattern->data, addr_pointed, comm_pattern->data_size);
else
memcpy(comm_pattern->data, comm->comm.src_buff, comm_pattern->data_size);
void get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, e_mc_call_type_t call_type)
{
-
+ mc_process_t process = &mc_model_checker->process;
mc_comm_pattern_t pattern = NULL;
pattern = xbt_new0(s_mc_comm_pattern_t, 1);
pattern->data_size = -1;
pattern->data_size = pattern->comm->comm.src_buff_size;
pattern->data = xbt_malloc0(pattern->data_size);
addr_pointed = *(void **) pattern->comm->comm.src_buff;
- if (addr_pointed > (void*) std_heap && addr_pointed < std_heap->breakval)
+ if (addr_pointed > (void*) process->heap_address
+ && addr_pointed < MC_process_get_heap(process)->breakval)
memcpy(pattern->data, addr_pointed, pattern->data_size);
else
memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size);
void MC_pre_modelcheck_comm_determinism(void)
{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
+ MC_SET_MC_HEAP;
mc_state_t initial_state = NULL;
smx_process_t process;
int i;
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
-
if (_sg_mc_visited > 0)
visited_states = xbt_dynar_new(sizeof(mc_visited_state_t), visited_state_free_voidp);
static void stack_region_free(stack_region_t s)
{
if (s) {
- xbt_free(s->process_name);
xbt_free(s);
}
}
void* real_area2, mc_snapshot_t snapshot2, mc_mem_region_t region2,
dw_type_t type, int pointer_level)
{
+ mc_process_t process = &mc_model_checker->process;
+
unsigned int cursor = 0;
dw_type_t member, subtype, subsubtype;
int elm_size, i, res;
case DW_TAG_enumeration_type:
case DW_TAG_union_type:
{
- return mc_snapshot_region_memcmp(
+ return MC_snapshot_region_memcmp(
real_area1, region1, real_area2, region2,
type->byte_size) != 0;
}
case DW_TAG_reference_type:
case DW_TAG_rvalue_reference_type:
{
- void* addr_pointed1 = mc_snapshot_read_pointer_region(real_area1, region1);
- void* addr_pointed2 = mc_snapshot_read_pointer_region(real_area2, region2);
+ void* addr_pointed1 = MC_region_read_pointer(region1, real_area1);
+ void* addr_pointed2 = MC_region_read_pointer(region2, real_area2);
if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
return (addr_pointed1 != addr_pointed2);
// * a pointer leads to the read-only segment of the current object;
// * a pointer lead to a different ELF object.
- if (addr_pointed1 > std_heap
+ if (addr_pointed1 > process->heap_address
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)) {
if (!
- (addr_pointed2 > std_heap
+ (addr_pointed2 > process->heap_address
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
return 1;
// The pointers are both in the heap:
case DW_TAG_class_type:
xbt_dynar_foreach(type->members, cursor, member) {
void *member1 =
- mc_member_resolve(real_area1, type, member, snapshot1, process_index);
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
void *member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, process_index, region1);
mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, process_index, region2);
res =
mc_snapshot_t snapshot2)
{
xbt_assert(r1 && r2, "Missing region.");
+
+#ifdef HAVE_SMPI
+ if (r1->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ xbt_assert(process_index >= 0);
+ if (r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ return 1;
+ }
+
+ size_t process_count = smpi_process_count();
+ xbt_assert(process_count == r1->privatized.regions_count
+ && process_count == r2->privatized.regions_count);
+
+ // Compare the global variables separately for each simulates process:
+ for (size_t process_index = 0; process_index < process_count; process_index++) {
+ int is_diff = compare_global_variables(object_info, process_index,
+ r1->privatized.regions[process_index], r2->privatized.regions[process_index],
+ snapshot1, snapshot2);
+ if (is_diff) return 1;
+ }
+ return 0;
+ }
+#else
+ xbt_assert(r1->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+#endif
+ xbt_assert(r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+
struct mc_compare_state state;
xbt_dynar_t variables;
int snapshot_compare(void *state1, void *state2)
{
+ mc_process_t process = &mc_model_checker->process;
mc_snapshot_t s1, s2;
int num1, num2;
#endif
/* Init heap information used in heap comparison algorithm */
- xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(std_heap, s1, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
- xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(std_heap, s2, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
+ xbt_mheap_t heap1 = (xbt_mheap_t) MC_snapshot_read(
+ s1, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
+ xbt_mheap_t heap2 = (xbt_mheap_t) MC_snapshot_read(
+ s2, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
res_init = init_heap_information(heap1, heap2, s1->to_ignore, s2->to_ignore);
if (res_init == -1) {
#ifdef MC_DEBUG
cursor++;
}
+ size_t regions_count = s1->snapshot_regions_count;
+ // TODO, raise a difference instead?
+ xbt_assert(regions_count == s2->snapshot_regions_count);
+ mc_comp_times->global_variables_comparison_time = 0;
- const char *names[3] = { "?", "libsimgrid", "binary" };
-#ifdef MC_DEBUG
- double *times[3] = {
- NULL,
- &mc_comp_times->libsimgrid_global_variables_comparison_time,
- &mc_comp_times->binary_global_variables_comparison_time
- };
-#endif
+ for (size_t k = 0; k != regions_count; ++k) {
+ mc_mem_region_t region1 = s1->snapshot_regions[k];
+ mc_mem_region_t region2 = s2->snapshot_regions[k];
- mc_object_info_t object_infos[] = { NULL, mc_libsimgrid_info, mc_binary_info };
+ // Preconditions:
+ if (region1->region_type != MC_REGION_TYPE_DATA)
+ continue;
+
+ xbt_assert(region1->region_type == region2->region_type);
+ xbt_assert(region1->object_info == region2->object_info);
+
+ xbt_assert(region1->object_info);
+
+ const char* name = region1->object_info->file_name;
- int k = 0;
- for (k = 2; k != 0; --k) {
#ifdef MC_DEBUG
if (is_diff == 0)
xbt_os_walltimer_stop(timer);
#endif
/* Compare global variables */
-#ifdef HAVE_SMPI
- if (object_infos[k] == mc_binary_info && smpi_privatize_global_variables) {
- // Compare the global variables separately for each simulates process:
- for (int process_index = 0; process_index < smpi_process_count(); process_index++) {
- is_diff =
- compare_global_variables(object_infos[k], process_index,
- s1->privatization_regions[process_index], s2->privatization_regions[process_index], s1, s2);
- if (is_diff) break;
- }
- }
- else
-#endif
- is_diff =
- compare_global_variables(object_infos[k], MC_NO_PROCESS_INDEX, s1->regions[k], s2->regions[k], s1, s2);
+ is_diff =
+ compare_global_variables(region1->object_info, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ region1, region2,
+ s1, s2);
if (is_diff != 0) {
XBT_TRACE3(mc, state_diff, num1, num2, "Different global variables");
#ifdef MC_DEBUG
xbt_os_walltimer_stop(timer);
- *times[k] = xbt_os_timer_elapsed(timer);
+ mc_comp_times->global_variables_comparison_time
+ += xbt_os_timer_elapsed(timer);
XBT_DEBUG("(%d - %d) Different global variables in %s", num1, num2,
- names[k]);
+ name);
errors++;
#else
#ifdef MC_VERBOSE
XBT_VERB("(%d - %d) Different global variables in %s", num1, num2,
- names[k]);
+ name);
#endif
reset_heap_information();
XBT_DEBUG("- Nb processes : %f", mc_comp_times->nb_processes_comparison_time);
XBT_DEBUG("- Nb bytes used : %f", mc_comp_times->bytes_used_comparison_time);
XBT_DEBUG("- Stacks sizes : %f", mc_comp_times->stacks_sizes_comparison_time);
- XBT_DEBUG("- Binary global variables : %f",
- mc_comp_times->binary_global_variables_comparison_time);
- XBT_DEBUG("- Libsimgrid global variables : %f",
- mc_comp_times->libsimgrid_global_variables_comparison_time);
+ XBT_DEBUG("- GLobal variables : %f", mc_comp_times->global_variables_comparison_time);
XBT_DEBUG("- Heap : %f", mc_comp_times->heap_comparison_time);
XBT_DEBUG("- Stacks : %f", mc_comp_times->stacks_comparison_time);
}
-/**************************** MC snapshot compare simcall **************************/
-/***********************************************************************************/
-
-int simcall_HANDLER_mc_compare_snapshots(smx_simcall_t simcall,
- mc_snapshot_t s1, mc_snapshot_t s2)
-{
- return snapshot_compare(s1, s2);
-}
-
-int MC_compare_snapshots(void *s1, void *s2)
-{
-
- return simcall_mc_compare_snapshots(s1, s2);
-
-}
-
}
int _sg_mc_send_determinism = 0;
int _sg_mc_safety = 0;
int _sg_mc_liveness = 0;
-
+int _sg_mc_snapshot_fds = 0;
void _mc_cfg_cb_reduce(const char *name, int pos)
{
_sg_mc_hash = xbt_cfg_get_boolean(_sg_cfg_set, name);
}
+void _mc_cfg_cb_snapshot_fds(const char *name, int pos)
+{
+ if (_sg_cfg_init_status && !_sg_do_model_check) {
+ xbt_die
+ ("You are specifying a value to enable/disable the use of FD snapshoting, but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
+ }
+ _sg_mc_snapshot_fds = xbt_cfg_get_boolean(_sg_cfg_set, name);
+}
+
void _mc_cfg_cb_max_depth(const char *name, int pos)
{
if (_sg_cfg_init_status && !_sg_do_model_check) {
xbt_dynar_t mc_heap_comparison_ignore;
xbt_dynar_t stacks_areas;
-void *maestro_stack_start, *maestro_stack_end;
+
/********************************* Backtrace ***********************************/
}
static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
- void *address)
+ const void *address)
{
unsigned int cursor = 0;
return -1;
}
-static int is_stack(void *address)
+static int is_stack(const void *address)
{
unsigned int cursor = 0;
stack_region_t stack;
}
-int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+// TODO, have a robust way to find it in O(1)
+static inline
+mc_mem_region_t MC_get_heap_region(mc_snapshot_t snapshot)
{
+ size_t n = snapshot->snapshot_regions_count;
+ for (size_t i=0; i!=n; ++i) {
+ mc_mem_region_t region = snapshot->snapshot_regions[i];
+ if (region->region_type == MC_REGION_TYPE_HEAP)
+ return region;
+ }
+ xbt_die("No heap region");
+}
+int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+{
+ mc_process_t process = &mc_model_checker->process;
struct s_mc_diff *state = mc_diff_info;
/* Start comparison */
malloc_info heapinfo_temp1, heapinfo_temp2;
malloc_info heapinfo_temp2b;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
+
+ // This is the address of std_heap->heapinfo in the application process:
+ void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
// This is in snapshot do not use them directly:
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, MC_NO_PROCESS_INDEX);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, MC_NO_PROCESS_INDEX);
+ const malloc_info* heapinfos1 = MC_snapshot_read_pointer(snapshot1, heapinfo_address, MC_PROCESS_INDEX_MISSING);
+ const malloc_info* heapinfos2 = MC_snapshot_read_pointer(snapshot2, heapinfo_address, MC_PROCESS_INDEX_MISSING);
while (i1 <= state->heaplimit) {
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i1], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i1], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[i1], sizeof(malloc_info));
if (heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type == MMALLOC_TYPE_HEAPINFO) { /* Free block */
i1 ++;
(char *) ((xbt_mheap_t) state->s_heap)->heapbase));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
continue;
}
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
if (heapinfo2b->type != MMALLOC_TYPE_UNFRAGMENTED) {
i2++;
}
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
(j1 << heapinfo2->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1)
while (i2 <= state->heaplimit && !equal) {
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
if (heapinfo2b->type == MMALLOC_TYPE_FREE || heapinfo2b->type == MMALLOC_TYPE_HEAPINFO) {
i2 ++;
(j2 << heapinfo2b->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot2, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot2, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
size_t i = 1, j = 0;
for(i = 1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i], sizeof(malloc_info));
if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo1->busy_block.busy_size > 0) {
XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
for (i=1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[i], sizeof(malloc_info));
if (heapinfo2->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo2->busy_block.busy_size > 0) {
* @param check_ignore
*/
static int compare_heap_area_without_type(struct s_mc_diff *state, int process_index,
- void *real_area1, void *real_area2,
+ const void *real_area1, const void *real_area2,
mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2,
xbt_dynar_t previous, int size,
int check_ignore)
{
+ mc_process_t process = &mc_model_checker->process;
int i = 0;
- void *addr_pointed1, *addr_pointed2;
+ const void *addr_pointed1, *addr_pointed2;
int pointer_align, res_compare;
ssize_t ignore1, ignore2;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
while (i < size) {
}
}
- if (mc_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
+ if (MC_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
pointer_align = (i / sizeof(void *)) * sizeof(void *);
- addr_pointed1 = mc_snapshot_read_pointer((char *) real_area1 + pointer_align, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer((char *) real_area2 + pointer_align, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char *) real_area1 + pointer_align, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char *) real_area2 + pointer_align, process_index);
- if (addr_pointed1 > maestro_stack_start
- && addr_pointed1 < maestro_stack_end
- && addr_pointed2 > maestro_stack_start
- && addr_pointed2 < maestro_stack_end) {
+ if (addr_pointed1 > process->maestro_stack_start
+ && addr_pointed1 < process->maestro_stack_end
+ && addr_pointed2 > process->maestro_stack_start
+ && addr_pointed2 < process->maestro_stack_end) {
i = pointer_align + sizeof(void *);
continue;
} else if (addr_pointed1 > state->s_heap
* @return 0 (same), 1 (different), -1 (unknown)
*/
static int compare_heap_area_with_type(struct s_mc_diff *state, int process_index,
- void *real_area1, void *real_area2,
+ const void *real_area1, const void *real_area2,
mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2,
xbt_dynar_t previous, dw_type_t type,
int res, elm_size, i;
unsigned int cursor = 0;
dw_type_t member;
- void *addr_pointed1, *addr_pointed2;;
+ const void *addr_pointed1, *addr_pointed2;;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
switch (type->type) {
case DW_TAG_unspecified_type:
if (real_area1 == real_area2)
return -1;
else
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
} else {
if (area_size != -1 && type->byte_size != area_size)
return -1;
else {
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
}
}
break;
if (area_size != -1 && type->byte_size != area_size)
return -1;
else
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
break;
case DW_TAG_typedef:
case DW_TAG_const_type:
case DW_TAG_rvalue_reference_type:
case DW_TAG_pointer_type:
if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
- addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, real_area1, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, real_area2, process_index);
return (addr_pointed1 != addr_pointed2);;
} else {
pointer_level++;
if (pointer_level > 1) { /* Array of pointers */
for (i = 0; i < (area_size / sizeof(void *)); i++) {
- addr_pointed1 = mc_snapshot_read_pointer((char*) real_area1 + i * sizeof(void *), snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer((char*) real_area2 + i * sizeof(void *), snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char*) real_area1 + i * sizeof(void *), process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char*) real_area2 + i * sizeof(void *), process_index);
if (addr_pointed1 > state->s_heap
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
&& addr_pointed2 > state->s_heap
return res;
}
} else {
- addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, real_area1, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, real_area2, process_index);
if (addr_pointed1 > state->s_heap
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
&& addr_pointed2 > state->s_heap
xbt_dynar_foreach(type->members, cursor, member) {
// TODO, optimize this? (for the offset case)
char *real_member1 =
- mc_member_resolve(real_area1, type, member, snapshot1, process_index);
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
char *real_member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
res =
compare_heap_area_with_type(state, process_index, real_member1, real_member2,
snapshot1, snapshot2,
return member->subtype;
} else {
char *real_member =
- mc_member_resolve(real_base_address, type, member, snapshot, process_index);
+ mc_member_resolve(real_base_address, type, member, (mc_address_space_t) snapshot, process_index);
if (real_member - (char *) real_base_address == offset)
return member->subtype;
}
* @param pointer_level
* @return 0 (same), 1 (different), -1
*/
-int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t snapshot1,
+int compare_heap_area(int process_index, const void *area1, const void *area2, mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2, xbt_dynar_t previous,
dw_type_t type, int pointer_level)
{
+ mc_process_t process = &mc_model_checker->process;
struct s_mc_diff *state = mc_diff_info;
int match_pairs = 0;
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, process_index);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, process_index);
+ // This is the address of std_heap->heapinfo in the application process:
+ void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
+
+ const malloc_info* heapinfos1 = MC_snapshot_read_pointer(snapshot1, heapinfo_address, process_index);
+ const malloc_info* heapinfos2 = MC_snapshot_read_pointer(snapshot2, heapinfo_address, process_index);
malloc_info heapinfo_temp1, heapinfo_temp2;
}
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[block1], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[block2], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[block1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[block2], sizeof(malloc_info));
if ((heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type==MMALLOC_TYPE_HEAPINFO)
&& (heapinfo2->type == MMALLOC_TYPE_FREE || heapinfo2->type ==MMALLOC_TYPE_HEAPINFO)) {
}
Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
if (dwarf == NULL) {
- xbt_die("Your program must be compiled with -g");
+ xbt_die("Your program must be compiled with -g (%s)", info->file_name);
}
// For each compilation unit:
Dwarf_Off offset = 0;
info->functions_index = index;
}
-mc_object_info_t MC_ip_find_object_info(void *ip)
-{
- size_t i;
- for (i = 0; i != mc_object_infos_size; ++i) {
- if (ip >= (void *) mc_object_infos[i]->start_exec
- && ip <= (void *) mc_object_infos[i]->end_exec) {
- return mc_object_infos[i];
- }
- }
- return NULL;
-}
-
-static dw_frame_t MC_find_function_by_ip_and_object(void *ip,
- mc_object_info_t info)
-{
- xbt_dynar_t dynar = info->functions_index;
- mc_function_index_item_t base =
- (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
- int i = 0;
- int j = xbt_dynar_length(dynar) - 1;
- while (j >= i) {
- int k = i + ((j - i) / 2);
- if (ip < base[k].low_pc) {
- j = k - 1;
- } else if (ip >= base[k].high_pc) {
- i = k + 1;
- } else {
- return base[k].function;
- }
- }
- return NULL;
-}
-
-dw_frame_t MC_find_function_by_ip(void *ip)
-{
- mc_object_info_t info = MC_ip_find_object_info(ip);
- if (info == NULL)
- return NULL;
- else
- return MC_find_function_by_ip_and_object(ip, info);
-}
-
static void MC_post_process_variables(mc_object_info_t info)
{
unsigned cursor = 0;
}
/** \brief Finds informations about a given shared object/executable */
-mc_object_info_t MC_find_object_info(memory_map_t maps, char *name,
+mc_object_info_t MC_find_object_info(memory_map_t maps, const char *name,
int executable)
{
mc_object_info_t result = MC_new_object_info();
MC_dwarf_register_non_global_variable(info, frame, variable);
}
-void MC_post_process_object_info(mc_object_info_t info)
+void MC_post_process_object_info(mc_process_t process, mc_object_info_t info)
{
xbt_dict_cursor_t cursor = NULL;
char *key = NULL;
// Resolve full_type:
if (type->name && type->byte_size == 0) {
- for (size_t i = 0; i != mc_object_infos_size; ++i) {
+ for (size_t i = 0; i != process->object_infos_size; ++i) {
dw_type_t same_type =
- xbt_dict_get_or_null(mc_object_infos[i]->full_types_by_name,
+ xbt_dict_get_or_null(process->object_infos[i]->full_types_by_name,
type->name);
if (same_type && same_type->name && same_type->byte_size) {
type->full_type = same_type;
#include <elfutils/libdw.h>
#include "mc_object_info.h"
-#include "mc_snapshot.h"
#include "mc_private.h"
static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
return 0;
}
+/** Convert a DWARF register into a libunwind register
+ *
+ * DWARF and libunwind does not use the same convention for numbering the
+ * registers on some architectures. The function makes the necessary
+ * convertion.
+ */
static int mc_dwarf_register_to_libunwind(int dwarf_register)
{
#if defined(UNW_TARGET_X86_64)
xbt_die("Bad/unknown register number.");
}
#else
-#error This architecture is not supported yet.
+#error This architecture is not supported yet for DWARF expression evaluation.
#endif
}
{
if (!state->frame_base)
return MC_EXPRESSION_E_MISSING_FRAME_BASE;
- error =
- mc_dwarf_push_value(state,
- ((uintptr_t) state->frame_base) + op->number);
+ uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
+ error = mc_dwarf_push_value(state, fb);
break;
}
- // Constants:
+ // ***** Constants:
+ // Short constant literals:
+ // DW_OP_lit15 pushed the 15 on the stack.
case DW_OP_lit0:
case DW_OP_lit1:
case DW_OP_lit2:
error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
break;
+ // Address from the base address of this ELF object.
+ // Push the address on the stack (base_address + argument).
case DW_OP_addr:
if (!state->object_info)
return MC_EXPRESSION_E_NO_BASE_ADDRESS;
if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
return MC_EXPRESSION_E_STACK_OVERFLOW;
- error = mc_dwarf_push_value(state,
- (Dwarf_Off) (uintptr_t)
- MC_object_base_address(state->object_info) +
- op->number);
+ Dwarf_Off addr = (Dwarf_Off) (uintptr_t)
+ MC_object_base_address(state->object_info) + op->number;
+ error = mc_dwarf_push_value(state, addr);
break;
+ // General constants:
+ // Push the constant argument on the stack.
case DW_OP_const1u:
case DW_OP_const2u:
case DW_OP_const4u:
error = mc_dwarf_push_value(state, op->number);
break;
- // Stack manipulation:
+ // ***** Stack manipulation:
- // Push the value at the top of the stack:
+ // Push another copy/duplicate the value at the top of the stack:
case DW_OP_dup:
if (state->stack_size == 0)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
break;
+ // Pop/drop the top of the stack:
case DW_OP_drop:
if (state->stack_size == 0)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
state->stack_size--;
break;
+ // Swap the two top-most value of the stack:
case DW_OP_swap:
if (state->stack_size < 2)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
}
break;
+ // Duplicate the value under the top of the stack:
case DW_OP_over:
if (state->stack_size < 2)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
break;
- // Operations:
+ // ***** Operations:
+ // Those usually take the top of the stack and the next value as argument
+ // and replace the top of the stack with the computed value
+ // (stack.top() += stack.before_top()).
case DW_OP_plus:
if (state->stack_size < 2)
case DW_OP_nop:
break;
- // Dereference:
+ // ***** Deference (memory fetch)
+
case DW_OP_deref_size:
return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
{
// Computed address:
uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
- uintptr_t temp;
- uintptr_t* res = (uintptr_t*) mc_snapshot_read((void*) address, state->snapshot, state->process_index, &temp, sizeof(uintptr_t));
- state->stack[state->stack_size - 1] = *res;
+ uintptr_t value;
+ if (state->address_space) {
+ uintptr_t temp;
+ const uintptr_t* res = (uintptr_t*) MC_address_space_read(
+ state->address_space, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ &temp, (const void*) address, sizeof(uintptr_t), state->process_index);
+ value = *res;
+ }
+ else {
+ // TODO, use a mc_process representing the current process instead of this
+ value = *(const uintptr_t*) address;
+ }
+ state->stack[state->stack_size - 1] = value;
}
break;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
s_mc_expression_state_t state;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = frame_pointer_address;
state.cursor = c;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.object_info = object_info;
state.process_index = process_index;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
unw_word_t ip = 0;
if (expression) {
mc_dwarf_resolve_location(location,
expression, object_info, c,
- frame_pointer_address, snapshot, process_index);
+ frame_pointer_address, address_space, process_index);
} else {
xbt_die("Could not resolve location");
}
typedef struct s_memory_map s_memory_map_t, *memory_map_t;
typedef struct s_dw_variable s_dw_variable_t, *dw_variable_t;
typedef struct s_dw_frame s_dw_frame_t, *dw_frame_t;
+
typedef struct s_mc_pages_store s_mc_pages_store_t, *mc_pages_store_t;
+typedef struct s_mc_snapshot s_mc_snapshot_t, *mc_snapshot_t;
+
+typedef struct s_mc_process s_mc_process_t, * mc_process_t;
typedef struct s_mc_model_checker s_mc_model_checker_t, *mc_model_checker_t;
extern mc_model_checker_t mc_model_checker;
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <string.h>
+
#include "mc_base.h"
#ifndef _XBT_WIN32
#include <unistd.h>
-#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
-#include <sys/mman.h>
-#include <libgen.h>
#endif
#include "simgrid/sg_config.h"
#include "xbt/dict.h"
#ifdef HAVE_MC
-#define UNW_LOCAL_ONLY
#include <libunwind.h>
+#include <xbt/mmalloc.h>
#include "../xbt/mmalloc/mmprivate.h"
#include "mc_object_info.h"
#include "mc_snapshot.h"
#include "mc_liveness.h"
#include "mc_private.h"
+#include "mc_unw.h"
#endif
#include "mc_record.h"
+#include "mc_protocol.h"
+#include "mc_client.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
"Logging specific to MC (global)");
+e_mc_mode_t mc_mode;
+
double *mc_time = NULL;
#ifdef HAVE_MC
/* Liveness */
xbt_automaton_t _mc_property_automaton = NULL;
-/* Variables */
-mc_object_info_t mc_libsimgrid_info = NULL;
-mc_object_info_t mc_binary_info = NULL;
-
-mc_object_info_t mc_object_infos[2] = { NULL, NULL };
-
-size_t mc_object_infos_size = 2;
-
/* Dot output */
FILE *dot_output = NULL;
const char *colors[13];
}
-static void MC_init_debug_info(void)
-{
- XBT_INFO("Get debug information ...");
-
- memory_map_t maps = MC_get_memory_map();
-
- /* Get local variables for state equality detection */
- mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
- mc_object_infos[0] = mc_binary_info;
-
- mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
- mc_object_infos[1] = mc_libsimgrid_info;
-
- // Use information of the other objects:
- MC_post_process_object_info(mc_binary_info);
- MC_post_process_object_info(mc_libsimgrid_info);
-
- MC_free_memory_map(maps);
- XBT_INFO("Get debug information done !");
-}
-
-
-mc_model_checker_t mc_model_checker = NULL;
-
-mc_model_checker_t MC_model_checker_new()
+void MC_init()
{
- mc_model_checker_t mc = xbt_new0(s_mc_model_checker_t, 1);
- mc->pages = mc_pages_store_new();
- mc->fd_clear_refs = -1;
- mc->fd_pagemap = -1;
- return mc;
+ MC_init_pid(getpid(), -1);
}
-void MC_model_checker_delete(mc_model_checker_t mc) {
- mc_pages_store_delete(mc->pages);
- if(mc->record)
- xbt_dynar_free(&mc->record);
-}
-
-void MC_init()
+void MC_init_pid(pid_t pid, int socket)
{
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+ if (mc_mode == MC_MODE_NONE) {
+ if (getenv(MC_ENV_SOCKET_FD)) {
+ mc_mode = MC_MODE_CLIENT;
+ } else {
+ mc_mode = MC_MODE_STANDALONE;
+ }
+ }
mc_time = xbt_new0(double, simix_process_maxpid);
/* Initialize the data structures that must be persistent across every
iteration of the model-checker (in RAW memory) */
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
- mc_model_checker = MC_model_checker_new();
+ mc_model_checker = MC_model_checker_new(pid, socket);
mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
mc_stats = xbt_new0(s_mc_stats_t, 1);
mc_stats->state_size = 1;
- MC_init_memory_map_info();
- MC_init_debug_info(); /* FIXME : get debug information only if liveness verification or visited state reduction */
-
if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0'))
MC_init_dot_output();
/* SIMIX */
MC_ignore_global_variable("smx_total_comms");
- MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
+ if (mc_mode == MC_MODE_STANDALONE || mc_mode == MC_MODE_CLIENT) {
+ MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
- smx_process_t process;
- xbt_swag_foreach(process, simix_global->process_list) {
- MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
+ smx_process_t process;
+ xbt_swag_foreach(process, simix_global->process_list) {
+ MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
+ }
}
}
- if (raw_mem_set)
- MC_SET_MC_HEAP;
+ mmalloc_set_current_heap(heap);
+
+ if (mc_mode == MC_MODE_CLIENT) {
+ // This will move somehwere else:
+ MC_client_handle_messages();
+ }
}
static void MC_modelcheck_comm_determinism_init(void)
{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
MC_init();
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
/* Create exploration stack */
mc_stack = xbt_fifo_new();
MC_modelcheck_comm_determinism();
- if(mc_mem_set)
- MC_SET_MC_HEAP;
-
+ mmalloc_set_current_heap(heap);
}
static void MC_modelcheck_safety_init(void)
{
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
_sg_mc_safety = 1;
MC_init();
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
/* Create exploration stack */
mc_stack = xbt_fifo_new();
MC_modelcheck_safety();
- if (mc_mem_set)
- MC_SET_MC_HEAP;
+ mmalloc_set_current_heap(heap);
xbt_abort();
//MC_exit();
static void MC_modelcheck_liveness_init()
{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
_sg_mc_liveness = 1;
MC_init();
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
/* Create exploration stack */
mc_stack = xbt_fifo_new();
MC_print_statistics(mc_stats);
xbt_free(mc_time);
- if (mc_mem_set)
- MC_SET_MC_HEAP;
+ mmalloc_set_current_heap(heap);
}
*/
void MC_replay(xbt_fifo_t stack)
{
- int raw_mem = (mmalloc_get_current_heap() == mc_heap);
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
int value, count = 1, j;
char *req_str;
}
XBT_DEBUG("**** End Replay ****");
-
- if (raw_mem)
- MC_SET_MC_HEAP;
- else
- MC_SET_STD_HEAP;
-
-
+ mmalloc_set_current_heap(heap);
}
void MC_replay_liveness(xbt_fifo_t stack)
*/
void MC_dump_stack_safety(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
MC_show_stack_safety(stack);
MC_SET_MC_HEAP;
while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
MC_state_delete(state, !state->in_visited_states ? 1 : 0);
- MC_SET_STD_HEAP;
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
- else
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
}
void MC_show_stack_safety(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
int value;
mc_state_t state;
}
}
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
}
void MC_show_deadlock(smx_simcall_t req)
void MC_dump_stack_liveness(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
mc_pair_t pair;
-
- MC_SET_MC_HEAP;
while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
MC_pair_delete(pair);
- MC_SET_STD_HEAP;
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
-
+ mmalloc_set_current_heap(heap);
}
void MC_print_statistics(mc_stats_t stats)
{
- xbt_mheap_t previous_heap = mmalloc_get_current_heap();
-
if (stats->expanded_pairs == 0) {
XBT_INFO("Expanded states = %lu", stats->expanded_states);
XBT_INFO("Visited states = %lu", stats->visited_states);
XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
}
XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0')) {
fprintf(dot_output, "}\n");
fclose(dot_output);
if (_sg_mc_send_determinism)
XBT_INFO("Send-deterministic : %s", !initial_global_state->send_deterministic ? "No" : "Yes");
}
- mmalloc_set_current_heap(previous_heap);
-}
-
-void MC_assert(int prop)
-{
- if (MC_is_active() && !prop) {
- XBT_INFO("**************************");
- XBT_INFO("*** PROPERTY NOT VALID ***");
- XBT_INFO("**************************");
- XBT_INFO("Counter-example execution trace:");
- MC_record_dump_path(mc_stack);
- MC_dump_stack_safety(mc_stack);
- MC_print_statistics(mc_stats);
- xbt_abort();
- }
-}
-
-void MC_cut(void)
-{
- user_max_depth_reached = 1;
+ mmalloc_set_current_heap(heap);
}
void MC_automaton_load(const char *file)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
if (_mc_property_automaton == NULL)
_mc_property_automaton = xbt_automaton_new();
xbt_automaton_load(_mc_property_automaton, file);
-
- MC_SET_STD_HEAP;
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
-
+ mmalloc_set_current_heap(heap);
}
-void MC_automaton_new_propositional_symbol(const char *id, void *fct)
+static void register_symbol(xbt_automaton_propositional_symbol_t symbol)
{
+ if (mc_mode != MC_MODE_CLIENT)
+ return;
+ s_mc_register_symbol_message_t message;
+ message.type = MC_MESSAGE_REGISTER_SYMBOL;
+ const char* name = xbt_automaton_propositional_symbol_get_name(symbol);
+ if (strlen(name) + 1 > sizeof(message.name))
+ xbt_die("Symbol is too long");
+ strncpy(message.name, name, sizeof(message.name));
+ message.callback = xbt_automaton_propositional_symbol_get_callback(symbol);
+ message.data = xbt_automaton_propositional_symbol_get_data(symbol);
+ MC_client_send_message(&message, sizeof(message));
+}
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+void MC_automaton_new_propositional_symbol(const char *id, int(*fct)(void))
+{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
if (_mc_property_automaton == NULL)
_mc_property_automaton = xbt_automaton_new();
- xbt_automaton_propositional_symbol_new(_mc_property_automaton, id, fct);
-
- MC_SET_STD_HEAP;
+ xbt_automaton_propositional_symbol_t symbol = xbt_automaton_propositional_symbol_new(_mc_property_automaton, id, fct);
+ register_symbol(symbol);
+ mmalloc_set_current_heap(heap);
+}
- if (raw_mem_set)
- MC_SET_MC_HEAP;
+void MC_automaton_new_propositional_symbol_pointer(const char *id, int* value)
+{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+ if (_mc_property_automaton == NULL)
+ _mc_property_automaton = xbt_automaton_new();
+ xbt_automaton_propositional_symbol_t symbol = xbt_automaton_propositional_symbol_new_pointer(_mc_property_automaton, id, value);
+ register_symbol(symbol);
+ mmalloc_set_current_heap(heap);
+}
+void MC_automaton_new_propositional_symbol_callback(const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function)
+{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+ if (_mc_property_automaton == NULL)
+ _mc_property_automaton = xbt_automaton_new();
+ xbt_automaton_propositional_symbol_t symbol = xbt_automaton_propositional_symbol_new_callback(
+ _mc_property_automaton, id, callback, data, free_function);
+ register_symbol(symbol);
+ mmalloc_set_current_heap(heap);
}
void MC_dump_stacks(FILE* file)
{
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
int nstack = 0;
stack_region_t current_stack;
++nstack;
}
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
+ mmalloc_set_current_heap(heap);
}
#endif
mc_object_info_t info, const void *address,
dw_type_t type)
{
+ mc_process_t process = &mc_model_checker->process;
top:
switch (type->type) {
mc_address_add(state->handled_addresses, pointed);
// Anything outside the R/W segments and the heap is not hashed:
- bool valid_pointer = (pointed >= (void *) mc_binary_info->start_rw
- && pointed <= (void *) mc_binary_info->end_rw)
- || (pointed >= (void *) mc_libsimgrid_info->start_rw
- && pointed <= (void *) mc_libsimgrid_info->end_rw)
- || (pointed >= std_heap
- && pointed < (void *) ((const char *) std_heap + STD_HEAP_SIZE));
+ bool valid_pointer = (pointed >= (void *) binary_info->start_rw
+ && pointed <= (void *) binary_info->end_rw)
+ || (pointed >= (void *) libsimgrid_info->start_rw
+ && pointed <= (void *) libsimgrid_info->end_rw)
+ || (pointed >= process->heap_address
+ && pointed < (void *) ((const char *) process->heap_address + STD_HEAP_SIZE));
if (!valid_pointer) {
XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed);
return;
}
const char *address = variable->address;
- bool valid_pointer = (address >= mc_binary_info->start_rw
- && address <= mc_binary_info->end_rw)
- || (address >= mc_libsimgrid_info->start_rw
- && address <= mc_libsimgrid_info->end_rw)
- || (address >= (const char *) std_heap
- && address < (const char *) std_heap + STD_HEAP_SIZE);
+ bool valid_pointer = (address >= binary_info->start_rw
+ && address <= binary_info->end_rw)
+ || (address >= libsimgrid_info->start_rw
+ && address <= libsimgrid_info->end_rw)
+ || (address >= (const char *) process->heap_address
+ && address < (const char *) process->heap_address + STD_HEAP_SIZE);
if (!valid_pointer)
continue;
MC_HASH(*hash, stack_frame->ip);
mc_object_info_t info;
- if (stack_frame->ip >= (unw_word_t) mc_libsimgrid_info->start_exec
- && stack_frame->ip < (unw_word_t) mc_libsimgrid_info->end_exec)
- info = mc_libsimgrid_info;
- else if (stack_frame->ip >= (unw_word_t) mc_binary_info->start_exec
- && stack_frame->ip < (unw_word_t) mc_binary_info->end_exec)
- info = mc_binary_info;
+ if (stack_frame->ip >= (unw_word_t) libsimgrid_info->start_exec
+ && stack_frame->ip < (unw_word_t) libsimgrid_info->end_exec)
+ info = libsimgrid_info;
+ else if (stack_frame->ip >= (unw_word_t) binary_info->start_exec
+ && stack_frame->ip < (unw_word_t) binary_info->end_exec)
+ info = binary_info;
else
continue;
mc_hash_t hash = MC_HASH_INIT;
MC_HASH(hash, xbt_swag_size(simix_global->process_list)); // process count
- // mc_hash_object_globals(&hash, &state, mc_binary_info);
- // mc_hash_object_globals(&hash, &state, mc_libsimgrid_info);
+ // mc_hash_object_globals(&hash, &state, binary_info);
+ // mc_hash_object_globals(&hash, &state, libsimgrid_info);
// mc_hash_stacks(&hash, &state, stacks);
mc_hash_state_destroy(&state);
#include "mc_private.h"
#include "smpi/private.h"
#include "mc/mc_snapshot.h"
+#include "mc_ignore.h"
+#include "mc_protocol.h"
+#include "mc_client.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_ignore, mc,
"Logging specific to MC ignore mechanism");
/**************************** Global variables ******************************/
-xbt_dynar_t mc_checkpoint_ignore;
+// Those structures live with the MCer and should be moved in the model_checker
+// structure but they are currently used before the MC initialisation
+// (in standalone mode).
+
extern xbt_dynar_t mc_heap_comparison_ignore;
extern xbt_dynar_t stacks_areas;
checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
}
-/***********************************************************************/
-
-void MC_ignore_heap(void *address, size_t size)
+xbt_dynar_t MC_checkpoint_ignore_new(void)
{
+ return xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t),
+ checkpoint_ignore_region_free_voidp);
+}
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
- mc_heap_ignore_region_t region = NULL;
- region = xbt_new0(s_mc_heap_ignore_region_t, 1);
- region->address = address;
- region->size = size;
-
- region->block =
- ((char *) address -
- (char *) std_heap->heapbase) / BLOCKSIZE + 1;
-
- if (std_heap->heapinfo[region->block].type == 0) {
- region->fragment = -1;
- std_heap->heapinfo[region->block].busy_block.ignore++;
- } else {
- region->fragment =
- ((uintptr_t) (ADDR2UINT(address) % (BLOCKSIZE))) >> std_heap->
- heapinfo[region->block].type;
- std_heap->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
- }
+/***********************************************************************/
+// Mcer
+void MC_heap_region_ignore_insert(mc_heap_ignore_region_t region)
+{
if (mc_heap_comparison_ignore == NULL) {
mc_heap_comparison_ignore =
xbt_dynar_new(sizeof(mc_heap_ignore_region_t),
heap_ignore_region_free_voidp);
xbt_dynar_push(mc_heap_comparison_ignore, ®ion);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
}
int start = 0;
int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
+ // Find the position where we want to insert the mc_heap_ignore_region_t:
while (start <= end) {
cursor = (start + end) / 2;
current_region =
(mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
cursor,
mc_heap_ignore_region_t);
- if (current_region->address == address) {
+ if (current_region->address == region->address) {
heap_ignore_region_free(region);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
- } else if (current_region->address < address) {
+ } else if (current_region->address < region->address) {
start = cursor + 1;
} else {
end = cursor - 1;
}
}
- if (current_region->address < address)
+ // Insert it mc_heap_ignore_region_t:
+ if (current_region->address < region->address)
xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, ®ion);
else
xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, ®ion);
+}
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+// MCed:
+static void MC_heap_region_ignore_send(mc_heap_ignore_region_t region)
+{
+ s_mc_ignore_heap_message_t message;
+ message.type = MC_MESSAGE_IGNORE_HEAP;
+ message.region = *region;
+ if (MC_protocol_send(mc_client->fd, &message, sizeof(message)))
+ xbt_die("Could not send ignored region to MCer");
+ XBT_DEBUG("Sent ignored region to the model-checker");
}
-void MC_remove_ignore_heap(void *address, size_t size)
+// MCed:
+void MC_ignore_heap(void *address, size_t size)
{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+
+ mc_heap_ignore_region_t region = xbt_new0(s_mc_heap_ignore_region_t, 1);
+ region->address = address;
+ region->size = size;
+
+ region->block =
+ ((char *) address -
+ (char *) std_heap->heapbase) / BLOCKSIZE + 1;
+
+ if (std_heap->heapinfo[region->block].type == 0) {
+ region->fragment = -1;
+ std_heap->heapinfo[region->block].busy_block.ignore++;
+ } else {
+ region->fragment =
+ ((uintptr_t) (ADDR2UINT(address) % (BLOCKSIZE))) >> std_heap->
+ heapinfo[region->block].type;
+ std_heap->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
+ }
+
+ MC_heap_region_ignore_insert(region);
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+#if 1
+ if (mc_mode == MC_MODE_CLIENT)
+ MC_heap_region_ignore_send(region);
+#endif
+ mmalloc_set_current_heap(heap);
+}
+
+void MC_remove_ignore_heap(void *address, size_t size)
+{
+ if (mc_mode == MC_MODE_CLIENT) {
+ s_mc_ignore_memory_message_t message;
+ message.type = MC_MESSAGE_UNIGNORE_HEAP;
+ message.addr = address;
+ message.size = size;
+ MC_client_send_message(&message, sizeof(message));
+ }
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
unsigned int cursor = 0;
int start = 0;
xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
MC_remove_ignore_heap(address, size);
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
}
+// MCer
void MC_ignore_global_variable(const char *name)
{
+ mc_process_t process = &mc_model_checker->process;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+ xbt_assert(process->object_infos, "MC subsystem not initialized");
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
- xbt_assert(mc_libsimgrid_info, "MC subsystem not initialized");
-
- unsigned int cursor = 0;
- dw_variable_t current_var;
- int start = 0;
- int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
+ size_t n = process->object_infos_size;
+ for (size_t i=0; i!=n; ++i) {
+ mc_object_info_t info = process->object_infos[i];
- while (start <= end) {
- cursor = (start + end) / 2;
- current_var =
- (dw_variable_t) xbt_dynar_get_as(mc_libsimgrid_info->global_variables,
- cursor, dw_variable_t);
- if (strcmp(current_var->name, name) == 0) {
- xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL);
- start = 0;
- end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
- } else if (strcmp(current_var->name, name) < 0) {
- start = cursor + 1;
- } else {
- end = cursor - 1;
+ // Binary search:
+ int start = 0;
+ int end = xbt_dynar_length(info->global_variables) - 1;
+ while (start <= end) {
+ unsigned int cursor = (start + end) / 2;
+ dw_variable_t current_var =
+ (dw_variable_t) xbt_dynar_get_as(info->global_variables,
+ cursor, dw_variable_t);
+ if (strcmp(current_var->name, name) == 0) {
+ xbt_dynar_remove_at(info->global_variables, cursor, NULL);
+ start = 0;
+ end = xbt_dynar_length(info->global_variables) - 1;
+ } else if (strcmp(current_var->name, name) < 0) {
+ start = cursor + 1;
+ } else {
+ end = cursor - 1;
+ }
}
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
}
/** \brief Ignore a local variable in a scope
{
// Processing of direct variables:
- // If the current subprogram matche the given name:
+ // If the current subprogram matches the given name:
if (!subprogram_name ||
(subprogram->name && strcmp(subprogram_name, subprogram->name) == 0)) {
}
}
+// MCer
void MC_ignore_local_variable(const char *var_name, const char *frame_name)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
+ mc_process_t process = &mc_model_checker->process;
if (strcmp(frame_name, "*") == 0)
frame_name = NULL;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
- MC_SET_MC_HEAP;
-
- MC_ignore_local_variable_in_object(var_name, frame_name, mc_libsimgrid_info);
- if (frame_name != NULL)
- MC_ignore_local_variable_in_object(var_name, frame_name, mc_binary_info);
+ size_t n = process->object_infos_size;
+ size_t i;
+ for (i=0; i!=n; ++i) {
+ MC_ignore_local_variable_in_object(var_name, frame_name, process->object_infos[i]);
+ }
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
+}
+void MC_stack_area_add(stack_region_t stack_area)
+{
+ if (stacks_areas == NULL)
+ stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
+ xbt_dynar_push(stacks_areas, &stack_area);
}
/** @brief Register a stack in the model checker
*
* The stacks are allocated in the heap. The MC handle them especially
- * when we analyse/compare the content of theap so it must be told where
+ * when we analyse/compare the content of the heap so it must be told where
* they are with this function.
*
* @param stack
*/
void MC_new_stack_area(void *stack, smx_process_t process, void *context, size_t size)
{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
- if (stacks_areas == NULL)
- stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
-
- stack_region_t region = NULL;
- region = xbt_new0(s_stack_region_t, 1);
+ stack_region_t region = xbt_new0(s_stack_region_t, 1);
region->address = stack;
- region->process_name = process && process->name ? strdup(process->name) : NULL;
region->context = context;
region->size = size;
region->block =
#endif
region->process_index = -1;
- xbt_dynar_push(stacks_areas, ®ion);
+ if (mc_mode == MC_MODE_CLIENT) {
+ s_mc_stack_region_message_t message;
+ message.type = MC_MESSAGE_STACK_REGION;
+ message.stack_region = *region;
+ MC_client_send_message(&message, sizeof(message));
+ }
+
+ MC_stack_area_add(region);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
}
-void MC_ignore(void *addr, size_t size)
+void MC_process_ignore_memory(mc_process_t process, void *addr, size_t size)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
- if (mc_checkpoint_ignore == NULL)
- mc_checkpoint_ignore =
- xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t),
- checkpoint_ignore_region_free_voidp);
-
+ xbt_dynar_t checkpoint_ignore = process->checkpoint_ignore;
mc_checkpoint_ignore_region_t region =
xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
region->addr = addr;
region->size = size;
- if (xbt_dynar_is_empty(mc_checkpoint_ignore)) {
- xbt_dynar_push(mc_checkpoint_ignore, ®ion);
+ if (xbt_dynar_is_empty(checkpoint_ignore)) {
+ xbt_dynar_push(checkpoint_ignore, ®ion);
} else {
unsigned int cursor = 0;
int start = 0;
- int end = xbt_dynar_length(mc_checkpoint_ignore) - 1;
+ int end = xbt_dynar_length(checkpoint_ignore) - 1;
mc_checkpoint_ignore_region_t current_region = NULL;
while (start <= end) {
cursor = (start + end) / 2;
current_region =
- (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(mc_checkpoint_ignore,
+ (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(checkpoint_ignore,
cursor,
mc_checkpoint_ignore_region_t);
if (current_region->addr == addr) {
if (current_region->size == size) {
checkpoint_ignore_region_free(region);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
} else if (current_region->size < size) {
start = cursor + 1;
if (current_region->addr == addr) {
if (current_region->size < size) {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, ®ion);
} else {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor, ®ion);
}
} else if (current_region->addr < addr) {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, ®ion);
} else {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor, ®ion);
}
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/dynar.h>
+
+#include "mc/datatypes.h"
+#include "mc_process.h"
+
+#include "xbt/misc.h" /* SG_BEGIN_DECL */
+
+SG_BEGIN_DECL();
+
+void MC_heap_region_ignore_insert(mc_heap_ignore_region_t region);
+void MC_process_ignore_memory(mc_process_t process, void *addr, size_t size);
+void MC_stack_area_add(stack_region_t stack_area);
+
+xbt_dynar_t MC_checkpoint_ignore_new(void);
+
+
+SG_END_DECL();
static xbt_dynar_t get_atomic_propositions_values()
{
- int res;
- int_f_void_t f;
unsigned int cursor = 0;
xbt_automaton_propositional_symbol_t ps = NULL;
xbt_dynar_t values = xbt_dynar_new(sizeof(int), NULL);
-
xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps) {
- f = (int_f_void_t) ps->function;
- res = f();
+ int res = xbt_automaton_propositional_symbol_evaluate(ps);
xbt_dynar_push_as(values, int, res);
}
return values;
}
-
-static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair) {
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
mc_visited_pair_t new_pair = NULL;
new_pair = MC_visited_pair_new(pair->num, pair->automaton_state, pair->atomic_propositions, pair->graph_state);
xbt_fifo_shift(mc_stack);
if (dot_output != NULL)
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_global_state->prev_pair, pair_test->num, initial_global_state->prev_req);
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return NULL;
}
}
}
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return new_pair;
-
}
-static void remove_acceptance_pair(int pair_num) {
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+static void remove_acceptance_pair(int pair_num)
+{
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
unsigned int cursor = 0;
mc_visited_pair_t pair_test = NULL;
}
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
}
unsigned int cursor = 0;
xbt_automaton_propositional_symbol_t p = NULL;
xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, p) {
- if (strcmp(p->pred, l->u.predicat) == 0)
+ if (strcmp(xbt_automaton_propositional_symbol_get_name(p), l->u.predicat) == 0)
return (int) xbt_dynar_get_as(atomic_propositions_values, cursor, int);
}
return -1;
if (initial_global_state->raw_mem_set)
MC_SET_MC_HEAP;
-
-
}
-void MC_modelcheck_liveness() {
-
+void MC_modelcheck_liveness()
+{
smx_process_t process = NULL;
mc_pair_t current_pair = NULL;
int value, res, visited_num = -1;
#include <stdint.h>
-#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <dwarf.h>
#include <elfutils/libdw.h>
#include "mc_interface.h"
#include "mc_object_info.h"
#include "mc_forward.h"
+#include "mc_address_space.h"
SG_BEGIN_DECL()
}
}
-void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
-void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
+void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_address_space_t address_space, int process_index);
+void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_address_space_t address_space, int process_index);
void mc_dwarf_expression_clear(mc_expression_t expression);
void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops);
unw_cursor_t* cursor;
void* frame_base;
- mc_snapshot_t snapshot;
+ mc_address_space_t address_space;
mc_object_info_t object_info;
int process_index;
} s_mc_expression_state_t, *mc_expression_state_t;
* @return Process address of the given member of the 'object' struct/class
*/
void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
if (!member->location.size) {
return ((char *) base) + member->offset;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = NULL;
state.cursor = NULL;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.stack_size = 1;
state.stack[0] = (uintptr_t) base;
state.process_index = process_index;
#include <fcntl.h>
#include "xbt/log.h"
+#include "xbt/dynar.h"
+#include "xbt/virtu.h"
#include "mc/mc.h"
#include "mc_object_info.h"
/* It creates the two heap regions: std_heap and mc_heap */
void MC_memory_init()
{
+ if (!malloc_use_mmalloc()) {
+ xbt_die("Model-checking support is not enabled: run with simgrid-mc.");
+ }
+
/* Create the first region HEAP_OFFSET bytes after the heap break address */
std_heap = mmalloc_get_default_md();
xbt_assert(std_heap != NULL);
-#if 0 && defined HAVE_GNU_LD && !defined MMALLOC_WANT_OVERRIDE_LEGACY
- /* use the system malloc for the model-checker data */
- mc_heap = NULL;
-#else
/* Create the second region a page after the first one ends + safety gap */
mc_heap =
xbt_mheap_new_options(-1,
(char *) (std_heap) + STD_HEAP_SIZE + xbt_pagesize,
0);
xbt_assert(mc_heap != NULL);
-#endif
}
/* Finalize the memory subsystem */
#include "xbt_modinter.h"
void MC_memory_exit(void)
{
- MC_free_object_info(&mc_binary_info);
- MC_free_object_info(&mc_libsimgrid_info);
-
- if (mc_heap)
+ if (mc_heap && mc_heap != std_heap)
xbt_mheap_destroy(mc_heap);
}
#ifndef MC_MEMORY_MAP_H
#define MC_MEMORY_MAP_H
+#include <sys/types.h>
+
#include <simgrid_config.h>
#include "mc_forward.h"
};
-void MC_init_memory_map_info(void);
-memory_map_t MC_get_memory_map(void);
+memory_map_t MC_get_memory_map(pid_t pid);
void MC_free_memory_map(memory_map_t map);
SG_END_DECL()
* @return Virtual memory page number of the given address
*/
static inline __attribute__ ((always_inline))
-size_t mc_page_number(void* base, void* address)
+size_t mc_page_number(const void* base, const void* address)
{
xbt_assert(address>=base, "The address is not in the range");
return ((uintptr_t) address - (uintptr_t) base) >> xbt_pagebits;
* @return Offset within the memory page
*/
static inline __attribute__ ((always_inline))
-size_t mc_page_offset(void* address)
+size_t mc_page_offset(const void* address)
{
return ((uintptr_t) address) & (xbt_pagesize-1);
}
* @param page Index of the page
*/
static inline __attribute__ ((always_inline))
-void* mc_page_from_number(void* base, size_t page)
+void* mc_page_from_number(const void* base, size_t page)
{
return (void*) ((char*)base + (page << xbt_pagebits));
}
static inline __attribute__ ((always_inline))
-bool mc_same_page(void* a, void* b)
+bool mc_same_page(const void* a, const void* b)
{
return ((uintptr_t) a >> xbt_pagebits) == ((uintptr_t) b >> xbt_pagebits);
}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "mc_model_checker.h"
+#include "mc_page_store.h"
+
+mc_model_checker_t mc_model_checker = NULL;
+
+mc_model_checker_t MC_model_checker_new(pid_t pid, int socket)
+{
+ mc_model_checker_t mc = xbt_new0(s_mc_model_checker_t, 1);
+ mc->pages = mc_pages_store_new();
+ mc->fd_clear_refs = -1;
+ mc->fd_pagemap = -1;
+ MC_process_init(&mc->process, pid, socket);
+ return mc;
+}
+
+void MC_model_checker_delete(mc_model_checker_t mc)
+{
+ mc_pages_store_delete(mc->pages);
+ if(mc->record)
+ xbt_dynar_free(&mc->record);
+ MC_process_clear(&mc->process);
+}
#ifndef MC_MODEL_CHECKER_H
#define MC_MODEL_CHECKER_H
+#include <sys/types.h>
+
#include <simgrid_config.h>
#include "mc_forward.h"
+#include "mc_process.h"
+#include "mc_page_store.h"
SG_BEGIN_DECL()
int fd_clear_refs;
int fd_pagemap;
xbt_dynar_t record;
+ s_mc_process_t process;
};
-mc_model_checker_t MC_model_checker_new(void);
+mc_model_checker_t MC_model_checker_new(pid_t pid, int socket);
void MC_model_checker_delete(mc_model_checker_t mc);
SG_END_DECL()
--- /dev/null
+#include <stddef.h>
+
+#include <xbt/dynar.h>
+
+#include "mc_object_info.h"
+#include "mc_private.h"
+
+dw_frame_t MC_file_object_info_find_function(mc_object_info_t info, const void *ip)
+{
+ xbt_dynar_t dynar = info->functions_index;
+ mc_function_index_item_t base =
+ (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
+ int i = 0;
+ int j = xbt_dynar_length(dynar) - 1;
+ while (j >= i) {
+ int k = i + ((j - i) / 2);
+ if (ip < base[k].low_pc) {
+ j = k - 1;
+ } else if (ip >= base[k].high_pc) {
+ i = k + 1;
+ } else {
+ return base[k].function;
+ }
+ }
+ return NULL;
+}
+
+dw_variable_t MC_file_object_info_find_variable_by_name(mc_object_info_t info, const char* name)
+{
+ unsigned int cursor = 0;
+ dw_variable_t variable;
+ xbt_dynar_foreach(info->global_variables, cursor, variable){
+ if(!strcmp(name, variable->name))
+ return variable;
+ }
+
+ return NULL;
+}
#define MC_OBJECT_INFO_H
#include <stdint.h>
+#include <stdbool.h>
#include <simgrid_config.h>
#include <xbt/dict.h>
#include "mc_forward.h"
#include "mc_location.h"
+#include "mc_process.h"
+#include "../smpi/private.h"
SG_BEGIN_DECL();
struct s_mc_object_info {
enum mc_object_info_flags flags;
char* file_name;
+ const void* start, *end;
char *start_exec, *end_exec; // Executable segment
char *start_rw, *end_rw; // Read-write segment
char *start_ro, *end_ro; // read-only segment
xbt_dynar_t functions_index;
};
+static inline __attribute__ ((always_inline))
+bool MC_object_info_executable(mc_object_info_t info)
+{
+ return info->flags & MC_OBJECT_INFO_EXECUTABLE;
+}
+
+static inline __attribute__ ((always_inline))
+bool MC_object_info_is_privatized(mc_object_info_t info)
+{
+ return info && MC_object_info_executable(info) && smpi_privatize_global_variables;
+}
+
/** Find the DWARF offset for this ELF object
*
* An offset is applied to address found in DWARF:
void* MC_object_base_address(mc_object_info_t info);
mc_object_info_t MC_new_object_info(void);
-mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable);
+mc_object_info_t MC_find_object_info(memory_map_t maps, const char* name, int executable);
void MC_free_object_info(mc_object_info_t* p);
-void MC_post_process_object_info(mc_object_info_t info);
+dw_frame_t MC_file_object_info_find_function(mc_object_info_t info, const void *ip);
+dw_variable_t MC_file_object_info_find_variable_by_name(mc_object_info_t info, const char* name);
+
+void MC_post_process_object_info(mc_process_t process, mc_object_info_t info);
void MC_dwarf_get_variables(mc_object_info_t info);
void MC_dwarf_get_variables_libdw(mc_object_info_t info);
// Not used:
char* get_type_description(mc_object_info_t info, char *type_name);
-extern mc_object_info_t mc_libsimgrid_info;
-extern mc_object_info_t mc_binary_info;
-extern mc_object_info_t mc_object_infos[2];
-extern size_t mc_object_infos_size;
-
-void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot, int process_index);
+void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_address_space_t snapshot, int process_index);
struct s_dw_variable{
Dwarf_Off dwarf_offset; /* Global offset of the field. */
+#include <unistd.h> // pread, pwrite
+
#include "mc_page_store.h"
#include "mc_mmu.h"
#include "mc_private.h"
* @param reference_pages Snapshot page numbers of the previous soft_dirty_reset (or NULL)
* @return Snapshot page numbers of this new snapshot
*/
-size_t* mc_take_page_snapshot_region(void* data, size_t page_count, uint64_t* pagemap, size_t* reference_pages)
+size_t* mc_take_page_snapshot_region(mc_process_t process,
+ void* data, size_t page_count, uint64_t* pagemap, size_t* reference_pages)
{
size_t* pagenos = (size_t*) malloc(page_count * sizeof(size_t));
+ const bool is_self = MC_process_is_self(process);
+
+ void* temp = NULL;
+ if (!is_self)
+ temp = malloc(xbt_pagesize);
+
for (size_t i=0; i!=page_count; ++i) {
bool softclean = pagemap && !(pagemap[i] & SOFT_DIRTY);
if (softclean && reference_pages) {
// Otherwise, we need to store the page the hard way
// (by reading its content):
void* page = (char*) data + (i << xbt_pagebits);
- pagenos[i] = mc_model_checker->pages->store_page(page);
+ xbt_assert(mc_page_offset(page)==0, "Not at the beginning of a page");
+ void* page_data;
+ if (is_self) {
+ page_data = page;
+ } else {
+ /* Adding another copy (and a syscall) will probably slow things a lot.
+ TODO, optimize this somehow (at least by grouping the syscalls)
+ if needed. Either:
+ - reduce the number of syscalls;
+ - let the application snapshot itself;
+ - move the segments in shared memory (this will break `fork` however).
+ */
+ page_data = temp;
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ temp, page, xbt_pagesize, MC_PROCESS_INDEX_DISABLED);
+ }
+ pagenos[i] = mc_model_checker->pages->store_page(page_data);
}
}
+ free(temp);
return pagenos;
}
* @param pagemap Linux kernel pagemap values fot this region (or NULL)
* @param reference_pages Snapshot page numbers of the previous soft_dirty_reset (or NULL)
*/
-void mc_restore_page_snapshot_region(void* start_addr, size_t page_count, size_t* pagenos, uint64_t* pagemap, size_t* reference_pagenos)
+void mc_restore_page_snapshot_region(mc_process_t process,
+ void* start_addr, size_t page_count, size_t* pagenos, uint64_t* pagemap, size_t* reference_pagenos)
{
for (size_t i=0; i!=page_count; ++i) {
// Otherwise, copy the page:
void* target_page = mc_page_from_number(start_addr, i);
const void* source_page = mc_model_checker->pages->get_page(pagenos[i]);
- memcpy(target_page, source_page, xbt_pagesize);
+ MC_process_write(process, source_page, target_page, xbt_pagesize);
}
}
// ***** High level API
-mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type,
+ void *start_addr, void* permanent_addr, size_t size,
+ mc_mem_region_t ref_reg)
{
- mc_mem_region_t new_reg = xbt_new(s_mc_mem_region_t, 1);
+ mc_process_t process = &mc_model_checker->process;
- new_reg->start_addr = start_addr;
- new_reg->permanent_addr = permanent_addr;
- new_reg->data = NULL;
- new_reg->size = size;
- new_reg->page_numbers = NULL;
+ mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ region->region_type = region_type;
+ region->storage_type = MC_REGION_STORAGE_TYPE_CHUNKED;
+ region->start_addr = start_addr;
+ region->permanent_addr = permanent_addr;
+ region->size = size;
xbt_assert((((uintptr_t)start_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
size_t page_count = mc_page_count(size);
uint64_t* pagemap = NULL;
- if (_sg_mc_soft_dirty && mc_model_checker->parent_snapshot) {
- pagemap = (uint64_t*) mmalloc_no_memset(mc_heap, sizeof(uint64_t) * page_count);
+ if (_sg_mc_soft_dirty && mc_model_checker->parent_snapshot &&
+ MC_process_is_self(process)) {
+ pagemap = (uint64_t*) malloc_no_memset(sizeof(uint64_t) * page_count);
mc_read_pagemap(pagemap, mc_page_number(NULL, permanent_addr), page_count);
}
+ size_t* reg_page_numbers = NULL;
+ if (ref_reg!=NULL && ref_reg->storage_type == MC_REGION_STORAGE_TYPE_CHUNKED)
+ reg_page_numbers = ref_reg->chunked.page_numbers;
+
// Take incremental snapshot:
- new_reg->page_numbers = mc_take_page_snapshot_region(permanent_addr, page_count, pagemap,
- ref_reg==NULL ? NULL : ref_reg->page_numbers);
+ region->chunked.page_numbers = mc_take_page_snapshot_region(process,
+ permanent_addr, page_count, pagemap, reg_page_numbers);
if(pagemap) {
mfree(mc_heap, pagemap);
}
- return new_reg;
+ return region;
}
-void mc_region_restore_sparse(mc_mem_region_t reg, mc_mem_region_t ref_reg)
+void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg, mc_mem_region_t ref_reg)
{
xbt_assert((((uintptr_t)reg->permanent_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
uint64_t* pagemap = NULL;
// Read soft-dirty bits if necessary in order to know which pages have changed:
- if (_sg_mc_soft_dirty && mc_model_checker->parent_snapshot) {
- pagemap = (uint64_t*) mmalloc_no_memset(mc_heap, sizeof(uint64_t) * page_count);
+ if (_sg_mc_soft_dirty && mc_model_checker->parent_snapshot
+ && MC_process_is_self(process)) {
+ pagemap = (uint64_t*) malloc_no_memset(sizeof(uint64_t) * page_count);
mc_read_pagemap(pagemap, mc_page_number(NULL, reg->permanent_addr), page_count);
}
- // Incremental per-page snapshot restoration:
- mc_restore_page_snapshot_region(reg->permanent_addr, page_count, reg->page_numbers,
- pagemap, ref_reg ? ref_reg->page_numbers : NULL);
+ // Incremental per-page snapshot restoration:s
+ size_t* reg_page_numbers = NULL;
+ if (ref_reg && ref_reg->storage_type == MC_REGION_STORAGE_TYPE_CHUNKED)
+ reg_page_numbers = ref_reg->chunked.page_numbers;
+
+ mc_restore_page_snapshot_region(process,
+ reg->permanent_addr, page_count, reg->chunked.page_numbers,
+ pagemap, reg_page_numbers);
if(pagemap) {
free(pagemap);
/** Store a page in memory */
size_t s_mc_pages_store::store_page(void* page)
{
- xbt_assert(mc_page_offset(page)==0, "Not at the beginning of a page");
xbt_assert(top_index_ <= this->capacity_, "top_index is not consistent");
// First, we check if a page with the same content is already in the page
{
xbt_test_add("Init");
size_t pagesize = (size_t) getpagesize();
- std::auto_ptr<s_mc_pages_store_t> store = std::auto_ptr<s_mc_pages_store_t>(new s_mc_pages_store(500));
+ std::unique_ptr<s_mc_pages_store_t> store = std::unique_ptr<s_mc_pages_store_t>(new s_mc_pages_store(500));
void* data = getpage();
xbt_test_assert(store->size()==0, "Bad size");
#ifndef MC_PRIVATE_H
#define MC_PRIVATE_H
+#include <sys/types.h>
+
#include "simgrid_config.h"
#include <stdio.h>
#include <stdint.h>
#include "mc/datatypes.h"
#include "xbt/fifo.h"
#include "xbt/config.h"
+
#include "xbt/function_types.h"
#include "xbt/mmalloc.h"
#include "../simix/smx_private.h"
typedef struct s_mc_function_index_item s_mc_function_index_item_t, *mc_function_index_item_t;
-/****************************** Snapshots ***********************************/
-
-extern xbt_dynar_t mc_checkpoint_ignore;
-
/********************************* MC Global **********************************/
+/** Initialisation of the model-checker
+ *
+ * @param pid PID of the target process
+ * @param socket FD for the communication socket **in server mode** (or -1 otherwise)
+ */
+void MC_init_pid(pid_t pid, int socket);
+
extern FILE *dot_output;
extern const char* colors[13];
extern xbt_parmap_t parmap;
void MC_print_statistics(mc_stats_t stats);
-extern char *libsimgrid_path;
-
/********************************** Snapshot comparison **********************************/
typedef struct s_mc_comparison_times{
double nb_processes_comparison_time;
double bytes_used_comparison_time;
double stacks_sizes_comparison_time;
- double binary_global_variables_comparison_time;
- double libsimgrid_global_variables_comparison_time;
+ double global_variables_comparison_time;
double heap_comparison_time;
double stacks_comparison_time;
}s_mc_comparison_times_t, *mc_comparison_times_t;
/********************************** Variables with DWARF **********************************/
-dw_frame_t MC_find_function_by_ip(void* ip);
-mc_object_info_t MC_ip_find_object_info(void* ip);
-
void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
/********************************** Miscellaneous **********************************/
--- /dev/null
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <regex.h>
+#include <sys/mman.h> // PROT_*
+
+#include <pthread.h>
+
+#include <libgen.h>
+
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include <xbt/mmalloc.h>
+
+#include "mc_process.h"
+#include "mc_object_info.h"
+#include "mc_address_space.h"
+#include "mc_unw.h"
+#include "mc_snapshot.h"
+#include "mc_ignore.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_process, mc,
+ "MC process information");
+
+static void MC_process_init_memory_map_info(mc_process_t process);
+static void MC_process_open_memory_file(mc_process_t process);
+
+// ***** Destructor callbacks
+
+// ***** mc_address_space methods for mc_process
+
+static mc_process_t MC_process_get_process(mc_process_t p) {
+ return p;
+}
+
+static const s_mc_address_space_class_t mc_process_class = {
+ .read = (void*) &MC_process_read,
+ .get_process = (void*) MC_process_get_process
+};
+
+bool MC_is_process(mc_address_space_t p)
+{
+ return p->address_space_class == &mc_process_class;
+}
+
+// ***** mc_process
+
+void MC_process_init(mc_process_t process, pid_t pid, int sockfd)
+{
+ process->address_space.address_space_class = &mc_process_class;
+ process->process_flags = MC_PROCESS_NO_FLAG;
+ process->socket = sockfd;
+ process->pid = pid;
+ if (pid==getpid())
+ process->process_flags |= MC_PROCESS_SELF_FLAG;
+ process->running = true;
+ process->status = 0;
+ process->memory_map = MC_get_memory_map(pid);
+ process->memory_file = -1;
+ process->cache_flags = 0;
+ process->heap = NULL;
+ process->heap_info = NULL;
+ MC_process_init_memory_map_info(process);
+ MC_process_open_memory_file(process);
+
+ // Read std_heap (is a struct mdesc*):
+ dw_variable_t std_heap_var = MC_process_find_variable_by_name(process, "std_heap");
+ if (!std_heap_var)
+ xbt_die("No heap information in the target process");
+ if(!std_heap_var->address)
+ xbt_die("No constant address for this variable");
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &process->heap_address, std_heap_var->address, sizeof(struct mdesc*),
+ MC_PROCESS_INDEX_DISABLED);
+
+ process->checkpoint_ignore = MC_checkpoint_ignore_new();
+
+ process->unw_addr_space = unw_create_addr_space(&mc_unw_accessors , __BYTE_ORDER);
+ if (process->process_flags & MC_PROCESS_SELF_FLAG) {
+ process->unw_underlying_addr_space = unw_local_addr_space;
+ process->unw_underlying_context = NULL;
+ } else {
+ process->unw_underlying_addr_space = unw_create_addr_space(&mc_unw_vmread_accessors, __BYTE_ORDER);
+ process->unw_underlying_context = _UPT_create(pid);
+ }
+}
+
+void MC_process_clear(mc_process_t process)
+{
+ process->address_space.address_space_class = NULL;
+ process->process_flags = MC_PROCESS_NO_FLAG;
+ process->pid = 0;
+
+ MC_free_memory_map(process->memory_map);
+ process->memory_map = NULL;
+
+ process->maestro_stack_start = NULL;
+ process->maestro_stack_end = NULL;
+
+ xbt_dynar_free(&process->checkpoint_ignore);
+
+ size_t i;
+ for (i=0; i!=process->object_infos_size; ++i) {
+ MC_free_object_info(&process->object_infos[i]);
+ }
+ free(process->object_infos);
+ process->object_infos = NULL;
+ process->object_infos_size = 0;
+ if (process->memory_file >= 0) {
+ close(process->memory_file);
+ }
+
+ if (process->unw_underlying_addr_space != unw_local_addr_space) {
+ unw_destroy_addr_space(process->unw_underlying_addr_space);
+ _UPT_destroy(process->unw_underlying_context);
+ }
+ process->unw_underlying_context = NULL;
+ process->unw_underlying_addr_space = NULL;
+
+ unw_destroy_addr_space(process->unw_addr_space);
+ process->unw_addr_space = NULL;
+
+ process->cache_flags = 0;
+
+ free(process->heap);
+ process->heap = NULL;
+
+ free(process->heap_info);
+ process->heap_info = NULL;
+}
+
+void MC_process_refresh_heap(mc_process_t process)
+{
+ assert(!MC_process_is_self(process));
+ // Read/dereference/refresh the std_heap pointer:
+ if (!process->heap) {
+ xbt_mheap_t oldheap = mmalloc_set_current_heap(mc_heap);
+ process->heap = malloc(sizeof(struct mdesc));
+ mmalloc_set_current_heap(oldheap);
+ }
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap, process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_DISABLED
+ );
+}
+
+void MC_process_refresh_malloc_info(mc_process_t process)
+{
+ assert(!MC_process_is_self(process));
+ if (!process->cache_flags & MC_PROCESS_CACHE_FLAG_HEAP)
+ MC_process_refresh_heap(process);
+ // Refresh process->heapinfo:
+ size_t malloc_info_bytesize = process->heap->heaplimit * sizeof(malloc_info);
+
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
+ process->heap_info = (malloc_info*) realloc(process->heap_info,
+ malloc_info_bytesize);
+ mmalloc_set_current_heap(heap);
+
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap_info,
+ process->heap->heapinfo, malloc_info_bytesize,
+ MC_PROCESS_INDEX_DISABLED);
+}
+
+#define SO_RE "\\.so[\\.0-9]*$"
+#define VERSION_RE "-[\\.0-9]*$"
+
+const char* FILTERED_LIBS[] = {
+ "libstdc++",
+ "libc++",
+ "libm",
+ "libgcc_s",
+ "libpthread",
+ "libunwind",
+ "libunwind-x86_64",
+ "libunwind-x86",
+ "libunwind-ptrace",
+ "libdw",
+ "libdl",
+ "librt",
+ "liblzma",
+ "libelf",
+ "libbz2",
+ "libz",
+ "libelf",
+ "libc",
+ "ld"
+};
+
+static bool MC_is_simgrid_lib(const char* libname)
+{
+ return !strcmp(libname, "libsimgrid");
+}
+
+static bool MC_is_filtered_lib(const char* libname)
+{
+ const size_t n = sizeof(FILTERED_LIBS) / sizeof(const char*);
+ size_t i;
+ for (i=0; i!=n; ++i)
+ if (strcmp(libname, FILTERED_LIBS[i])==0)
+ return true;
+ return false;
+}
+
+struct s_mc_memory_map_re {
+ regex_t so_re;
+ regex_t version_re;
+};
+
+static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* res) {
+ const char* map_basename = basename((char*) pathname);
+
+ regmatch_t match;
+ if(regexec(&res->so_re, map_basename, 1, &match, 0))
+ return NULL;
+
+ char* libname = strndup(map_basename, match.rm_so);
+
+ // Strip the version suffix:
+ if(libname && !regexec(&res->version_re, libname, 1, &match, 0)) {
+ char* temp = libname;
+ libname = strndup(temp, match.rm_so);
+ free(temp);
+ }
+
+ return libname;
+}
+
+/** @brief Finds the range of the different memory segments and binary paths */
+static void MC_process_init_memory_map_info(mc_process_t process)
+{
+ XBT_DEBUG("Get debug information ...");
+ process->maestro_stack_start = NULL;
+ process->maestro_stack_end = NULL;
+ process->object_infos = NULL;
+ process->object_infos_size = 0;
+ process->binary_info = NULL;
+ process->libsimgrid_info = NULL;
+
+ struct s_mc_memory_map_re res;
+
+ if(regcomp(&res.so_re, SO_RE, 0) || regcomp(&res.version_re, VERSION_RE, 0))
+ xbt_die(".so regexp did not compile");
+
+ memory_map_t maps = process->memory_map;
+
+ const char* current_name = NULL;
+
+ size_t i = 0;
+ for (i=0; i < maps->mapsize; i++) {
+ map_region_t reg = &(maps->regions[i]);
+ const char* pathname = maps->regions[i].pathname;
+
+ // Nothing to do
+ if (maps->regions[i].pathname == NULL) {
+ current_name = NULL;
+ continue;
+ }
+
+ // [stack], [vvar], [vsyscall], [vdso] ...
+ if (pathname[0] == '[') {
+ if ((reg->prot & PROT_WRITE) && !memcmp(pathname, "[stack]", 7)) {
+ process->maestro_stack_start = reg->start_addr;
+ process->maestro_stack_end = reg->end_addr;
+ }
+ current_name = NULL;
+ continue;
+ }
+
+ if (current_name && strcmp(current_name, pathname)==0)
+ continue;
+
+ current_name = pathname;
+ if (!(reg->prot & PROT_READ) && (reg->prot & PROT_EXEC))
+ continue;
+
+ const bool is_executable = !i;
+ char* libname = NULL;
+ if (!is_executable) {
+ libname = MC_get_lib_name(pathname, &res);
+ if(!libname)
+ continue;
+ if (MC_is_filtered_lib(libname)) {
+ free(libname);
+ continue;
+ }
+ }
+
+ mc_object_info_t info =
+ MC_find_object_info(process->memory_map, pathname, is_executable);
+ process->object_infos = (mc_object_info_t*) realloc(process->object_infos,
+ (process->object_infos_size+1) * sizeof(mc_object_info_t*));
+ process->object_infos[process->object_infos_size] = info;
+ process->object_infos_size++;
+ if (is_executable)
+ process->binary_info = info;
+ else if (libname && MC_is_simgrid_lib(libname))
+ process->libsimgrid_info = info;
+ free(libname);
+ }
+
+ regfree(&res.so_re);
+ regfree(&res.version_re);
+
+ // Resolve time (including accress differents objects):
+ for (i=0; i!=process->object_infos_size; ++i)
+ MC_post_process_object_info(process, process->object_infos[i]);
+
+ xbt_assert(process->maestro_stack_start, "Did not find maestro_stack_start");
+ xbt_assert(process->maestro_stack_end, "Did not find maestro_stack_end");
+
+ XBT_DEBUG("Get debug information done !");
+}
+
+mc_object_info_t MC_process_find_object_info(mc_process_t process, const void *addr)
+{
+ size_t i;
+ for (i = 0; i != process->object_infos_size; ++i) {
+ if (addr >= (void *) process->object_infos[i]->start
+ && addr <= (void *) process->object_infos[i]->end) {
+ return process->object_infos[i];
+ }
+ }
+ return NULL;
+}
+
+mc_object_info_t MC_process_find_object_info_exec(mc_process_t process, const void *addr)
+{
+ size_t i;
+ for (i = 0; i != process->object_infos_size; ++i) {
+ if (addr >= (void *) process->object_infos[i]->start_exec
+ && addr <= (void *) process->object_infos[i]->end_exec) {
+ return process->object_infos[i];
+ }
+ }
+ return NULL;
+}
+
+mc_object_info_t MC_process_find_object_info_rw(mc_process_t process, const void *addr)
+{
+ size_t i;
+ for (i = 0; i != process->object_infos_size; ++i) {
+ if (addr >= (void *) process->object_infos[i]->start_rw
+ && addr <= (void *) process->object_infos[i]->end_rw) {
+ return process->object_infos[i];
+ }
+ }
+ return NULL;
+}
+
+// Functions, variables…
+
+dw_frame_t MC_process_find_function(mc_process_t process, const void *ip)
+{
+ mc_object_info_t info = MC_process_find_object_info_exec(process, ip);
+ if (info == NULL)
+ return NULL;
+ else
+ return MC_file_object_info_find_function(info, ip);
+}
+
+dw_variable_t MC_process_find_variable_by_name(mc_process_t process, const char* name)
+{
+ const size_t n = process->object_infos_size;
+ size_t i;
+ for (i=0; i!=n; ++i) {
+ mc_object_info_t info =process->object_infos[i];
+ dw_variable_t var = MC_file_object_info_find_variable_by_name(info, name);
+ if (var)
+ return var;
+ }
+ return NULL;
+}
+
+// ***** Memory access
+
+int MC_process_vm_open(pid_t pid, int flags)
+{
+ const size_t buffer_size = 30;
+ char buffer[buffer_size];
+ int res = snprintf(buffer, buffer_size, "/proc/%lli/mem", (long long) pid);
+ if (res < 0 || res >= buffer_size) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ return open(buffer, flags);
+}
+
+static void MC_process_open_memory_file(mc_process_t process)
+{
+ if (MC_process_is_self(process) || process->memory_file >= 0)
+ return;
+
+ int fd = MC_process_vm_open(process->pid, O_RDWR);
+ if (fd<0)
+ xbt_die("Could not open file for process virtual address space");
+ process->memory_file = fd;
+}
+
+static ssize_t pread_whole(int fd, void *buf, size_t count, off_t offset)
+{
+ char* buffer = (char*) buf;
+ ssize_t real_count = count;
+ while (count) {
+ ssize_t res = pread(fd, buffer, count, offset);
+ if (res > 0) {
+ count -= res;
+ buffer += res;
+ offset += res;
+ } else if (res==0) {
+ return -1;
+ } else if (errno != EINTR) {
+ return -1;
+ }
+ }
+ return real_count;
+}
+
+static ssize_t pwrite_whole(int fd, const void *buf, size_t count, off_t offset)
+{
+ const char* buffer = (const char*) buf;
+ ssize_t real_count = count;
+ while (count) {
+ ssize_t res = pwrite(fd, buffer, count, offset);
+ if (res > 0) {
+ count -= res;
+ buffer += res;
+ offset += res;
+ } else if (res==0) {
+ return -1;
+ } else if (errno != EINTR) {
+ return -1;
+ }
+ }
+ return real_count;
+}
+
+const void* MC_process_read(mc_process_t process, e_adress_space_read_flags_t flags,
+ void* local, const void* remote, size_t len,
+ int process_index)
+{
+ if (process_index != MC_PROCESS_INDEX_DISABLED) {
+ mc_object_info_t info = MC_process_find_object_info_rw(process, remote);
+ // Segment overlap is not handled.
+ if (MC_object_info_is_privatized(info)) {
+ if (process_index < 0)
+ xbt_die("Missing process index");
+ // Address translation in the privaization segment:
+ size_t offset = (const char*) remote - info->start_rw;
+ remote = (const char*) remote - offset;
+ }
+ }
+
+ if (MC_process_is_self(process)) {
+ if (flags & MC_ADDRESS_SPACE_READ_FLAGS_LAZY)
+ return remote;
+ else {
+ memcpy(local, remote, len);
+ return local;
+ }
+ } else {
+ if (pread_whole(process->memory_file, local, len, (off_t) remote) < 0)
+ xbt_die("Read from process %lli failed", (long long) process->pid);
+ return local;
+ }
+}
+
+void MC_process_write(mc_process_t process, const void* local, void* remote, size_t len)
+{
+ if (MC_process_is_self(process)) {
+ memcpy(remote, local, len);
+ } else {
+ if (pwrite_whole(process->memory_file, local, len, (off_t) remote) < 0)
+ xbt_die("Write to process %lli failed", (long long) process->pid);
+ }
+}
+
+static pthread_once_t zero_buffer_flag = PTHREAD_ONCE_INIT;
+static const void* zero_buffer;
+static const int zero_buffer_size = 10 * 4096;
+
+static void MC_zero_buffer_init(void)
+{
+ int fd = open("/dev/zero", O_RDONLY);
+ if (fd<0)
+ xbt_die("Could not open /dev/zero");
+ zero_buffer = mmap(NULL, zero_buffer_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (zero_buffer == MAP_FAILED)
+ xbt_die("Could not map the zero buffer");
+ close(fd);
+}
+
+void MC_process_clear_memory(mc_process_t process, void* remote, size_t len)
+{
+ if (MC_process_is_self(process)) {
+ memset(remote, 0, len);
+ } else {
+ pthread_once(&zero_buffer_flag, MC_zero_buffer_init);
+ while (len) {
+ size_t s = len > zero_buffer_size ? zero_buffer_size : len;
+ MC_process_write(process, zero_buffer, remote, s);
+ remote = (char*) remote + s;
+ len -= s;
+ }
+ }
+}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_PROCESS_H
+#define MC_PROCESS_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "simgrid_config.h"
+
+#include <sys/types.h>
+
+#include <xbt/mmalloc.h>
+#include "xbt/mmalloc/mmprivate.h"
+
+#include "simix/popping_private.h"
+
+#include "mc_forward.h"
+#include "mc_mmalloc.h" // std_heap
+#include "mc_memory_map.h"
+#include "mc_address_space.h"
+
+SG_BEGIN_DECL()
+
+int MC_process_vm_open(pid_t pid, int flags);
+
+typedef enum {
+ MC_PROCESS_NO_FLAG = 0,
+ MC_PROCESS_SELF_FLAG = 1,
+} e_mc_process_flags_t;
+
+// Those flags are used to track down which cached information
+// is still up to date and which information needs to be updated.
+typedef enum {
+ MC_PROCESS_CACHE_FLAG_HEAP = 1,
+ MC_PROCESS_CACHE_FLAG_MALLOC_INFO = 2,
+} e_mc_process_cache_flags_t ;
+
+/** Representation of a process
+ */
+struct s_mc_process {
+ s_mc_address_space_t address_space;
+ e_mc_process_flags_t process_flags;
+ pid_t pid;
+ int socket;
+ int status;
+ bool running;
+ memory_map_t memory_map;
+ void *maestro_stack_start, *maestro_stack_end;
+ mc_object_info_t libsimgrid_info;
+ mc_object_info_t binary_info;
+ mc_object_info_t* object_infos;
+ size_t object_infos_size;
+ int memory_file;
+
+ // Cache: don't use those fields directly but with the getters
+ // which ensure that proper synchronisation has been done.
+
+ e_mc_process_cache_flags_t cache_flags;
+
+ /** Address of the heap structure in the target process.
+ */
+ void* heap_address;
+
+ /** Copy of the heap structure of the process
+ *
+ * This is refreshed with the `MC_process_refresh` call.
+ * This is not used if the process is the current one:
+ * use `MC_process_get_heap_info` in order to use it.
+ */
+ xbt_mheap_t heap;
+
+ /** Copy of the allocation info structure
+ *
+ * This is refreshed with the `MC_process_refresh` call.
+ * This is not used if the process is the current one:
+ * use `MC_process_get_malloc_info` in order to use it.
+ */
+ malloc_info* heap_info;
+
+ // ***** Libunwind-data
+
+ /** Full-featured MC-aware libunwind address space for the process
+ *
+ * This address space is using a mc_unw_context_t
+ * (with mc_process_t/mc_address_space_t and unw_context_t).
+ */
+ unw_addr_space_t unw_addr_space;
+
+ /** Underlying libunwind addres-space
+ *
+ * The `find_proc_info`, `put_unwind_info`, `get_dyn_info_list_addr`
+ * operations of the native MC address space is currently delegated
+ * to this address space (either the local or a ptrace unwinder).
+ */
+ unw_addr_space_t unw_underlying_addr_space;
+
+ /** The corresponding context
+ */
+ void* unw_underlying_context;
+
+ xbt_dynar_t checkpoint_ignore;
+};
+
+bool MC_is_process(mc_address_space_t p);
+
+void MC_process_init(mc_process_t process, pid_t pid, int sockfd);
+void MC_process_clear(mc_process_t process);
+
+/** Refresh the information about the process
+ *
+ * Do not use direclty, this is used by the getters when appropriate
+ * in order to have fresh data.
+ */
+void MC_process_refresh_heap(mc_process_t process);
+
+/** Refresh the information about the process
+ *
+ * Do not use direclty, this is used by the getters when appropriate
+ * in order to have fresh data.
+ * */
+void MC_process_refresh_malloc_info(mc_process_t process);
+
+static inline
+bool MC_process_is_self(mc_process_t process)
+{
+ return process->process_flags & MC_PROCESS_SELF_FLAG;
+}
+
+/* Process memory access: */
+
+/** Read data from a process memory
+ *
+ * @param process the process
+ * @param local local memory address (destination)
+ * @param remote target process memory address (source)
+ * @param len data size
+ */
+const void* MC_process_read(mc_process_t process,
+ e_adress_space_read_flags_t flags,
+ void* local, const void* remote, size_t len,
+ int process_index);
+
+/** Write data to a process memory
+ *
+ * @param process the process
+ * @param local local memory address (source)
+ * @param remote target process memory address (target)
+ * @param len data size
+ */
+void MC_process_write(mc_process_t process, const void* local, void* remote, size_t len);
+
+void MC_process_clear_memory(mc_process_t process, void* remote, size_t len);
+
+/* Functions, variables of the process: */
+
+mc_object_info_t MC_process_find_object_info(mc_process_t process, const void* addr);
+mc_object_info_t MC_process_find_object_info_exec(mc_process_t process, const void* addr);
+mc_object_info_t MC_process_find_object_info_rw(mc_process_t process, const void* addr);
+
+dw_frame_t MC_process_find_function(mc_process_t process, const void* ip);
+
+static inline xbt_mheap_t MC_process_get_heap(mc_process_t process)
+{
+ if (MC_process_is_self(process))
+ return std_heap;
+ if (!(process->cache_flags & MC_PROCESS_CACHE_FLAG_HEAP))
+ MC_process_refresh_heap(process);
+ return process->heap;
+}
+
+static inline malloc_info* MC_process_get_malloc_info(mc_process_t process)
+{
+ if (MC_process_is_self(process))
+ return std_heap->heapinfo;
+ if (!(process->cache_flags & MC_PROCESS_CACHE_FLAG_MALLOC_INFO))
+ MC_process_refresh_malloc_info(process);
+ return process->heap_info;
+}
+
+/** Find (one occurence of) the named variable definition
+ */
+dw_variable_t MC_process_find_variable_by_name(mc_process_t process, const char* name);
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <xbt/log.h>
+
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_protocol, mc, "Generic MC protocol logic");
+
+int MC_protocol_send(int socket, void* message, size_t size)
+{
+ while (send(socket, message, size, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ return errno;
+ }
+ return 0;
+}
+
+int MC_protocol_send_simple_message(int socket, int type)
+{
+ s_mc_message_t message;
+ message.type = type;
+ return MC_protocol_send(socket, &message, sizeof(message));
+}
+
+int MC_protocol_hello(int socket)
+{
+ int e;
+ if ((e = MC_protocol_send_simple_message(socket, MC_MESSAGE_HELLO)) != 0) {
+ XBT_ERROR("Could not send HELLO message: %s", strerror(e));
+ return 1;
+ }
+
+ s_mc_message_t message;
+ message.type = MC_MESSAGE_NONE;
+
+ size_t s;
+ while ((s = recv(socket, &message, sizeof(message), 0)) == -1) {
+ if (errno == EINTR)
+ continue;
+ else {
+ XBT_ERROR("Could not receive HELLO message: %s", strerror(errno));
+ return 2;
+ }
+ }
+ if (s < sizeof(message) || message.type != MC_MESSAGE_HELLO) {
+ XBT_ERROR("Did not receive suitable HELLO message. Who are you?");
+ return 3;
+ }
+
+ return 0;
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_PROTOCOL_H
+#define MC_PROTOCOL_H
+
+#include <xbt/misc.h>
+
+#include "mc/datatypes.h"
+
+SG_BEGIN_DECL()
+
+// ***** Environment variables for passing context to the model-checked process
+
+/** Environment variable name set by `simgrid-mc` to enable MC support in the
+ * children MC processes
+ */
+#define MC_ENV_VARIABLE "SIMGRIC_MC"
+
+/** Environment variable name used to pass the communication socket */
+#define MC_ENV_SOCKET_FD "SIMGRID_MC_SOCKET_FD"
+
+// ***** MC mode
+
+typedef enum {
+ MC_MODE_NONE = 0,
+ MC_MODE_STANDALONE,
+ MC_MODE_CLIENT,
+ MC_MODE_SERVER
+} e_mc_mode_t;
+
+extern e_mc_mode_t mc_mode;
+
+// ***** Messages
+
+typedef enum {
+ MC_MESSAGE_NONE,
+ MC_MESSAGE_HELLO,
+ MC_MESSAGE_CONTINUE,
+ MC_MESSAGE_IGNORE_HEAP,
+ MC_MESSAGE_UNIGNORE_HEAP,
+ MC_MESSAGE_IGNORE_MEMORY,
+ MC_MESSAGE_STACK_REGION,
+ MC_MESSAGE_REGISTER_SYMBOL,
+} e_mc_message_type;
+
+#define MC_MESSAGE_LENGTH 512
+
+/** Basic structure for a MC message
+ *
+ * The current version of the client/server protocol sends C structures over `AF_LOCAL`
+ * `SOCK_DGRAM` sockets. This means that the protocol is ABI/architecture specific:
+ * we currently can't model-check a x86 process from a x86_64 process.
+ *
+ * Moreover the protocol is not stable. The same version of the library should be used
+ * for the client and the server.
+ *
+ * This is the basic structure shared by all messages: all message start with a message
+ * type.
+ */
+typedef struct s_mc_message {
+ e_mc_message_type type;
+} s_mc_message_t, *mc_message_t;
+
+typedef struct s_mc_ignore_heap_message {
+ e_mc_message_type type;
+ s_mc_heap_ignore_region_t region;
+} s_mc_ignore_heap_message_t, *mc_ignore_heap_message_t;
+
+typedef struct s_mc_ignore_memory_message {
+ e_mc_message_type type;
+ void *addr;
+ size_t size;
+} s_mc_ignore_memory_message_t, *mc_ignore_memory_message_t;
+
+typedef struct s_mc_stack_region_message {
+ e_mc_message_type type;
+ s_stack_region_t stack_region;
+} s_mc_stack_region_message_t, *mc_stack_region_message_t;
+
+typedef struct s_mc_register_symbol_message {
+ e_mc_message_type type;
+ char name[128];
+ int (*callback)(void*);
+ void* data;
+} s_mc_register_symbol_message_t, * mc_register_symbol_message_t;
+
+int MC_protocol_send(int socket, void* message, size_t size);
+int MC_protocol_send_simple_message(int socket, int type);
+int MC_protocol_hello(int socket);
+
+SG_END_DECL()
+
+#endif
*/
void MC_pre_modelcheck_safety()
{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
mc_state_t initial_state = NULL;
smx_process_t process;
- /* Create the initial state and push it into the exploration stack */
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
if (_sg_mc_visited > 0)
visited_states = xbt_dynar_new(sizeof(mc_visited_state_t), visited_state_free_voidp);
}
xbt_fifo_unshift(mc_stack, initial_state);
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <memory>
+#include <system_error>
+
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/signalfd.h>
+
+#include <xbt/log.h>
+
+#include "mc_model_checker.h"
+#include "mc_protocol.h"
+#include "mc_server.h"
+#include "mc_private.h"
+#include "mc_ignore.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_server, mc, "MC server logic");
+
+// HArdcoded index for now:
+#define SOCKET_FD_INDEX 0
+#define SIGNAL_FD_INDEX 1
+
+mc_server_t mc_server;
+
+struct mc_symbol_pointer_callback
+{
+ mc_process_t process;
+ void* value;
+};
+
+static int mc_symbol_pointer_callback_evaluate(void* p)
+{
+ struct mc_symbol_pointer_callback* callback = (struct mc_symbol_pointer_callback*) p;
+ int value;
+ MC_process_read(callback->process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &value, callback->value, sizeof(value), MC_PROCESS_INDEX_ANY);
+ return value;
+}
+
+s_mc_server::s_mc_server(pid_t pid, int socket)
+{
+ this->pid = pid;
+ this->socket = socket;
+}
+
+void s_mc_server::start()
+{
+ /* Wait for the target process to initialize and exchange a HELLO messages
+ * before trying to look at its memory map.
+ */
+ XBT_DEBUG("Greeting the MC client");
+ int res = MC_protocol_hello(socket);
+ if (res != 0)
+ throw std::system_error(res, std::system_category());
+ XBT_DEBUG("Greeted the MC client");
+
+ // Block SIGCHLD (this will be handled with accept/signalfd):
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
+ throw std::system_error(errno, std::system_category());
+
+ sigset_t full_set;
+ sigfillset(&full_set);
+
+ // Prepare data for poll:
+
+ struct pollfd* socket_pollfd = &fds[SOCKET_FD_INDEX];
+ socket_pollfd->fd = socket;
+ socket_pollfd->events = POLLIN;
+ socket_pollfd->revents = 0;
+
+ int signal_fd = signalfd(-1, &set, 0);
+ if (signal_fd == -1)
+ throw std::system_error(errno, std::system_category());
+
+ struct pollfd* signalfd_pollfd = &fds[SIGNAL_FD_INDEX];
+ signalfd_pollfd->fd = signal_fd;
+ signalfd_pollfd->events = POLLIN;
+ signalfd_pollfd->revents = 0;
+}
+
+void s_mc_server::shutdown()
+{
+ XBT_DEBUG("Shuting down model-checker");
+
+ mc_process_t process = &mc_model_checker->process;
+ int status = process->status;
+ if (process->running) {
+ XBT_DEBUG("Killing process");
+ kill(process->pid, SIGTERM);
+ if (waitpid(process->pid, &status, 0) == -1)
+ throw std::system_error(errno, std::system_category());
+ // TODO, handle the case when the process does not want to die with a timeout
+ process->status = status;
+ }
+}
+
+void s_mc_server::exit()
+{
+ // Finished:
+ int status = mc_model_checker->process.status;
+ if (WIFEXITED(status))
+ ::exit(WEXITSTATUS(status));
+ else if (WIFSIGNALED(status)) {
+ // Try to uplicate the signal of the model-checked process.
+ // This is a temporary hack so we don't try too hard.
+ kill(mc_model_checker->process.pid, WTERMSIG(status));
+ abort();
+ } else {
+ xbt_die("Unexpected status from model-checked process");
+ }
+}
+
+void s_mc_server::resume(mc_process_t process)
+{
+ int socket = process->socket;
+ int res = MC_protocol_send_simple_message(socket, MC_MESSAGE_CONTINUE);
+ if (res)
+ throw std::system_error(res, std::system_category());
+}
+
+static
+void throw_socket_error(int fd)
+{
+ int error = 0;
+ socklen_t errlen = sizeof(error);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen) == -1)
+ error = errno;
+ throw std::system_error(error, std::system_category());
+}
+
+void s_mc_server::handle_events()
+{
+ char buffer[MC_MESSAGE_LENGTH];
+ struct pollfd* socket_pollfd = &fds[SOCKET_FD_INDEX];
+ struct pollfd* signalfd_pollfd = &fds[SIGNAL_FD_INDEX];
+
+ while(poll(fds, 2, -1) == -1) {
+ switch(errno) {
+ case EINTR:
+ continue;
+ default:
+ throw std::system_error(errno, std::system_category());
+ }
+ }
+
+ if (socket_pollfd->revents) {
+ if (socket_pollfd->revents & POLLIN) {
+
+ ssize_t size = recv(socket_pollfd->fd, buffer, sizeof(buffer), MSG_DONTWAIT);
+ if (size == -1 && errno != EAGAIN)
+ throw std::system_error(errno, std::system_category());
+
+ s_mc_message_t base_message;
+ if (size < (ssize_t) sizeof(base_message))
+ xbt_die("Broken message");
+ memcpy(&base_message, buffer, sizeof(base_message));
+
+ switch(base_message.type) {
+
+ case MC_MESSAGE_IGNORE_HEAP:
+ {
+ XBT_DEBUG("Received ignored region");
+ s_mc_ignore_heap_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken messsage");
+ memcpy(&message, buffer, sizeof(message));
+ mc_heap_ignore_region_t region = xbt_new(s_mc_heap_ignore_region_t, 1);
+ *region = message.region;
+ MC_heap_region_ignore_insert(region);
+ break;
+ }
+
+
+ case MC_MESSAGE_UNIGNORE_HEAP:
+ {
+ XBT_DEBUG("Received unignored region");
+ s_mc_ignore_memory_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken messsage");
+ memcpy(&message, buffer, sizeof(message));
+ MC_remove_ignore_heap(message.addr, message.size);
+ break;
+ }
+
+ case MC_MESSAGE_IGNORE_MEMORY:
+ {
+ XBT_DEBUG("Received ignored memory");
+ s_mc_ignore_memory_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken messsage");
+ memcpy(&message, buffer, sizeof(message));
+ MC_process_ignore_memory(&mc_model_checker->process,
+ message.addr, message.size);
+ break;
+ }
+
+ case MC_MESSAGE_STACK_REGION:
+ {
+ XBT_DEBUG("Received stack area");
+ s_mc_stack_region_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken messsage");
+ memcpy(&message, buffer, sizeof(message));
+ stack_region_t stack_region = xbt_new(s_stack_region_t, 1);
+ *stack_region = message.stack_region;
+ MC_stack_area_add(stack_region);
+ }
+ break;
+
+ case MC_MESSAGE_REGISTER_SYMBOL:
+ {
+ s_mc_register_symbol_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken message");
+ memcpy(&message, buffer, sizeof(message));
+ if (message.callback)
+ xbt_die("Support for callbacks/functions symbols not implemented in client/server mode.");
+ XBT_DEBUG("Received symbol: %s", message.name);
+
+ struct mc_symbol_pointer_callback* callback = xbt_new(struct mc_symbol_pointer_callback, 1);
+ callback->process = &mc_model_checker->process;
+ callback->value = message.data;
+
+ MC_automaton_new_propositional_symbol_callback(message.name,
+ mc_symbol_pointer_callback_evaluate, callback, free);
+ break;
+ }
+
+ default:
+ xbt_die("Unexpected message from model-checked application");
+
+ }
+ return;
+ }
+ if (socket_pollfd->revents & POLLERR) {
+ throw_socket_error(socket_pollfd->fd);
+ }
+ if (socket_pollfd->revents & POLLHUP)
+ xbt_die("Socket hang up?");
+ }
+
+ if (signalfd_pollfd->revents) {
+ if (signalfd_pollfd->revents & POLLIN) {
+ this->handle_signals();
+ return;
+ }
+ if (signalfd_pollfd->revents & POLLERR) {
+ throw_socket_error(signalfd_pollfd->fd);
+ }
+ if (signalfd_pollfd->revents & POLLHUP)
+ xbt_die("Signalfd hang up?");
+ }
+}
+
+void s_mc_server::loop()
+{
+ while (mc_model_checker->process.running)
+ this->handle_events();
+}
+
+void s_mc_server::handle_signals()
+{
+ struct signalfd_siginfo info;
+ struct pollfd* signalfd_pollfd = &fds[SIGNAL_FD_INDEX];
+ while (1) {
+ ssize_t size = read(signalfd_pollfd->fd, &info, sizeof(info));
+ if (size == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ throw std::system_error(errno, std::system_category());
+ } else if (size != sizeof(info))
+ return throw std::runtime_error(
+ "Bad communication with model-checked application");
+ else
+ break;
+ }
+ this->on_signal(&info);
+}
+
+void s_mc_server::handle_waitpid()
+{
+ XBT_DEBUG("Check for wait event");
+ int status;
+ pid_t pid;
+ while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
+ if (pid == -1) {
+ if (errno == ECHILD) {
+ // No more children:
+ if (mc_model_checker->process.running)
+ xbt_die("Inconsistent state");
+ else
+ break;
+ } else {
+ XBT_ERROR("Could not wait for pid: %s", strerror(errno));
+ throw std::system_error(errno, std::system_category());
+ }
+ }
+
+ if (pid == mc_model_checker->process.pid) {
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ XBT_DEBUG("Child process is over");
+ mc_model_checker->process.status = status;
+ mc_model_checker->process.running = false;
+ }
+ }
+ }
+}
+
+void s_mc_server::on_signal(const struct signalfd_siginfo* info)
+{
+ switch(info->ssi_signo) {
+ case SIGCHLD:
+ this->handle_waitpid();
+ break;
+ default:
+ break;
+ }
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_SERVER_H
+#define MC_SERVER_H
+
+#include <xbt/misc.h>
+
+SG_BEGIN_DECL()
+
+#define MC_SERVER_ERROR 127
+
+typedef struct s_mc_server s_mc_server_t, *mc_server_t;
+
+extern mc_server_t mc_server;
+
+SG_END_DECL()
+
+#ifdef __cplusplus
+
+struct s_mc_server {
+private:
+ pid_t pid;
+ int socket;
+ struct pollfd fds[2];
+public:
+ s_mc_server(pid_t pid, int socket);
+ void start();
+ void shutdown();
+ void exit();
+ void resume(mc_process_t process);
+ void loop();
+ void handle_events();
+protected:
+ void handle_signals();
+ void handle_waitpid();
+ void on_signal(const struct signalfd_siginfo* info);
+};
+
+#endif
+
+#endif
* @param Snapshot region in the snapshot this pointer belongs to
* (or NULL if it does not belong to any snapshot region)
* */
-mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int process_index)
+mc_mem_region_t mc_get_snapshot_region(const void* addr, mc_snapshot_t snapshot, int process_index)
{
-#ifdef HAVE_SMPI
- if (snapshot->privatization_regions) {
-
- if (process_index < 0) {
+ size_t n = snapshot->snapshot_regions_count;
+ for (size_t i = 0; i != n; ++i) {
+ mc_mem_region_t region = snapshot->snapshot_regions[i];
+ if (!(region && mc_region_contain(region, addr)))
+ continue;
- mc_mem_region_t region = snapshot->privatization_regions[0];
- if( mc_region_contain(region, addr) ) {
+ if (region->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+#ifdef HAVE_SMPI
+ // Use the current process index of the snapshot:
+ if (process_index == MC_PROCESS_INDEX_DISABLED) {
+ process_index = snapshot->privatization_index;
+ }
+ if (process_index < 0) {
xbt_die("Missing process index");
}
-
- } else {
- if (process_index >= smpi_process_count()) {
+ if (process_index >= region->privatized.regions_count) {
xbt_die("Invalid process index");
}
-
- mc_mem_region_t region = snapshot->privatization_regions[process_index];
- if( mc_region_contain(region, addr) ) {
- return region;
- }
-
- }
- }
+ mc_mem_region_t priv_region = region->privatized.regions[process_index];
+ xbt_assert(mc_region_contain(priv_region, addr));
+ return priv_region;
+#else
+ xbt_die("Privatized region in a non SMPI build (this should not happen)");
#endif
-
- for (size_t i = 0; i != NB_REGIONS; ++i) {
- mc_mem_region_t region = snapshot->regions[i];
- if ( region && mc_region_contain(region, addr) ) {
- return region;
}
+
+ return region;
}
return NULL;
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer of original location)
*/
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
// Last byte of the memory area:
void* end = (char*) addr + size - 1;
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer or original location)
*/
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size)
+const void* MC_snapshot_read(
+ mc_snapshot_t snapshot, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index)
{
- if (snapshot) {
- mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
- return mc_snapshot_read_region(addr, region, target, size);
- } else {
- return addr;
- }
+ mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
+ if (region)
+ return MC_region_read(region, target, addr, size);
+ else
+ return MC_process_read(snapshot->process, flags, target, addr, size, process_index);
}
/** Compare memory between snapshots (with known regions)
* @param snapshot2 Region of the address in the second snapshot
* @return same as memcmp
* */
-int mc_snapshot_region_memcmp(
- void* addr1, mc_mem_region_t region1,
- void* addr2, mc_mem_region_t region2,
+int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2,
size_t size)
{
// Using alloca() for large allocations may trigger stack overflow:
// use malloc if the buffer is too big.
bool stack_alloc = size < 64;
- void* buffer1a = (region1==NULL || region1->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
- void* buffer2a = (region2==NULL || region2->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
- void* buffer1 = mc_snapshot_read_region(addr1, region1, buffer1a, size);
- void* buffer2 = mc_snapshot_read_region(addr2, region2, buffer2a, size);
+ const bool region1_need_buffer = region1==NULL || region1->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+ const bool region2_need_buffer = region2==NULL || region2->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+ void* buffer1a = region1_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+ void* buffer2a = region2_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+ const void* buffer1 = MC_region_read(region1, buffer1a, addr1, size);
+ const void* buffer2 = MC_region_read(region2, buffer2a, addr2, size);
int res;
if (buffer1 == buffer2) {
res = 0;
* @param snapshot2 Second snapshot
* @return same as memcmp
* */
-int mc_snapshot_memcmp(
- void* addr1, mc_snapshot_t snapshot1,
- void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
+int MC_snapshot_memcmp(
+ const void* addr1, mc_snapshot_t snapshot1,
+ const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
{
mc_mem_region_t region1 = mc_get_snapshot_region(addr1, snapshot1, process_index);
mc_mem_region_t region2 = mc_get_snapshot_region(addr2, snapshot2, process_index);
- return mc_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
+ return MC_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
}
#ifdef SIMGRID_TEST
// Init memory and take snapshots:
init_memory(source, byte_size);
- mc_mem_region_t region0 = mc_region_new_sparse(0, source, source, byte_size, NULL);
+ mc_mem_region_t region0 = mc_region_new_sparse(MC_REGION_TYPE_UNKNOWN, source, source, byte_size, NULL);
for(int i=0; i<n; i+=2) {
init_memory((char*) source + i*xbt_pagesize, xbt_pagesize);
}
- mc_mem_region_t region = mc_region_new_sparse(0, source, source, byte_size, NULL);
+ mc_mem_region_t region = mc_region_new_sparse(MC_REGION_TYPE_UNKNOWN, source, source, byte_size, NULL);
void* destination = mmap(NULL, byte_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
xbt_assert(source!=MAP_FAILED, "Could not allocate destination memory");
xbt_test_add("Reading whole region data for %i page(s)", n);
- void* read = mc_snapshot_read_region(source, region, destination, byte_size);
- xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in mc_snapshot_read_region()");
+ const void* read = MC_region_read(region, source, destination, byte_size);
+ xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in MC_region_read()");
xbt_test_add("Reading parts of region data for %i page(s)", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- void* read = mc_snapshot_read_region((char*) source+offset, region, destination, size);
+ const void* read = MC_region_read(region, destination, (const char*) source+offset, size);
xbt_test_assert(!memcmp((char*) source+offset, read, size),
- "Mismatch in mc_snapshot_read_region()");
+ "Mismatch in MC_region_read()");
}
xbt_test_add("Compare whole region data for %i page(s)", n);
- xbt_test_assert(!mc_snapshot_region_memcmp(source, NULL, source, region, byte_size),
- "Mismatch in mc_snapshot_region_memcmp() for the whole region");
- xbt_test_assert(mc_snapshot_region_memcmp(source, region0, source, region, byte_size),
- "Unexpected match in mc_snapshot_region_memcmp() with previous snapshot");
+ xbt_test_assert(!MC_snapshot_region_memcmp(source, NULL, source, region, byte_size),
+ "Mismatch in MC_snapshot_region_memcmp() for the whole region");
+ xbt_test_assert(MC_snapshot_region_memcmp(source, region0, source, region, byte_size),
+ "Unexpected match in MC_snapshot_region_memcmp() with previous snapshot");
xbt_test_add("Compare parts of region data for %i page(s) with current value", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
xbt_test_add("Compare parts of region data for %i page(s) with itself", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
if (n==1) {
xbt_test_add("Read pointer for %i page(s)", n);
memcpy(source, &mc_model_checker, sizeof(void*));
- mc_mem_region_t region2 = mc_region_new_sparse(0, source, source, byte_size, NULL);
- xbt_test_assert(mc_snapshot_read_pointer_region(source, region2) == mc_model_checker,
- "Mismtach in mc_snapshot_read_pointer_region()");
+ mc_mem_region_t region2 = mc_region_new_sparse(MC_REGION_TYPE_UNKNOWN, source, source, byte_size, NULL);
+ xbt_test_assert(MC_region_read_pointer(region2, source) == mc_model_checker,
+ "Mismtach in MC_region_read_pointer()");
MC_region_destroy(region2);
}
#include "mc_model_checker.h"
#include "mc_page_store.h"
#include "mc_mmalloc.h"
+#include "mc_address_space.h"
+#include "mc_unw.h"
SG_BEGIN_DECL()
// ***** Snapshot region
-#define NB_REGIONS 3 /* binary data (data + BSS) (type = 2), libsimgrid data (data + BSS) (type = 1), std_heap (type = 0)*/
+typedef enum e_mc_region_type_t {
+ MC_REGION_TYPE_UNKNOWN = 0,
+ MC_REGION_TYPE_HEAP = 1,
+ MC_REGION_TYPE_DATA = 2
+} mc_region_type_t;
+
+// TODO, use OO instead of this
+typedef enum e_mc_region_storeage_type_t {
+ MC_REGION_STORAGE_TYPE_NONE = 0,
+ MC_REGION_STORAGE_TYPE_FLAT = 1,
+ MC_REGION_STORAGE_TYPE_CHUNKED = 2,
+ MC_REGION_STORAGE_TYPE_PRIVATIZED = 3
+} mc_region_storage_type_t;
/** @brief Copy/snapshot of a given memory region
*
- * Two types of region snapshots exist:
+ * Different types of region snapshot storage types exist:
* <ul>
* <li>flat/dense snapshots are a simple copy of the region;</li>
* <li>sparse/per-page snapshots are snaapshots which shared
* identical pages.</li>
+ * <li>privatized (SMPI global variable privatisation).
* </ul>
+ *
+ * This is handled with a variant based approch:
+ *
+ * * `storage_type` identified the type of storage;
+ * * an anonymous enum is used to distinguish the relevant types for
+ * each type.
*/
-typedef struct s_mc_mem_region{
+typedef struct s_mc_mem_region s_mc_mem_region_t, *mc_mem_region_t;
+
+struct s_mc_mem_region {
+ mc_region_type_t region_type;
+ mc_region_storage_type_t storage_type;
+ mc_object_info_t object_info;
+
/** @brief Virtual address of the region in the simulated process */
void *start_addr;
+ /** @brief Size of the data region in bytes */
+ size_t size;
+
/** @brief Permanent virtual address of the region
*
* This is usually the same address as the simuilated process address.
* */
void *permanent_addr;
- /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
- void *data;
+ union {
+ struct {
+ /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
+ void *data;
+ } flat;
+ struct {
+ /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
+ size_t* page_numbers;
+ } chunked;
+ struct {
+ size_t regions_count;
+ mc_mem_region_t* regions;
+ } privatized;
+ };
- /** @brief Size of the data region in bytes */
- size_t size;
-
- /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
- size_t* page_numbers;
-
-} s_mc_mem_region_t, *mc_mem_region_t;
+};
-mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* data_addr, size_t size, mc_mem_region_t ref_reg);
+mc_mem_region_t mc_region_new_sparse(mc_region_type_t type, void *start_addr, void* data_addr, size_t size, mc_mem_region_t ref_reg);
void MC_region_destroy(mc_mem_region_t reg);
-void mc_region_restore_sparse(mc_mem_region_t reg, mc_mem_region_t ref_reg);
+void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg, mc_mem_region_t ref_reg);
static inline __attribute__ ((always_inline))
-bool mc_region_contain(mc_mem_region_t region, void* p)
+bool mc_region_contain(mc_mem_region_t region, const void* p)
{
return p >= region->start_addr &&
p < (void*)((char*) region->start_addr + region->size);
void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region)
{
size_t pageno = mc_page_number(region->start_addr, (void*) addr);
- size_t snapshot_pageno = region->page_numbers[pageno];
+ size_t snapshot_pageno = region->chunked.page_numbers[pageno];
const void* snapshot_page = mc_page_store_get_page(mc_model_checker->pages, snapshot_pageno);
return (char*) snapshot_page + mc_page_offset((void*) addr);
}
-mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int process_index);
+mc_mem_region_t mc_get_snapshot_region(const void* addr, mc_snapshot_t snapshot, int process_index);
/** \brief Translate a pointer from process address space to snapshot address space
*
return (void *) addr;
}
- // Flat snapshot:
- else if (region->data) {
- uintptr_t offset = addr - (uintptr_t) region->start_addr;
- return (void *) ((uintptr_t) region->data + offset);
- }
+ switch (region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ default:
+ xbt_die("Storage type not supported");
+
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ {
+ uintptr_t offset = addr - (uintptr_t) region->start_addr;
+ return (void *) ((uintptr_t) region->flat.data + offset);
+ }
- // Per-page snapshot:
- else if (region->page_numbers) {
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
return mc_translate_address_region(addr, region);
- }
- else {
- xbt_die("No data for this memory region");
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ {
+ xbt_assert(process_index >=0,
+ "Missing process index for privatized region");
+ xbt_assert((size_t) process_index < region->privatized.regions_count,
+ "Out of range process index");
+ mc_mem_region_t subregion = region->privatized.regions[process_index];
+ xbt_assert(subregion, "Missing memory region for process %i", process_index);
+ return mc_translate_address(addr, snapshot, process_index);
+ }
}
}
int flags;
}s_fd_infos_t, *fd_infos_t;
-struct s_mc_snapshot{
+struct s_mc_snapshot {
+ mc_process_t process;
+ s_mc_address_space_t address_space;
size_t heap_bytes_used;
- mc_mem_region_t regions[NB_REGIONS];
+ mc_mem_region_t* snapshot_regions;
+ size_t snapshot_regions_count;
xbt_dynar_t enabled_processes;
- mc_mem_region_t* privatization_regions;
int privatization_index;
size_t *stack_sizes;
xbt_dynar_t stacks;
fd_infos_t *current_fd;
};
-/** @brief Process index used when no process is available
- *
- * The expected behaviour is that if a process index is needed it will fail.
- * */
-#define MC_NO_PROCESS_INDEX -1
-
-/** @brief Process index when any process is suitable
- *
- * We could use a special negative value in the future.
- */
-#define MC_ANY_PROCESS_INDEX 0
-
static inline __attribute__ ((always_inline))
mc_mem_region_t mc_get_region_hinted(void* addr, mc_snapshot_t snapshot, int process_index, mc_mem_region_t region)
{
typedef struct s_mc_snapshot_stack{
xbt_dynar_t local_variables;
+ mc_unw_context_t context;
xbt_dynar_t stack_frames; // mc_stack_frame_t
int process_index;
}s_mc_snapshot_stack_t, *mc_snapshot_stack_t;
-typedef struct s_mc_global_t{
+typedef struct s_mc_global_t {
mc_snapshot_t snapshot;
int raw_mem_set;
int prev_pair;
size_t size;
}s_mc_checkpoint_ignore_region_t, *mc_checkpoint_ignore_region_t;
-static void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
+static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
mc_snapshot_t MC_take_snapshot(int num_state);
void MC_restore_snapshot(mc_snapshot_t);
int mc_important_snapshot(mc_snapshot_t snapshot);
-size_t* mc_take_page_snapshot_region(void* data, size_t page_count, uint64_t* pagemap, size_t* reference_pages);
+size_t* mc_take_page_snapshot_region(mc_process_t process,
+ void* data, size_t page_count, uint64_t* pagemap, size_t* reference_pages);
void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count);
-void mc_restore_page_snapshot_region(void* start_addr, size_t page_count, size_t* pagenos, uint64_t* pagemap, size_t* reference_pagenos);
-
-static inline __attribute__((always_inline))
-bool mc_snapshot_region_linear(mc_mem_region_t region) {
- return !region || !region->data;
-}
-
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size);
-
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size);
-int mc_snapshot_region_memcmp(
- void* addr1, mc_mem_region_t region1,
- void* addr2, mc_mem_region_t region2, size_t size);
-int mc_snapshot_memcmp(
- void* addr1, mc_snapshot_t snapshot1,
- void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size);
-
-static void* mc_snapshot_read_pointer(void* addr, mc_snapshot_t snapshot, int process_index);
+void mc_restore_page_snapshot_region(
+ mc_process_t process,
+ void* start_addr, size_t page_count, size_t* pagenos,
+ uint64_t* pagemap, size_t* reference_pagenos);
+
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size);
+
+const void* MC_snapshot_read(mc_snapshot_t snapshot, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index);
+int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2, size_t size);
+int MC_snapshot_memcmp(
+ const void* addr1, mc_snapshot_t snapshot1,
+ const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size);
static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer(void* addr, mc_snapshot_t snapshot, int process_index)
+const void* MC_snapshot_read_pointer(mc_snapshot_t snapshot, const void* addr, int process_index)
{
void* res;
- return *(void**) mc_snapshot_read(addr, snapshot, process_index, &res, sizeof(void*));
+ return *(const void**) MC_snapshot_read(snapshot, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ &res, addr, sizeof(void*), process_index);
}
static inline __attribute__ ((always_inline))
- void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot) {
+const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot)
+{
if(snapshot==NULL)
xbt_die("snapshot is NULL");
- void** addr = &(std_heap->breakval);
- return mc_snapshot_read_pointer(addr, snapshot, MC_ANY_PROCESS_INDEX);
+ // This is &std_heap->breakval in the target process:
+ void** addr = &MC_process_get_heap(&mc_model_checker->process)->breakval;
+ // Read (std_heap->breakval) in the target process (*addr i.e. std_heap->breakval):
+ return MC_snapshot_read_pointer(snapshot, addr, MC_PROCESS_INDEX_ANY);
}
/** @brief Read memory from a snapshot region
* @return Pointer where the data is located (target buffer of original location)
*/
static inline __attribute__((always_inline))
-void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
if (region==NULL)
+ // Should be deprecated:
return addr;
uintptr_t offset = (char*) addr - (char*) region->start_addr;
xbt_assert(mc_region_contain(region, addr),
"Trying to read out of the region boundary.");
- // Linear memory region:
- if (region->data) {
- return (char*) region->data + offset;
- }
-
- // Fragmented memory region:
- else if (region->page_numbers) {
- // Last byte of the region:
- void* end = (char*) addr + size - 1;
- if( mc_same_page(addr, end) ) {
- // The memory is contained in a single page:
- return mc_translate_address_region((uintptr_t) addr, region);
- } else {
- // The memory spans several pages:
- return mc_snapshot_read_fragmented(addr, region, target, size);
+ switch (region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ default:
+ xbt_die("Storage type not supported");
+
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ return (char*) region->flat.data + offset;
+
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
+ {
+ // Last byte of the region:
+ void* end = (char*) addr + size - 1;
+ if (mc_same_page(addr, end) ) {
+ // The memory is contained in a single page:
+ return mc_translate_address_region((uintptr_t) addr, region);
+ } else {
+ // The memory spans several pages:
+ return MC_region_read_fragmented(region, target, addr, size);
+ }
}
- }
- else {
- xbt_die("No data available for this region");
+ // We currently do not pass the process_index to this function so we assume
+ // that the privatized region has been resolved in the callers:
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ xbt_die("Storage type not supported");
}
}
static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer_region(void* addr, mc_mem_region_t region)
+void* MC_region_read_pointer(mc_mem_region_t region, const void* addr)
{
void* res;
- return *(void**) mc_snapshot_read_region(addr, region, &res, sizeof(void*));
+ return *(void**) MC_region_read(region, &res, addr, sizeof(void*));
}
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+/** \file
+ * Libunwind support for mc_address_space objects.
+ */
+
+// We need this for the register indices:
+#define _GNU_SOURCE
+
+#include <string.h>
+
+// On x86_64, libunwind unw_context_t has the same layout as ucontext_t:
+#include <sys/ucontext.h>
+
+#include <libunwind.h>
+
+#include "mc_object_info.h"
+#include "mc_process.h"
+#include "mc_unw.h"
+
+// ***** Implementation
+
+/** Get frame unwind information (libunwind method)
+ *
+ * Delegates to the local/ptrace implementation.
+ */
+static int find_proc_info(unw_addr_space_t as,
+ unw_word_t ip, unw_proc_info_t *pip,
+ int need_unwind_info, void* arg)
+{
+ mc_unw_context_t context = (mc_unw_context_t) arg;
+ return unw_get_accessors(context->process->unw_underlying_addr_space)->find_proc_info(
+ context->process->unw_underlying_addr_space, ip, pip,
+ need_unwind_info, context->process->unw_underlying_context
+ );
+}
+
+/** Release frame unwind information (libunwind method)
+ *
+ * Delegates to the local/ptrace implementation.
+ */
+static void put_unwind_info(unw_addr_space_t as,
+ unw_proc_info_t *pip, void* arg)
+{
+ mc_unw_context_t context = (mc_unw_context_t) arg;
+ return unw_get_accessors(context->process->unw_underlying_addr_space)->put_unwind_info(
+ context->process->unw_underlying_addr_space, pip,
+ context->process->unw_underlying_context
+ );
+}
+
+/** (libunwind method)
+ *
+ * Not implemented.
+ */
+static int get_dyn_info_list_addr(unw_addr_space_t as,
+ unw_word_t *dilap, void* arg)
+{
+ mc_unw_context_t context = (mc_unw_context_t) arg;
+ return unw_get_accessors(context->process->unw_underlying_addr_space)->get_dyn_info_list_addr(
+ context->process->unw_underlying_addr_space,
+ dilap,
+ context->process->unw_underlying_context
+ );
+}
+
+/** Read from the target address space memory (libunwind method)
+ *
+ * Delegates to the `mc_process_t`.
+ */
+static int access_mem(unw_addr_space_t as,
+ unw_word_t addr, unw_word_t *valp,
+ int write, void* arg)
+{
+ mc_unw_context_t context = (mc_unw_context_t) arg;
+ if (write)
+ return -UNW_EREADONLYREG;
+ MC_address_space_read(context->address_space,
+ 0, valp, (void*) addr, sizeof(unw_word_t), MC_PROCESS_INDEX_ANY);
+ // We don't handle failure gracefully.
+ return 0;
+}
+
+static void* get_reg(unw_context_t* context, unw_regnum_t regnum)
+{
+#ifdef __x86_64
+ mcontext_t* mcontext = &context->uc_mcontext;
+ switch (regnum) {
+ case UNW_X86_64_RAX: return &mcontext->gregs[REG_RAX];
+ case UNW_X86_64_RDX: return &mcontext->gregs[REG_RDX];
+ case UNW_X86_64_RCX: return &mcontext->gregs[REG_RCX];
+ case UNW_X86_64_RBX: return &mcontext->gregs[REG_RBX];
+ case UNW_X86_64_RSI: return &mcontext->gregs[REG_RSI];
+ case UNW_X86_64_RDI: return &mcontext->gregs[REG_RDI];
+ case UNW_X86_64_RBP: return &mcontext->gregs[REG_RBP];
+ case UNW_X86_64_RSP: return &mcontext->gregs[REG_RSP];
+ case UNW_X86_64_R8: return &mcontext->gregs[REG_R8];
+ case UNW_X86_64_R9: return &mcontext->gregs[REG_R9];
+ case UNW_X86_64_R10: return &mcontext->gregs[REG_R10];
+ case UNW_X86_64_R11: return &mcontext->gregs[REG_R11];
+ case UNW_X86_64_R12: return &mcontext->gregs[REG_R12];
+ case UNW_X86_64_R13: return &mcontext->gregs[REG_R13];
+ case UNW_X86_64_R14: return &mcontext->gregs[REG_R14];
+ case UNW_X86_64_R15: return &mcontext->gregs[REG_R15];
+ case UNW_X86_64_RIP: return &mcontext->gregs[REG_RIP];
+ default: return NULL;
+ }
+#else
+ return NULL;
+#endif
+}
+
+/** Read a standard register (libunwind method)
+ */
+static int access_reg(unw_addr_space_t as,
+ unw_regnum_t regnum, unw_word_t *valp,
+ int write, void* arg)
+{
+ mc_unw_context_t as_context = (mc_unw_context_t) arg;
+ unw_context_t* context = &as_context->context;
+ if (write)
+ return -UNW_EREADONLYREG;
+ greg_t* preg = get_reg(context, regnum);
+ if (!preg)
+ return -UNW_EBADREG;
+ *valp = *preg;
+ return 0;
+}
+
+/** Read a floating-point register (libunwind method)
+ *
+ * FP registers are caller-saved. The values saved by functions such as
+ * `getcontext()` is not relevant for the caller. It is not really necessary
+ * to save and handle them.
+ */
+static int access_fpreg(unw_addr_space_t as,
+ unw_regnum_t regnum, unw_fpreg_t *fpvalp,
+ int write, void* arg)
+{
+ return -UNW_EBADREG;
+}
+
+/** Resume the execution of the context (libunwind method)
+ *
+ * We don't use this.
+ */
+static int resume(unw_addr_space_t as,
+ unw_cursor_t *cp, void* arg)
+{
+ return -UNW_EUNSPEC;
+}
+
+/** Find informations about a function (libunwind method)
+ */
+static int get_proc_name(unw_addr_space_t as,
+ unw_word_t addr, char *bufp,
+ size_t buf_len, unw_word_t *offp,
+ void* arg)
+{
+ mc_unw_context_t context = (mc_unw_context_t) arg;
+ dw_frame_t frame = MC_process_find_function(context->process, (void*) addr);
+ if (!frame)
+ return - UNW_ENOINFO;
+ *offp = (unw_word_t) frame->low_pc - addr;
+
+ strncpy(bufp, frame->name, buf_len);
+ if (bufp[buf_len - 1]) {
+ bufp[buf_len - 1] = 0;
+ return -UNW_ENOMEM;
+ }
+
+ return 0;
+}
+
+// ***** Init
+
+unw_accessors_t mc_unw_accessors =
+ {
+ .find_proc_info = &find_proc_info,
+ .put_unwind_info = &put_unwind_info,
+ .get_dyn_info_list_addr = &get_dyn_info_list_addr,
+ .access_mem = &access_mem,
+ .access_reg = &access_reg,
+ .access_fpreg = &access_fpreg,
+ .resume = &resume,
+ .get_proc_name = &get_proc_name
+ };
+
+// ***** Context management
+
+int mc_unw_init_context(
+ mc_unw_context_t context, mc_process_t process, unw_context_t* c)
+{
+ context->address_space = (mc_address_space_t) process;
+ context->process = process;
+
+ // Take a copy of the context for our own purpose:
+ context->context = *c;
+#if defined(PROCESSOR_x86_64) || defined(PROCESSOR_i686)
+ // On x86_64, ucontext_t contains a pointer to itself for FP registers.
+ // We don't really need support for FR registers as they are caller saved
+ // and probably never use those fields as libunwind-x86_64 does not read
+ // FP registers from the unw_context_t
+ // but we fix the pointer in order to avoid dangling pointers:
+ context->context.uc_mcontext.fpregs = &(context->context.__fpregs_mem);
+#else
+ // Do we need to do any fixup like this?
+ #error Target CPU type is not handled.
+#endif
+
+ return 0;
+}
+
+int mc_unw_destroy_context(mc_unw_context_t context)
+{
+ context->address_space = NULL;
+ context->process = NULL;
+ return 0;
+}
+
+// ***** Cursor management
+
+int mc_unw_init_cursor(unw_cursor_t *cursor, mc_unw_context_t context)
+{
+ if (!context->process || !context->address_space)
+ return -UNW_EUNSPEC;
+ mc_address_space_t as = context->address_space;
+
+ // Use local unwinding for current process:
+ if (MC_is_process(as) && MC_process_is_self((mc_process_t) as))
+ return unw_init_local(cursor, &context->context);
+
+ return unw_init_remote(cursor, context->process->unw_addr_space, context);
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+
+/ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_UNW_H
+#define MC_UNW_H
+
+/** \file
+ * Libunwind implementation for the model-checker
+ *
+ * Libunwind provides an pluggable stack unwinding API: the way the current
+ * registers and memory is accessed, the way unwinding informations is found
+ * is pluggable.
+ *
+ * This component implements the libunwind API for he model-checker:
+ *
+ * * reading memory from a mc_address_space_t;
+ *
+ * * reading stack registers from a saved snapshot (context).
+ *
+ * Parts of the libunwind information fetching is currently handled by the
+ * standard `libunwind` implementations (either the local one or the ptrace one)
+ * because parsing `.eh_frame` section is not fun and `libdw` does not help
+ * much here.
+ */
+
+#include "mc_process.h"
+
+SG_BEGIN_DECL()
+
+// ***** Libunwind namespace
+
+/** Virtual table for our `libunwind-process_vm_readv` implementation.
+ *
+ * This implementation reuse most the code of `libunwind-ptrace` but
+ * does not use ptrace() to read the target process memory by
+ * `process_vm_readv()` or `/dev/${pid}/mem` if possible.
+ *
+ * Does not support any MC-specific behaviour (privatisation, snapshots)
+ * and `ucontext_t`.
+ *
+ * It works with `void*` contexts allocated with `_UPT_create(pid)`.
+ */
+extern unw_accessors_t mc_unw_vmread_accessors;
+
+/** Virtual table for our `libunwind` implementation
+ *
+ * Stack unwinding on a `mc_process_t` (for memory, unwinding information)
+ * and `ucontext_t` (for processor registers).
+ *
+ * It works with the `s_mc_unw_context_t` context.
+ */
+extern unw_accessors_t mc_unw_accessors;
+
+// ***** Libunwind context
+
+/** A `libunwind` context
+ */
+typedef struct s_mc_unw_context {
+ mc_address_space_t address_space;
+ mc_process_t process;
+ unw_context_t context;
+} s_mc_unw_context_t, *mc_unw_context_t;
+
+/** Initialises an already allocated context */
+int mc_unw_init_context(
+ mc_unw_context_t context, mc_process_t process, unw_context_t* c);
+
+/** Destroys (but not not `free`) a context */
+int mc_unw_destroy_context(mc_unw_context_t context);
+
+// ***** Libunwind cursor
+
+/** Initialises a `libunwind` cursor */
+int mc_unw_init_cursor(unw_cursor_t *cursor, mc_unw_context_t context);
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include "mc_unw.h"
+
+/** \file
+ * Libunwind namespace implementation using process_vm_readv.
+ *.
+ * This implem
+ */
+
+/** Partial structure of libunwind-ptrace context in order to get the PID
+ *
+ * The context type for libunwind-race is an opaque type. We need to get the
+ * PID which is the first field. This is a hack which might break if the
+ * libunwind-ptrace structure changes.
+ */
+struct _UPT_info {
+ pid_t pid;
+ // Other things;
+};
+
+/** Get the PID of a `libunwind-ptrace` context
+ */
+static inline
+pid_t _UPT_getpid(void* arg)
+{
+ struct _UPT_info* info = arg;
+ return info->pid;
+}
+
+/** Read from the memory, avoid using `ptrace` (libunwind method)
+ */
+static int access_mem(const unw_addr_space_t as,
+ const unw_word_t addr, unw_word_t* const valp,
+ const int write, void* const arg)
+{
+ if (write)
+ return - UNW_EINVAL;
+ ssize_t s;
+ pid_t pid = _UPT_getpid(arg);
+ size_t size = sizeof(unw_word_t);
+
+#ifdef HAVE_PROCESS_VM_READV
+ // process_vm_read implementation.
+ // This is only available since Linux 3.2.
+
+ struct iovec local = { valp, size };
+ struct iovec remote = { (void*) addr, size };
+ s = process_vm_readv(pid, &local, 1, &remote, 1, 0);
+ if (s >= 0) {
+ if (s != size)
+ return - UNW_EINVAL;
+ else
+ return 0;
+ }
+ if (s < 0 && errno != ENOSYS)
+ return - UNW_EINVAL;
+#endif
+
+ // /proc/${pid}/mem implementation.
+ // On recent kernels, we do not need to ptrace the target process.
+ // On older kernels, it is necessary to ptrace the target process.
+ size_t count = size;
+ off_t off = (off_t) addr;
+ char* buf = (char*) valp;
+ int fd = MC_process_vm_open(pid, O_RDONLY);
+ if (fd < 0)
+ return - UNW_EINVAL;
+ while (1) {
+ ssize_t s = pread(fd, buf, count, off);
+ if (s == 0) {
+ close(fd);
+ return - UNW_EINVAL;
+ }
+ if (s == -1)
+ break;
+ count -= s;
+ buf += s;
+ off += s;
+ if (count == 0) {
+ close(fd);
+ return 0;
+ }
+ }
+ close(fd);
+
+ // ptrace implementation.
+ // We need to have PTRACE_ATTACH-ed it before.
+ return _UPT_access_mem(as, addr, valp, write, arg);
+}
+
+unw_accessors_t mc_unw_vmread_accessors =
+ {
+ .find_proc_info = &_UPT_find_proc_info,
+ .put_unwind_info = &_UPT_put_unwind_info,
+ .get_dyn_info_list_addr = &_UPT_get_dyn_info_list_addr,
+ .access_mem = &access_mem,
+ .access_reg = &_UPT_access_reg,
+ .access_fpreg = &_UPT_access_fpreg,
+ .resume = &_UPT_resume,
+ .get_proc_name = &_UPT_get_proc_name
+ };
*/
static mc_visited_state_t visited_state_new()
{
+ mc_process_t process = &(mc_model_checker->process);
mc_visited_state_t new_state = NULL;
new_state = xbt_new0(s_mc_visited_state_t, 1);
- new_state->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
+ new_state->heap_bytes_used = mmalloc_get_bytes_used_remote(
+ MC_process_get_heap(process)->heaplimit,
+ MC_process_get_malloc_info(process));
new_state->nb_processes = xbt_swag_size(simix_global->process_list);
new_state->system_state = MC_take_snapshot(mc_stats->expanded_states);
new_state->num = mc_stats->expanded_states;
mc_visited_pair_t MC_visited_pair_new(int pair_num, xbt_automaton_state_t automaton_state, xbt_dynar_t atomic_propositions, mc_state_t graph_state)
{
+ mc_process_t process = &(mc_model_checker->process);
mc_visited_pair_t pair = NULL;
pair = xbt_new0(s_mc_visited_pair_t, 1);
pair->graph_state = graph_state;
if(pair->graph_state->system_state == NULL)
pair->graph_state->system_state = MC_take_snapshot(pair_num);
- pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
+ pair->heap_bytes_used = mmalloc_get_bytes_used_remote(
+ MC_process_get_heap(process)->heaplimit,
+ MC_process_get_malloc_info(process));
pair->nb_processes = xbt_swag_size(simix_global->process_list);
pair->automaton_state = automaton_state;
pair->num = pair_num;
int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max)
{
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
int cursor = 0, previous_cursor, next_cursor;
int nb_processes, heap_bytes_used, nb_processes_test, heap_bytes_used_test;
*max = next_cursor;
next_cursor++;
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
return -1;
}
}
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return cursor;
}
}
}
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
mc_visited_state_t new_state = visited_state_new();
graph_state->system_state = new_state->system_state;
if (xbt_dynar_is_empty(visited_states)) {
xbt_dynar_push(visited_states, &new_state);
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return NULL;
} else {
xbt_dynar_insert_at(visited_states, cursor, &new_state);
XBT_DEBUG("Replace visited state %d with the new visited state %d", state_test->num, new_state->num);
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
return state_test;
}
cursor++;
XBT_DEBUG("Remove visited state (maximum number of stored states reached)");
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return NULL;
-
}
}
if (_sg_mc_visited == 0)
return -1;
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
+ xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap);
mc_visited_pair_t new_visited_pair = NULL;
} else {
MC_visited_pair_delete(pair_test);
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
+ mmalloc_set_current_heap(heap);
return new_visited_pair->other_num;
}
}
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
+ mmalloc_set_current_heap(heap);
return -1;
}
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <stdlib.h>
+
+#include <sys/types.h>
+
#include "mc_memory_map.h"
#include "mc_private.h"
-#include <stdlib.h>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory_map, mc,
"Logging specific to algorithms for memory_map");
-memory_map_t MC_get_memory_map(void)
+memory_map_t MC_get_memory_map(pid_t pid)
{
- FILE *fp; /* File pointer to process's proc maps file */
- char *line = NULL; /* Temporal storage for each line that is readed */
- ssize_t read; /* Number of bytes readed */
- size_t n = 0; /* Amount of bytes to read by xbt_getline */
- memory_map_t ret = NULL; /* The memory map to return */
-
-/* The following variables are used during the parsing of the file "maps" */
- s_map_region_t memreg; /* temporal map region used for creating the map */
- char *lfields[6], *tok, *endptr;
- int i;
-
-/* Open the actual process's proc maps file and create the memory_map_t */
-/* to be returned. */
- fp = fopen("/proc/self/maps", "r");
-
+ /* Open the actual process's proc maps file and create the memory_map_t */
+ /* to be returned. */
+ char* path = bprintf("/proc/%i/maps", (int) pid);
+ FILE *fp = fopen(path, "r");
+ free(path);
if(fp == NULL)
perror("fopen failed");
-
xbt_assert(fp,
- "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug.");
-
+ "Cannot open %s to investigate the memory map of the process.", path);
setbuf(fp, NULL);
- ret = xbt_new0(s_memory_map_t, 1);
+ memory_map_t ret = xbt_new0(s_memory_map_t, 1);
/* Read one line at the time, parse it and add it to the memory map to be returned */
+ ssize_t read; /* Number of bytes readed */
+ char* line = NULL;
+ size_t n = 0; /* Amount of bytes to read by xbt_getline */
while ((read = xbt_getline(&line, &n, fp)) != -1) {
//fprintf(stderr,"%s", line);
/* Tokenize the line using spaces as delimiters and store each token */
/* in lfields array. We expect 5 tokens/fields */
+ char* lfields[6];
lfields[0] = strtok(line, " ");
+ int i;
for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
lfields[i] = strtok(NULL, " ");
}
/* Ok we are good enough to try to get the info we need */
/* First get the start and the end address of the map */
- tok = strtok(lfields[0], "-");
+ char *tok = strtok(lfields[0], "-");
if (tok == NULL)
xbt_abort();
+ s_map_region_t memreg; /* temporal map region used for creating the map */
+ char *endptr;
memreg.start_addr = (void *) strtoul(tok, &endptr, 16);
/* Make sure that the entire string was an hex number */
if (*endptr != '\0')
/* Create space for a new map region in the region's array and copy the */
/* parsed stuff from the temporal memreg variable */
+ XBT_DEBUG("Found region for %s",
+ memreg.pathname ? memreg.pathname : "(null)");
ret->regions =
xbt_realloc(ret->regions, sizeof(memreg) * (ret->mapsize + 1));
memcpy(ret->regions + ret->mapsize, &memreg, sizeof(memreg));
}
free(line);
-
fclose(fp);
-
return ret;
}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <exception>
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+
+#include <signal.h>
+#include <poll.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <xbt/log.h>
+
+#include "simgrid/sg_config.h"
+#include "xbt_modinter.h"
+
+#include "mc_base.h"
+#include "mc_private.h"
+#include "mc_protocol.h"
+#include "mc_server.h"
+#include "mc_model_checker.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_main, mc, "Entry point for simgrid-mc");
+
+static const bool trace = true;
+
+static int do_child(int socket, char** argv)
+{
+ XBT_DEBUG("Inside the child process PID=%i", (int) getpid());
+ int res;
+
+ // Remove CLOEXEC in order to pass the socket to the exec-ed program:
+ int fdflags = fcntl(socket, F_GETFD, 0);
+ if (fdflags == -1) {
+ std::perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+ }
+ if (fcntl(socket, F_SETFD, fdflags & ~FD_CLOEXEC) == -1) {
+ std::perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+ }
+
+ XBT_DEBUG("CLOEXEC removed on socket %i", socket);
+
+ // Set environment:
+ setenv(MC_ENV_VARIABLE, "1", 1);
+
+ char buffer[64];
+ res = std::snprintf(buffer, sizeof(buffer), "%i", socket);
+ if ((size_t) res >= sizeof(buffer) || res == -1)
+ return MC_SERVER_ERROR;
+ setenv(MC_ENV_SOCKET_FD, buffer, 1);
+
+ execvp(argv[1], argv+1);
+ std::perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+}
+
+static int do_parent(int socket, pid_t child)
+{
+ XBT_DEBUG("Inside the parent process");
+ if (mc_server)
+ xbt_die("MC server already present");
+ try {
+ mc_mode = MC_MODE_SERVER;
+ mc_server = new s_mc_server(child, socket);
+ mc_server->start();
+ MC_init_pid(child, socket);
+ mc_server->resume(&mc_model_checker->process);
+ mc_server->loop();
+ mc_server->shutdown();
+ mc_server->exit();
+ }
+ catch(std::exception& e) {
+ XBT_ERROR(e.what());
+ }
+ exit(MC_SERVER_ERROR);
+}
+
+static char** argvdup(int argc, char** argv)
+{
+ char** argv_copy = xbt_new(char*, argc+1);
+ std::memcpy(argv_copy, argv, sizeof(char*) * argc);
+ argv_copy[argc] = NULL;
+ return argv_copy;
+}
+
+int main(int argc, char** argv)
+{
+ // We need to keep the original parameters in order to pass them to the
+ // model-checked process:
+ int argc_copy = argc;
+ char** argv_copy = argvdup(argc, argv);
+ xbt_log_init(&argc_copy, argv_copy);
+ sg_config_init(&argc_copy, argv_copy);
+
+ if (argc < 2)
+ xbt_die("Missing arguments.\n");
+
+ bool server_mode = false;
+ char* env = std::getenv("SIMGRID_MC_MODE");
+ if (env) {
+ if (std::strcmp(env, "server") == 0)
+ server_mode = true;
+ else if (std::strcmp(env, "standalone") == 0)
+ server_mode = false;
+ else
+ XBT_WARN("Unrecognised value for SIMGRID_MC_MODE (server/standalone)");
+ }
+
+ if (!server_mode) {
+ setenv(MC_ENV_VARIABLE, "1", 1);
+ execvp(argv[1], argv+1);
+
+ std::perror("simgrid-mc");
+ return 127;
+ }
+
+ // Create a AF_LOCAL socketpair:
+ int res;
+
+ int sockets[2];
+ res = socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, sockets);
+ if (res == -1) {
+ perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+ }
+
+ XBT_DEBUG("Created socketpair");
+
+ pid_t pid = fork();
+ if (pid < 0) {
+ perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+ } else if (pid == 0) {
+ close(sockets[1]);
+ return do_child(sockets[0], argv);
+ } else {
+ close(sockets[0]);
+ return do_parent(sockets[1], pid);
+ }
+
+ return 0;
+}
xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_hash, NULL);
xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/hash", "no");
+ /* Set max depth exploration */
+ xbt_cfg_register(&_sg_cfg_set, "model-check/snapshot_fds",
+ "Whether file descriptors must be snapshoted",
+ xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_snapshot_fds, NULL);
+ xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/snapshot_fds", "no");
+
/* Set max depth exploration */
xbt_cfg_register(&_sg_cfg_set, "model-check/max_depth",
"Specify the max depth of exploration (default : 1000)",
#include "smx_private.h"
#ifdef HAVE_MC
+#include "mc/mc_process.h"
+#include "mc/mc_model_checker.h"
#endif
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);
*/
void SIMIX_simcall_handle(smx_simcall_t simcall, int value) {
XBT_DEBUG("Handling simcall %p: %s", simcall, SIMIX_simcall_name(simcall->call));
+ #ifdef HAVE_MC
+ if (mc_model_checker) {
+ mc_model_checker->process.cache_flags = 0;
+ }
+ #endif
SIMCALL_SET_MC_VALUE(simcall, value);
if (simcall->issuer->context->iwannadie && simcall->call != SIMCALL_PROCESS_CLEANUP)
return;
fd.write('#include "smx_private.h"\n');
fd.write('#ifdef HAVE_MC\n');
- # fd.write('#include "mc/mc_private.h"\n');
+ fd.write('#include "mc/mc_process.h"\n');
+ fd.write('#include "mc/mc_model_checker.h"\n');
fd.write('#endif\n');
fd.write('\n');
fd.write('XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);\n\n');
fd.write(' */\n');
fd.write('void SIMIX_simcall_handle(smx_simcall_t simcall, int value) {\n');
fd.write(' XBT_DEBUG("Handling simcall %p: %s", simcall, SIMIX_simcall_name(simcall->call));\n');
+ fd.write(' #ifdef HAVE_MC\n');
+ fd.write(' if (mc_model_checker) {\n');
+ fd.write(' mc_model_checker->process.cache_flags = 0;\n');
+ fd.write(' }\n');
+ fd.write(' #endif\n');
fd.write(' SIMCALL_SET_MC_VALUE(simcall, value);\n');
fd.write(' if (simcall->issuer->context->iwannadie && simcall->call != SIMCALL_PROCESS_CLEANUP)\n');
fd.write(' return;\n');
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <stdlib.h>
+
#include "smx_private.h"
#include "xbt/heap.h"
#include "xbt/sysdep.h"
#ifdef HAVE_MC
#include "mc/mc_private.h"
+#include "mc/mc_model_checker.h"
+#include "mc/mc_protocol.h"
+#include "mc/mc_client.h"
#endif
#include "mc/mc_record.h"
if (sg_cfg_get_boolean("clean_atexit"))
atexit(SIMIX_clean);
+#ifdef HAVE_MC
+ // The communication initialisation is done ASAP.
+ // We need to commuicate initialisation of the different layers to the model-checker.
+ if (mc_mode == MC_MODE_NONE) {
+ if (getenv(MC_ENV_SOCKET_FD)) {
+ mc_mode = MC_MODE_CLIENT;
+ MC_client_init();
+ MC_client_hello();
+ } else {
+ mc_mode = MC_MODE_STANDALONE;
+ }
+ }
+#endif
+
if (_sg_cfg_exit_asap)
exit(0);
}
}
}
+ // FIXME, cross-process support (mmap across process when necessary)
int current = smpi_privatisation_regions[dest].file_descriptor;
XBT_DEBUG("Switching data frame to the one of process %d", dest);
void* tmp = mmap (TOPAGE(start_data_exe), size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
xbt_die("could not find dst node active comms !");
// act_dst->rate=rate;
- ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair<IBNode*,IBNode*>(act_src, act_dst);
+ ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair(act_src, act_dst);
//post the action in the second dist, to retrieve in the other callback
XBT_DEBUG("IB callback - action %p init", action);
m_lastUpdate = now;
m_lastValue = lmm_variable_getvalue(getVariable());
}
-
#include "xbt/automaton.h"
#include <stdio.h> /* printf */
+struct xbt_automaton_propositional_symbol{
+ char* pred;
+ /** Callback used to evaluate the value of the symbol */
+ int (*callback)(void*);
+ /** Additional data for the callback.
+ Alternatively it can be used as a pointer to the data. */
+ void* data;
+ //** Optional callback used to free the data field */
+ void (*free_function)(void*);
+};
+
xbt_automaton_t xbt_automaton_new(){
xbt_automaton_t automaton = NULL;
automaton = xbt_new0(struct xbt_automaton, 1);
return a->current_state;
}
-xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct){
+static int call_simple_function(void* function)
+{
+ return ((int (*)(void)) function)();
+}
+
+xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void)){
xbt_automaton_propositional_symbol_t prop_symb = NULL;
prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
prop_symb->pred = strdup(id);
- prop_symb->function = fct;
+ prop_symb->callback = call_simple_function;
+ prop_symb->data = fct;
+ prop_symb->free_function = NULL;
xbt_dynar_push(a->propositional_symbols, &prop_symb);
return prop_symb;
}
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value)
+{
+ xbt_automaton_propositional_symbol_t prop_symb = NULL;
+ prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+ prop_symb->pred = strdup(id);
+ prop_symb->callback = NULL;
+ prop_symb->data = value;
+ prop_symb->free_function = NULL;
+ xbt_dynar_push(a->propositional_symbols, &prop_symb);
+ return prop_symb;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+ xbt_automaton_t a, const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function)
+{
+ xbt_automaton_propositional_symbol_t prop_symb = NULL;
+ prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+ prop_symb->pred = strdup(id);
+ prop_symb->callback = callback;
+ prop_symb->data = data;
+ prop_symb->free_function = free_function;
+ xbt_dynar_push(a->propositional_symbols, &prop_symb);
+ return prop_symb;
+}
+
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol)
+{
+ if (symbol->callback)
+ return (symbol->callback)(symbol->data);
+ else
+ return *(int*) symbol->data;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->callback;
+}
+
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->data;
+}
+
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->pred;
+}
+
int xbt_automaton_state_compare(xbt_automaton_state_t s1, xbt_automaton_state_t s2){
/* single id for each state, id and type sufficient for comparison*/
}
void xbt_automaton_propositional_symbol_free_voidp(void *ps){
- xbt_automaton_propositional_symbol_free((xbt_automaton_propositional_symbol_t) * (void **) ps);
+ xbt_automaton_propositional_symbol_t symbol = (xbt_automaton_propositional_symbol_t) * (void **) ps;
+ if (symbol->free_function)
+ symbol->free_function(symbol->data);
+ xbt_free(symbol->pred);
+ xbt_automaton_propositional_symbol_free(symbol);
}
void xbt_automaton_free(xbt_automaton_t a){
* under the terms of the license (GNU LGPL) which comes with this package. */
/* Redefine the classical malloc/free/realloc functions so that they fit well in the mmalloc framework */
+#define _GNU_SOURCE
+#include <stdlib.h>
+
+#include <dlfcn.h>
+
+#include "../../mc/mc_base.h"
#include "mmprivate.h"
#include "xbt_modinter.h"
#include "internal_config.h"
#include <math.h>
+#include "../mc/mc_protocol.h"
//#define MM_LEGACY_VERBOSE 1 /* define this to see which version of malloc gets used */
backwards compatibility with the non-mmap'd version. */
xbt_mheap_t __mmalloc_default_mdp = NULL;
+static int __malloc_use_mmalloc;
+
+int malloc_use_mmalloc(void)
+{
+ return __malloc_use_mmalloc;
+}
static xbt_mheap_t __mmalloc_current_heap = NULL; /* The heap we are currently using. */
return __mmalloc_current_heap;
}
-void mmalloc_set_current_heap(xbt_mheap_t new_heap)
+xbt_mheap_t mmalloc_set_current_heap(xbt_mheap_t new_heap)
{
+ xbt_mheap_t heap = __mmalloc_current_heap;
__mmalloc_current_heap = new_heap;
+ return heap;
}
-
#ifdef MMALLOC_WANT_OVERRIDE_LEGACY
-#if 0 && defined(HAVE_GNU_LD)
-#undef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#include <dlfcn.h>
-
-static void * (*real_malloc) (size_t) = NULL;
-static void * (*real_realloc) (void*,size_t) = NULL;
-static void * (*real_free) (void*) = NULL;
+/* Fake implementations, they are used to fool dlsym:
+ * dlsym used calloc and falls back to some other mechanism
+ * if this fails.
+ */
+static void* mm_fake_calloc(size_t nmemb, size_t size) { return NULL; }
+static void* mm_fake_malloc(size_t n) { return NULL; }
+static void* mm_fake_realloc(void *p, size_t s) { return NULL; }
-static void mm_gnuld_legacy_init(void) { /* This function is called from mmalloc_preinit(); it works even if it's static because all mm is in mm.c */
- real_malloc = (void * (*) (size_t)) dlsym(RTLD_NEXT, "malloc");
- real_realloc = (void * (*) (void*,size_t)) dlsym(RTLD_NEXT, "realloc");
- real_free = (void * (*) (void*)) dlsym(RTLD_NEXT, "free");
- __mmalloc_current_heap = __mmalloc_default_mdp;
-}
+/* Function signatures for the main malloc functions: */
+typedef void* (*mm_malloc_t)(size_t size);
+typedef void (*mm_free_t)(void*);
+typedef void* (*mm_calloc_t)(size_t nmemb, size_t size);
+typedef void* (*mm_realloc_t)(void *ptr, size_t size);
-/* Hello pimple!
- * DL needs some memory while resolving the malloc symbol, that is somehow problematic
- * To that extend, we have a little area here living in .BSS that we return if asked for memory before the malloc is resolved.
- */
-static int allocated_junk = 0; /* keep track of many blocks of our little area was already given to someone */
-#define JUNK_SIZE 8
-#define MAX_JUNK_AREAS (64 * 1024 / JUNK_SIZE)
-static char junkareas[MAX_JUNK_AREAS][JUNK_SIZE];
-
-/* This version use mmalloc if there is a current heap, or the legacy implem if not */
-static void *malloc_or_calloc(size_t n, int setzero) {
- xbt_mheap_t mdp = __mmalloc_current_heap;
- void *ret;
-#ifdef MM_LEGACY_VERBOSE
- static int warned_raw = 0;
- static int warned_mmalloc = 0;
-#endif
-
- if (mdp) {
- LOCK(mdp);
- ret = mmalloc(mdp, n);
- UNLOCK(mdp);
- // This was already done by mmalloc:
- if (mdp->options & XBT_MHEAP_OPTION_MEMSET) {
- setzero = 0;
- }
-#ifdef MM_LEGACY_VERBOSE
- if (!warned_mmalloc) {
- fprintf(stderr,"Using mmalloc; enabling the model-checker in cmake may have a bad impact on your simulation performance\n");
- warned_mmalloc = 1;
- }
-#endif
- } else if (!real_malloc) {
- size_t needed_areas = n / JUNK_SIZE;
- if(needed_areas * JUNK_SIZE != n) needed_areas++;
- if (allocated_junk+needed_areas>=MAX_JUNK_AREAS) {
- fprintf(stderr,
- "Panic: real malloc symbol not resolved yet, and I already gave my little private memory chunk away.\n");
- exit(1);
- } else {
- size_t i = allocated_junk;
- allocated_junk += needed_areas;
- ret = junkareas[i];
- }
- }
- else {
-#ifdef MM_LEGACY_VERBOSE
- if (!warned_raw) {
- fprintf(stderr,"Using system malloc after interception; you seem to be currently model-checking\n");
- warned_raw = 1;
- }
-#endif
- ret = real_malloc(n);
- }
- if (ret && setzero) {
- memset(ret, 0, n);
- }
- return ret;
-}
+/* Function pointers to the real/next implementations: */
+static mm_malloc_t mm_real_malloc = mm_fake_malloc;
+static mm_free_t mm_real_free;
+static mm_calloc_t mm_real_calloc = mm_fake_calloc;
+static mm_realloc_t mm_real_realloc = mm_fake_realloc;
-void *malloc(size_t n)
-{
- return malloc_or_calloc(n, 0);
-}
+#define GET_HEAP() __mmalloc_current_heap
-void *calloc(size_t nmemb, size_t size)
+/** Constructor functions used to initialize the malloc implementation
+ */
+static void __attribute__((constructor(101))) mm_legacy_constructor()
{
- return malloc_or_calloc(nmemb*size, 1);
+ __malloc_use_mmalloc = getenv(MC_ENV_VARIABLE) ? 1 : 0;
+ if (__malloc_use_mmalloc) {
+ __mmalloc_current_heap = mmalloc_preinit();
+ } else {
+ mm_real_realloc = (mm_realloc_t) dlsym(RTLD_NEXT, "realloc");
+ mm_real_malloc = (mm_malloc_t) dlsym(RTLD_NEXT, "malloc");
+ mm_real_free = (mm_free_t) dlsym(RTLD_NEXT, "free");
+ mm_real_calloc = (mm_calloc_t) dlsym(RTLD_NEXT, "calloc");
+ }
}
-void *realloc(void *p, size_t s)
+void* malloc_no_memset(size_t n)
{
- xbt_mheap_t mdp = __mmalloc_current_heap;
- void *ret;
-
- if (mdp) {
- LOCK(mdp);
- ret = mrealloc(mdp, p, s);
- UNLOCK(mdp);
- } else {
- ret = real_realloc(p,s);
+ if (!__malloc_use_mmalloc) {
+ return mm_real_malloc(n);
}
+ xbt_mheap_t mdp = GET_HEAP();
+ if (!mdp)
+ return NULL;
+
+ LOCK(mdp);
+ void *ret = mmalloc_no_memset(mdp, n);
+ UNLOCK(mdp);
return ret;
}
-void free(void *p)
+void *malloc(size_t n)
{
- if (p==NULL)
- return;
- if (p<(void*)junkareas || p>=(void*)(junkareas[MAX_JUNK_AREAS]) ) {
- // main use case
-
- xbt_mheap_t mdp = __mmalloc_current_heap;
-
- if (mdp) {
- LOCK(mdp);
- mfree(mdp, p);
- UNLOCK(mdp);
- } else {
- real_free(p);
- }
- } else {
- // We are in the junkarea.
- // This area is used to allocate memory at initilization time.
-
- if(allocated_junk && p==junkareas[allocated_junk-1]) {
- // Last junkarea. We can reuse it.
- allocated_junk--;
- } else {
- // We currently cannot reuse freed junkareas in the general case.
- }
+ if (!__malloc_use_mmalloc) {
+ return mm_real_malloc(n);
}
-}
-
-#else /* NO GNU_LD */
-void *malloc(size_t n)
-{
- xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
+ xbt_mheap_t mdp = GET_HEAP();
+ if (!mdp)
+ return NULL;
LOCK(mdp);
void *ret = mmalloc(mdp, n);
UNLOCK(mdp);
-
-
return ret;
}
void *calloc(size_t nmemb, size_t size)
{
- xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
+ if (!__malloc_use_mmalloc) {
+ return mm_real_calloc(nmemb, size);
+ }
+
+ xbt_mheap_t mdp = GET_HEAP();
+ if (!mdp)
+ return NULL;
LOCK(mdp);
void *ret = mmalloc(mdp, nmemb*size);
UNLOCK(mdp);
-
// This was already done in the callee:
if(!(mdp->options & XBT_MHEAP_OPTION_MEMSET)) {
memset(ret, 0, nmemb * size);
}
-
return ret;
}
void *realloc(void *p, size_t s)
{
- void *ret = NULL;
- xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
+ if (!__malloc_use_mmalloc) {
+ return mm_real_realloc(p, s);
+ }
+
+ xbt_mheap_t mdp = GET_HEAP();
+ if (!mdp)
+ return NULL;
LOCK(mdp);
- ret = mrealloc(mdp, p, s);
+ void* ret = mrealloc(mdp, p, s);
UNLOCK(mdp);
-
return ret;
}
void free(void *p)
{
- if (p != NULL) {
- xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
-
- LOCK(mdp);
- mfree(mdp, p);
- UNLOCK(mdp);
+ if (!__malloc_use_mmalloc) {
+ mm_real_free(p);
+ return;
}
+
+ if (!p)
+ return;
+
+ xbt_mheap_t mdp = GET_HEAP();
+ LOCK(mdp);
+ mfree(mdp, p);
+ UNLOCK(mdp);
}
-#endif /* NO GNU_LD */
#endif /* WANT_MALLOC_OVERRIDE */
}
xbt_assert(__mmalloc_default_mdp != NULL);
-#if 0 && defined(HAVE_GNU_LD) && defined(MMALLOC_WANT_OVERRIDE_LEGACY)
- mm_gnuld_legacy_init();
-#endif
-
return __mmalloc_default_mdp;
}
// xbt_mheap_destroy_no_free(__mmalloc_default_mdp);
}
-size_t mmalloc_get_bytes_used(xbt_mheap_t heap){
- int i = 0, j = 0;
+// This is the underlying implementation of mmalloc_get_bytes_used_remote.
+// Is it used directly in order to evaluate the bytes used from a different
+// process.
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo)
+{
int bytes = 0;
-
- while(i<=((struct mdesc *)heap)->heaplimit){
- if(((struct mdesc *)heap)->heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
- if(((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size > 0)
- bytes += ((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size;
-
- } else if(((struct mdesc *)heap)->heapinfo[i].type > 0){
- for(j=0; j < (size_t) (BLOCKSIZE >> ((struct mdesc *)heap)->heapinfo[i].type); j++){
- if(((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j] > 0)
- bytes += ((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j];
+ for (size_t i=0; i<=heaplimit; ++i){
+ if (heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
+ if (heapinfo[i].busy_block.busy_size > 0)
+ bytes += heapinfo[i].busy_block.busy_size;
+ } else if (heapinfo[i].type > 0) {
+ for (size_t j=0; j < (size_t) (BLOCKSIZE >> heapinfo[i].type); j++){
+ if(heapinfo[i].busy_frag.frag_size[j] > 0)
+ bytes += heapinfo[i].busy_frag.frag_size[j];
}
}
- i++;
}
-
return bytes;
}
+size_t mmalloc_get_bytes_used(const xbt_mheap_t heap){
+ const struct mdesc* heap_data = (const struct mdesc *) heap;
+ return mmalloc_get_bytes_used_remote(heap_data->heaplimit, heap_data->heapinfo);
+}
+
ssize_t mmalloc_get_busy_size(xbt_mheap_t heap, void *ptr){
ssize_t block = ((char*)ptr - (char*)(heap->heapbase)) / BLOCKSIZE + 1;
void mmcheck(xbt_mheap_t heap);
+int malloc_use_mmalloc(void);
+
+int mmalloc_exec_using_mm(int argc, const char** argv);
+void mmalloc_ensure_using_mm(int argc, const char** argv);
+
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo);
+
#endif /* __MMPRIVATE_H */
++xbt_pagebits;
}
-#ifdef MMALLOC_WANT_OVERRIDE_LEGACY
- mmalloc_preinit();
-#endif
#ifdef _TWO_DIGIT_EXPONENT
/* Even printf behaves differently on Windows... */
_set_output_format(_TWO_DIGIT_EXPONENT);
#define XBT_MODINTER_H
#include "xbt/misc.h"
+SG_BEGIN_DECL()
+
/* Modules definitions */
void xbt_backtrace_preinit(void);
void xbt_backtrace_postexit(void);
void *mmalloc_preinit(void);
void mmalloc_postexit(void);
+SG_END_DECL()
#endif /* XBT_MODINTER_H */
#include "../../src/include/mc/datatypes.h"
#include "../../src/mc/mc_object_info.h"
#include "../../src/mc/mc_private.h"
+#include "../../src/mc/mc_model_checker.h"
int test_some_array[4][5][6];
struct some_struct { int first; int second[4][5]; } test_some_struct;
return NULL;
}
-static dw_variable_t find_global_variable_by_name(mc_object_info_t info, const char* name) {
- unsigned int cursor = 0;
- dw_variable_t variable;
- xbt_dynar_foreach(info->global_variables, cursor, variable){
- if(!strcmp(name, variable->name))
- return variable;
- }
-
- return NULL;
-}
-
static dw_frame_t find_function_by_name(mc_object_info_t info, const char* name) {
xbt_dict_cursor_t cursor = 0;
dw_frame_t subprogram;
}
-static dw_variable_t test_global_variable(mc_object_info_t info, const char* name, void* address, long byte_size) {
- dw_variable_t variable = find_global_variable_by_name(info, name);
+static dw_variable_t test_global_variable(mc_process_t process, mc_object_info_t info, const char* name, void* address, long byte_size) {
+
+ dw_variable_t variable = MC_file_object_info_find_variable_by_name(info, name);
xbt_assert(variable, "Global variable %s was not found", name);
xbt_assert(!strcmp(variable->name, name), "Name mismatch for %s", name);
xbt_assert(variable->global, "Variable %s is not global", name);
xbt_assert(variable->address == address,
"Address mismatch for %s : %p expected but %p found", name, address, variable->address);
- dw_type_t type = xbt_dict_get_or_null(mc_binary_info->types, variable->type_origin);
+ dw_type_t type = xbt_dict_get_or_null(process->binary_info->types, variable->type_origin);
xbt_assert(type!=NULL, "Missing type for %s", name);
xbt_assert(type->byte_size = byte_size, "Byte size mismatch for %s", name);
return variable;
typedef struct foo {int i;} s_foo;
-static void test_type_by_name(s_foo my_foo) {
- assert(xbt_dict_get_or_null(mc_binary_info->full_types_by_name, "struct foo"));
+static void test_type_by_name(mc_process_t process, s_foo my_foo) {
+ assert(xbt_dict_get_or_null(process->binary_info->full_types_by_name, "struct foo"));
}
-int main(int argc, char** argv) {
-
- // xbt_init(&argc, argv);
+int main(int argc, char** argv)
+{
SIMIX_global_init(&argc, argv);
- MC_memory_init();
- MC_init();
dw_variable_t var;
dw_type_t type;
+
+ s_mc_process_t p;
+ mc_process_t process = &p;
+ MC_process_init(&p, getpid(), -1);
- test_global_variable(mc_binary_info, "some_local_variable", &some_local_variable, sizeof(int));
+ test_global_variable(process, process->binary_info, "some_local_variable", &some_local_variable, sizeof(int));
- var = test_global_variable(mc_binary_info, "test_some_array", &test_some_array, sizeof(test_some_array));
- type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
+ var = test_global_variable(process, process->binary_info, "test_some_array", &test_some_array, sizeof(test_some_array));
+ type = xbt_dict_get_or_null(process->binary_info->types, var->type_origin);
xbt_assert(type->element_count == 6*5*4, "element_count mismatch in test_some_array : %i / %i", type->element_count, 6*5*4);
- var = test_global_variable(mc_binary_info, "test_some_struct", &test_some_struct, sizeof(test_some_struct));
- type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
- assert(find_member(mc_binary_info, "first", type)->offset == 0);
- assert(find_member(mc_binary_info, "second", type)->offset
+ var = test_global_variable(process, process->binary_info, "test_some_struct", &test_some_struct, sizeof(test_some_struct));
+ type = xbt_dict_get_or_null(process->binary_info->types, var->type_origin);
+ assert(find_member(process->binary_info, "first", type)->offset == 0);
+ assert(find_member(process->binary_info, "second", type)->offset
== ((const char*)&test_some_struct.second) - (const char*)&test_some_struct);
unw_context_t context;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
- test_local_variable(mc_binary_info, "main", "argc", &argc, &cursor);
+ test_local_variable(process->binary_info, "main", "argc", &argc, &cursor);
{
int lexical_block_variable = 50;
- test_local_variable(mc_binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
+ test_local_variable(process->binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
}
s_foo my_foo;
- test_type_by_name(my_foo);
+ test_type_by_name(process, my_foo);
_exit(0);
}
#! ./tesh
$ $SG_TEST_EXENV ${bindir:=.}/dwarf
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
#!/usr/bin/env tesh
!expect signal SIGABRT
-$ ${bindir:=.}/random_bug ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=model-check:1 --cfg=model-check/record:1
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/record' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/random_bug ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=model-check:1 --cfg=model-check/record:1
> [ 0.000000] (0:@) Check a safety property
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (1:app@Tremblay) **************************
> [ 0.000000] (1:app@Tremblay) *** PROPERTY NOT VALID ***
> [ 0.000000] (1:app@Tremblay) **************************
#!/usr/bin/env tesh
-$ ${bindir:=.}/random_bug ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" "--cfg=model-check/replay:1/3;1/4"
-> [ 0.000000] (0:@) Configuration change: Set 'model-check/replay' to '1/3;1/4'
+$ ${bindir:=.}/random_bug ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml --log=xbt_cfg.thresh:warning "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" "--cfg=model-check/replay:1/3;1/4"
> [ 0.000000] (0:@) path=1/3;1/4
> Error reached
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock10
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --log=xbt_cfg.thresh:warning --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock10
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock4
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --log=xbt_cfg.thresh:warning --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock4
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock5
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --log=xbt_cfg.thresh:warning --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock5
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock6
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock6
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-wait-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-wait-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock2
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock3
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 29
> [0.000000] [mc_global/INFO] Executed transitions = 28
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 24
> [0.000000] [mc_global/INFO] Executed transitions = 23
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock2
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 29
> [0.000000] [mc_global/INFO] Executed transitions = 28
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_create
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun --log=xbt_cfg.thresh:warning -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_create
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Executed transitions = 22
> (1) Got MPI_COMM_NULL
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_dup
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_dup
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_split
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_split
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Executed transitions = 34
> (1) Derived communicator too small (size = 1)
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/bcast-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/bcast-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 4
> [0.000000] [mc_global/INFO] Executed transitions = 3
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder-allreduce
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder-allreduce
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 45
> [0.000000] [mc_global/INFO] Executed transitions = 44
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/complex-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/complex-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/deadlock-config
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/deadlock-config
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> WARNING: This test depends on the MPI's eager limit. Set it appropriately.
> Initializing (0 of 3)
> (0) is alive on Tremblay
> [0.000000] [mc_global/INFO] Visited states = 4
> [0.000000] [mc_global/INFO] Executed transitions = 3
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/finalize-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/finalize-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (1) Finished normally
> (2) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/irecv-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/irecv-deadlock
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 22
> [0.000000] [mc_global/INFO] Executed transitions = 21
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (0) Finished normally
> (1) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error2
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3-any_src
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3-any_src
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml --log=xbt_cfg.thresh:warning -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-