From: Gabriel Corona Date: Thu, 12 Feb 2015 15:03:51 +0000 (+0100) Subject: Merge master into mc-process X-Git-Tag: v3_12~732^2~119 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/ffe8ce65fd9a8e18a0469f26f067c3ea6d5d60d4?hp=0ccbaaa805875e64f29ceb8434e17c7de99b050c Merge master into mc-process --- diff --git a/buildtools/Cmake/CompleteInFiles.cmake b/buildtools/Cmake/CompleteInFiles.cmake index 9600214c05..b1ba41ffd8 100644 --- a/buildtools/Cmake/CompleteInFiles.cmake +++ b/buildtools/Cmake/CompleteInFiles.cmake @@ -172,6 +172,7 @@ CHECK_FUNCTION_EXISTS(asprintf HAVE_ASPRINTF) 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( diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index 790a06d452..76cc745f56 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -594,10 +594,19 @@ set(MC_SRC_BASE ) 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 @@ -633,8 +642,18 @@ set(MC_SRC 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 diff --git a/buildtools/Cmake/Distrib.cmake b/buildtools/Cmake/Distrib.cmake index 428db7c6ea..53f9e09fb5 100644 --- a/buildtools/Cmake/Distrib.cmake +++ b/buildtools/Cmake/Distrib.cmake @@ -205,6 +205,7 @@ set(source_to_pack ${LUA_SRC} ${MC_SRC_BASE} ${MC_SRC} + ${MC_SIMGRID_MC_SRC} ${MSG_SRC} ${NS3_SRC} ${RNGSTREAM_SRC} diff --git a/buildtools/Cmake/Flags.cmake b/buildtools/Cmake/Flags.cmake index d45e7f9305..27aa988d29 100644 --- a/buildtools/Cmake/Flags.cmake +++ b/buildtools/Cmake/Flags.cmake @@ -1,9 +1,23 @@ 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") @@ -63,16 +77,19 @@ if(enable_model-checking AND enable_compile_optimizations) 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") diff --git a/buildtools/Cmake/MakeLib.cmake b/buildtools/Cmake/MakeLib.cmake index 9f15a915bd..91611c92c0 100644 --- a/buildtools/Cmake/MakeLib.cmake +++ b/buildtools/Cmake/MakeLib.cmake @@ -22,6 +22,14 @@ endif() 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") @@ -93,7 +101,7 @@ if(HAVE_MC) # 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") diff --git a/buildtools/Cmake/PrintArgs.cmake b/buildtools/Cmake/PrintArgs.cmake index 518092640a..9805a49fc1 100644 --- a/buildtools/Cmake/PrintArgs.cmake +++ b/buildtools/Cmake/PrintArgs.cmake @@ -62,6 +62,7 @@ if(enable_print_message) 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("") diff --git a/buildtools/Cmake/src/internal_config.h.in b/buildtools/Cmake/src/internal_config.h.in index 76f05f8540..577178acd6 100644 --- a/buildtools/Cmake/src/internal_config.h.in +++ b/buildtools/Cmake/src/internal_config.h.in @@ -132,6 +132,9 @@ /* 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@ diff --git a/examples/msg/mc/bugged1.tesh b/examples/msg/mc/bugged1.tesh index 85cd2ce791..03f5d54f9b 100644 --- a/examples/msg/mc/bugged1.tesh +++ b/examples/msg/mc/bugged1.tesh @@ -2,11 +2,8 @@ ! 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 @@ -37,4 +34,3 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)% > [ 0.000000] (1:server@HostA) Expanded states = 22 > [ 0.000000] (1:server@HostA) Visited states = 56 > [ 0.000000] (1:server@HostA) Executed transitions = 52 - diff --git a/examples/msg/mc/bugged1_liveness.c b/examples/msg/mc/bugged1_liveness.c index 5143623f2e..c5e9820a3b 100644 --- a/examples/msg/mc/bugged1_liveness.c +++ b/examples/msg/mc/bugged1_liveness.c @@ -26,14 +26,6 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(bugged1_liveness, "my log messages"); 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) { @@ -165,8 +157,8 @@ int main(int argc, char *argv[]) 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]; diff --git a/examples/msg/mc/bugged1_liveness.tesh b/examples/msg/mc/bugged1_liveness.tesh index 5f72c22e51..dc3c3a7be1 100644 --- a/examples/msg/mc/bugged1_liveness.tesh +++ b/examples/msg/mc/bugged1_liveness.tesh @@ -2,11 +2,8 @@ ! 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 diff --git a/examples/msg/mc/bugged1_liveness_sparse.tesh b/examples/msg/mc/bugged1_liveness_sparse.tesh index bc934d924e..1ad6da3b2e 100644 --- a/examples/msg/mc/bugged1_liveness_sparse.tesh +++ b/examples/msg/mc/bugged1_liveness_sparse.tesh @@ -2,12 +2,8 @@ ! 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 diff --git a/examples/msg/mc/bugged1_liveness_visited.tesh b/examples/msg/mc/bugged1_liveness_visited.tesh index d05858a39f..859e793af3 100644 --- a/examples/msg/mc/bugged1_liveness_visited.tesh +++ b/examples/msg/mc/bugged1_liveness_visited.tesh @@ -2,12 +2,8 @@ ! 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 diff --git a/examples/msg/mc/bugged1_liveness_visited_sparse.tesh b/examples/msg/mc/bugged1_liveness_visited_sparse.tesh index 9e987ea3cd..1750e8b638 100644 --- a/examples/msg/mc/bugged1_liveness_visited_sparse.tesh +++ b/examples/msg/mc/bugged1_liveness_visited_sparse.tesh @@ -2,13 +2,8 @@ ! 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 diff --git a/examples/msg/mc/bugged2.tesh b/examples/msg/mc/bugged2.tesh index d3d7eec5e1..49619cea8f 100644 --- a/examples/msg/mc/bugged2.tesh +++ b/examples/msg/mc/bugged2.tesh @@ -2,11 +2,8 @@ ! 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 @@ -899,4 +896,3 @@ $ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)% > [ 0.000000] (1:server@HostA) Expanded states = 461 > [ 0.000000] (1:server@HostA) Visited states = 2271 > [ 0.000000] (1:server@HostA) Executed transitions = 2117 - diff --git a/examples/msg/mc/bugged2_liveness.c b/examples/msg/mc/bugged2_liveness.c index d6beac0f42..25e2dedd2e 100644 --- a/examples/msg/mc/bugged2_liveness.c +++ b/examples/msg/mc/bugged2_liveness.c @@ -19,11 +19,6 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(bugged3, "my log messages"); int cs = 0; -int predCS(){ - return cs; -} - - int coordinator(int argc, char **argv); int client(int argc, char **argv); @@ -103,7 +98,7 @@ int main(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); diff --git a/examples/smpi/mc/bugged1_liveness.c b/examples/smpi/mc/bugged1_liveness.c index 68a5ef4671..b92f4e3909 100644 --- a/examples/smpi/mc/bugged1_liveness.c +++ b/examples/smpi/mc/bugged1_liveness.c @@ -23,15 +23,6 @@ int r, cs; -static int predR(){ - return r; -} - -static int predCS(){ - return cs; -} - - int main(int argc, char **argv){ int err, size, rank; @@ -47,8 +38,8 @@ int main(int argc, char **argv){ 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)); diff --git a/examples/smpi/mc/non_deterministic.tesh b/examples/smpi/mc/non_deterministic.tesh index d32f46a291..494c917120 100644 --- a/examples/smpi/mc/non_deterministic.tesh +++ b/examples/smpi/mc/non_deterministic.tesh @@ -1,18 +1,9 @@ #! ./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 ***** diff --git a/examples/smpi/mc/send_deterministic.tesh b/examples/smpi/mc/send_deterministic.tesh index 6bafa97516..39dccba678 100644 --- a/examples/smpi/mc/send_deterministic.tesh +++ b/examples/smpi/mc/send_deterministic.tesh @@ -1,18 +1,9 @@ #! ./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 diff --git a/include/simgrid/modelchecker.h b/include/simgrid/modelchecker.h index 0d41344468..3cc7e2d583 100644 --- a/include/simgrid/modelchecker.h +++ b/include/simgrid/modelchecker.h @@ -17,6 +17,17 @@ 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 @@ -28,7 +39,11 @@ extern int _sg_mc_visited; #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); @@ -41,6 +56,9 @@ XBT_PUBLIC(void) MC_ignore(void *addr, size_t size); #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) @@ -48,17 +66,6 @@ XBT_PUBLIC(void) MC_ignore(void *addr, size_t size); #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 */ diff --git a/include/xbt/automaton.h b/include/xbt/automaton.h index c24453f727..e6267e243b 100644 --- a/include/xbt/automaton.h +++ b/include/xbt/automaton.h @@ -57,13 +57,11 @@ typedef struct xbt_automaton_transition { 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); @@ -99,7 +97,21 @@ XBT_PUBLIC(void) xbt_automaton_display(xbt_automaton_t a); 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); diff --git a/include/xbt/mmalloc.h b/include/xbt/mmalloc.h index 191d3cc3e2..5e32858826 100644 --- a/include/xbt/mmalloc.h +++ b/include/xbt/mmalloc.h @@ -62,7 +62,7 @@ XBT_PUBLIC( void ) *xbt_mheap_destroy(xbt_mheap_t md); 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; @@ -71,12 +71,14 @@ struct s_dw_type; 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 diff --git a/src/include/mc/datatypes.h b/src/include/mc/datatypes.h index 20805a8549..22c7e4f7dc 100644 --- a/src/include/mc/datatypes.h +++ b/src/include/mc/datatypes.h @@ -7,8 +7,6 @@ #ifndef MC_DATATYPE_H #define MC_DATATYPE_H -#define UNW_LOCAL_ONLY - #include "xbt/misc.h" #include "xbt/swag.h" #include "xbt/fifo.h" @@ -33,7 +31,6 @@ typedef struct s_mc_heap_ignore_region{ typedef struct s_stack_region{ void *address; - char *process_name; void *context; size_t size; int block; diff --git a/src/include/mc/mc.h b/src/include/mc/mc.h index 2bfe7ad44b..23b17815c7 100644 --- a/src/include/mc/mc.h +++ b/src/include/mc/mc.h @@ -51,11 +51,10 @@ extern int _sg_mc_comms_determinism; 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); @@ -65,6 +64,7 @@ void _mc_cfg_cb_soft_dirty(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); @@ -88,6 +88,7 @@ XBT_PUBLIC(void) MC_new_stack_area(void *stack, smx_process_t process, void *con /********************************* 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() diff --git a/src/mc/mc_address_space.c b/src/mc/mc_address_space.c new file mode 100644 index 0000000000..df738ecf2d --- /dev/null +++ b/src/mc/mc_address_space.c @@ -0,0 +1,7 @@ +/* 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" diff --git a/src/mc/mc_address_space.h b/src/mc/mc_address_space.h new file mode 100644 index 0000000000..a8724bc35a --- /dev/null +++ b/src/mc/mc_address_space.h @@ -0,0 +1,89 @@ +/* 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 + +#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 diff --git a/src/mc/mc_base.c b/src/mc/mc_base.c index 82ca8c6a4f..96c14b2606 100644 --- a/src/mc/mc_base.c +++ b/src/mc/mc_base.c @@ -10,11 +10,13 @@ #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; diff --git a/src/mc/mc_base.h b/src/mc/mc_base.h index c46241459f..c21a00bc26 100644 --- a/src/mc/mc_base.h +++ b/src/mc/mc_base.h @@ -14,8 +14,24 @@ 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; diff --git a/src/mc/mc_checkpoint.c b/src/mc/mc_checkpoint.c index 38f64893db..1fdf717986 100644 --- a/src/mc/mc_checkpoint.c +++ b/src/mc/mc_checkpoint.c @@ -5,7 +5,6 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #define _GNU_SOURCE -#define UNW_LOCAL_ONLY #include @@ -25,7 +24,6 @@ #include "../simix/smx_private.h" -#define UNW_LOCAL_ONLY #include #include @@ -35,12 +33,12 @@ #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 **************************************/ /*****************************************************************************************/ @@ -49,13 +47,16 @@ static void MC_snapshot_stack_free(mc_snapshot_stack_t s) 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) @@ -69,59 +70,66 @@ static void local_variable_free_voidp(void *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 @@ -132,7 +140,7 @@ static mc_mem_region_t mc_region_new_dense(int type, void *start_addr, void* per * @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); @@ -151,113 +159,139 @@ static mc_mem_region_t MC_region_new(int type, void *start_addr, void* permanent * @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); @@ -294,6 +328,18 @@ void MC_find_object_address(memory_map_t maps, mc_object_info_t result) 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); @@ -324,6 +370,8 @@ static bool mc_valid_variable(dw_variable_t var, dw_frame_t scope, 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; @@ -336,7 +384,8 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, 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; @@ -352,6 +401,7 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, 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), @@ -405,15 +455,16 @@ static void MC_stack_frame_free_voipd(void *s) } } -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"); @@ -435,7 +486,7 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) // 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) { @@ -452,11 +503,11 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) && !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"); } } @@ -478,9 +529,19 @@ static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t * snapshot) 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; @@ -497,6 +558,7 @@ static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t * snapshot) } +// FIXME, cross-process support (mc_heap_comparison_ignore) static xbt_dynar_t MC_take_snapshot_ignore() { @@ -531,23 +593,28 @@ static void mc_free_snapshot_ignored_data_pvoid(void* data) { 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); } } @@ -557,7 +624,8 @@ static void MC_snapshot_ignore_restore(mc_snapshot_t snapshot) 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); } } @@ -580,17 +648,18 @@ int mc_important_snapshot(mc_snapshot_t snapshot) 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"); @@ -605,7 +674,8 @@ static void MC_get_current_fd(mc_snapshot_t snapshot){ 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; @@ -655,25 +725,37 @@ static void MC_get_current_fd(mc_snapshot_t snapshot){ 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(); @@ -690,36 +772,25 @@ mc_snapshot_t MC_take_snapshot(int num_state) } 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 @@ -730,7 +801,16 @@ void MC_restore_snapshot(mc_snapshot_t snapshot) 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); @@ -745,24 +825,29 @@ void MC_restore_snapshot(mc_snapshot_t snapshot) }; 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(); -} diff --git a/src/mc/mc_client.c b/src/mc/mc_client.c new file mode 100644 index 0000000000..6a8d4eeb07 --- /dev/null +++ b/src/mc/mc_client.c @@ -0,0 +1,94 @@ +/* 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 +#include +#include + +#include +#include + +#include +#include +#include + +#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); + } + } +} diff --git a/src/mc/mc_client.h b/src/mc/mc_client.h new file mode 100644 index 0000000000..638a8eafda --- /dev/null +++ b/src/mc/mc_client.h @@ -0,0 +1,31 @@ +/* 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 + +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 diff --git a/src/mc/mc_client_api.c b/src/mc/mc_client_api.c new file mode 100644 index 0000000000..fad7c0ffd8 --- /dev/null +++ b/src/mc/mc_client_api.c @@ -0,0 +1,74 @@ +/* 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 +#include +#include +#include + +#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); +} diff --git a/src/mc/mc_comm_determinism.c b/src/mc/mc_comm_determinism.c index b68e563946..6576d606c2 100644 --- a/src/mc/mc_comm_determinism.c +++ b/src/mc/mc_comm_determinism.c @@ -167,6 +167,7 @@ static void print_incomplete_communications_pattern(){ 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; @@ -176,7 +177,8 @@ static void update_comm_pattern(mc_comm_pattern_t comm_pattern, smx_synchro_t co 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); @@ -216,7 +218,7 @@ void list_comm_pattern_free_voidp(void *p) { 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; @@ -237,7 +239,8 @@ void get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, e_mc_call_type_t 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); @@ -322,16 +325,12 @@ void complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm, int backtrackin 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); diff --git a/src/mc/mc_compare.cpp b/src/mc/mc_compare.cpp index 4745d3a4ee..5b6352ade7 100644 --- a/src/mc/mc_compare.cpp +++ b/src/mc/mc_compare.cpp @@ -60,7 +60,6 @@ extern "C" { static void stack_region_free(stack_region_t s) { if (s) { - xbt_free(s->process_name); xbt_free(s); } } @@ -102,6 +101,8 @@ static int compare_areas_with_type(struct mc_compare_state& state, 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; @@ -115,7 +116,7 @@ static int compare_areas_with_type(struct mc_compare_state& state, 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; } @@ -169,8 +170,8 @@ static int compare_areas_with_type(struct mc_compare_state& state, 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); @@ -190,10 +191,10 @@ static int compare_areas_with_type(struct mc_compare_state& state, // * 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: @@ -228,9 +229,9 @@ static int compare_areas_with_type(struct mc_compare_state& state, 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 = @@ -260,6 +261,32 @@ static int compare_global_variables(mc_object_info_t object_info, 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; @@ -357,6 +384,7 @@ static int compare_local_variables(int process_index, int snapshot_compare(void *state1, void *state2) { + mc_process_t process = &mc_model_checker->process; mc_snapshot_t s1, s2; int num1, num2; @@ -456,10 +484,14 @@ int snapshot_compare(void *state1, void *state2) #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 @@ -535,21 +567,27 @@ int snapshot_compare(void *state1, void *state2) 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); @@ -557,33 +595,24 @@ int snapshot_compare(void *state1, void *state2) #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(); @@ -679,28 +708,9 @@ void print_comparison_times() 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); - -} - } diff --git a/src/mc/mc_config.c b/src/mc/mc_config.c index 07c9179889..62517120ba 100644 --- a/src/mc/mc_config.c +++ b/src/mc/mc_config.c @@ -58,7 +58,7 @@ int _sg_mc_comms_determinism = 0; 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) { @@ -118,6 +118,15 @@ void _mc_cfg_cb_hash(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) { diff --git a/src/mc/mc_diff.c b/src/mc/mc_diff.c index 03dfb36aba..257481c2a2 100644 --- a/src/mc/mc_diff.c +++ b/src/mc/mc_diff.c @@ -20,7 +20,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_diff, xbt, xbt_dynar_t mc_heap_comparison_ignore; xbt_dynar_t stacks_areas; -void *maestro_stack_start, *maestro_stack_end; + /********************************* Backtrace ***********************************/ @@ -229,7 +229,7 @@ static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, } static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list, - void *address) + const void *address) { unsigned int cursor = 0; @@ -253,7 +253,7 @@ static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list, return -1; } -static int is_stack(void *address) +static int is_stack(const void *address) { unsigned int cursor = 0; stack_region_t stack; @@ -415,9 +415,22 @@ void reset_heap_information() } -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 */ @@ -434,17 +447,20 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) 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 ++; @@ -490,7 +506,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) (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) { @@ -517,7 +533,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) 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++; @@ -530,7 +546,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) } 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) { @@ -583,7 +599,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) (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) @@ -595,7 +611,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) 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 ++; @@ -630,7 +646,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) (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) { @@ -667,7 +683,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) 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) { @@ -708,7 +724,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) 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) { @@ -763,20 +779,21 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2) * @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) { @@ -799,16 +816,16 @@ static int compare_heap_area_without_type(struct s_mc_diff *state, int process_i } } - 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 @@ -853,7 +870,7 @@ static int compare_heap_area_without_type(struct s_mc_diff *state, int process_i * @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, @@ -878,10 +895,10 @@ top: 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: @@ -892,12 +909,12 @@ top: 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; @@ -905,7 +922,7 @@ top: 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: @@ -962,15 +979,15 @@ top: 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 @@ -985,8 +1002,8 @@ top: 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 @@ -1023,9 +1040,9 @@ top: 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, @@ -1091,7 +1108,7 @@ static dw_type_t get_offset_type(void *real_base_address, dw_type_t type, 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; } @@ -1118,10 +1135,11 @@ static dw_type_t get_offset_type(void *real_base_address, dw_type_t type, * @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; @@ -1138,8 +1156,11 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t 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; @@ -1203,11 +1224,11 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t } - 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)) { diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c index 2b2c2a0aaa..a286459ea8 100644 --- a/src/mc/mc_dwarf.c +++ b/src/mc/mc_dwarf.c @@ -1024,7 +1024,7 @@ void MC_dwarf_get_variables(mc_object_info_t info) } 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; @@ -1172,48 +1172,6 @@ static void MC_make_functions_index(mc_object_info_t info) 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; @@ -1310,7 +1268,7 @@ static void MC_post_process_types(mc_object_info_t info) } /** \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(); @@ -1408,7 +1366,7 @@ void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, 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; @@ -1417,9 +1375,9 @@ void MC_post_process_object_info(mc_object_info_t info) // 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; diff --git a/src/mc/mc_dwarf_expression.c b/src/mc/mc_dwarf_expression.c index 7653210faf..92e4e47bfc 100644 --- a/src/mc/mc_dwarf_expression.c +++ b/src/mc/mc_dwarf_expression.c @@ -11,7 +11,6 @@ #include #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) @@ -23,6 +22,12 @@ 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) @@ -84,7 +89,7 @@ static int mc_dwarf_register_to_libunwind(int dwarf_register) 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 } @@ -168,15 +173,16 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, { 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: @@ -212,17 +218,20 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, 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: @@ -238,9 +247,9 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, 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; @@ -248,6 +257,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, 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; @@ -255,6 +265,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, 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; @@ -266,13 +277,17 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, } 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) @@ -373,7 +388,8 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, case DW_OP_nop: break; - // Dereference: + // ***** Deference (memory fetch) + case DW_OP_deref_size: return MC_EXPRESSION_E_UNSUPPORTED_OPERATION; @@ -383,9 +399,19 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops, { // 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; @@ -410,13 +436,13 @@ void mc_dwarf_resolve_location(mc_location_t location, 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; @@ -459,7 +485,7 @@ void mc_dwarf_resolve_locations(mc_location_t location, 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; @@ -472,7 +498,7 @@ void mc_dwarf_resolve_locations(mc_location_t location, 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"); } diff --git a/src/mc/mc_forward.h b/src/mc/mc_forward.h index 267f82cbfa..bd78e99299 100644 --- a/src/mc/mc_forward.h +++ b/src/mc/mc_forward.h @@ -15,7 +15,11 @@ typedef struct s_dw_type s_dw_type_t, *dw_type_t; 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; diff --git a/src/mc/mc_global.c b/src/mc/mc_global.c index 63ecd05968..85dacbca78 100644 --- a/src/mc/mc_global.c +++ b/src/mc/mc_global.c @@ -4,15 +4,14 @@ /* 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 + #include "mc_base.h" #ifndef _XBT_WIN32 #include -#include #include #include -#include -#include #endif #include "simgrid/sg_config.h" @@ -23,8 +22,8 @@ #include "xbt/dict.h" #ifdef HAVE_MC -#define UNW_LOCAL_ONLY #include +#include #include "../xbt/mmalloc/mmprivate.h" #include "mc_object_info.h" @@ -35,12 +34,17 @@ #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 @@ -59,14 +63,6 @@ xbt_fifo_t mc_stack = NULL; /* 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]; @@ -104,57 +100,29 @@ static void MC_init_dot_output() } -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); @@ -162,9 +130,6 @@ void MC_init() 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(); @@ -212,16 +177,22 @@ void MC_init() /* 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(); + } } @@ -230,13 +201,9 @@ void MC_init() 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(); @@ -255,21 +222,16 @@ static void MC_modelcheck_comm_determinism_init(void) 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(); @@ -286,8 +248,7 @@ static void MC_modelcheck_safety_init(void) MC_modelcheck_safety(); - if (mc_mem_set) - MC_SET_MC_HEAP; + mmalloc_set_current_heap(heap); xbt_abort(); //MC_exit(); @@ -295,15 +256,11 @@ static void MC_modelcheck_safety_init(void) 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(); @@ -319,8 +276,7 @@ static void MC_modelcheck_liveness_init() MC_print_statistics(mc_stats); xbt_free(mc_time); - if (mc_mem_set) - MC_SET_MC_HEAP; + mmalloc_set_current_heap(heap); } @@ -443,7 +399,7 @@ static void MC_restore_communications_pattern(mc_state_t state) { */ 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; @@ -530,13 +486,7 @@ void MC_replay(xbt_fifo_t stack) } 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) @@ -627,8 +577,7 @@ 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); @@ -637,22 +586,13 @@ void MC_dump_stack_safety(xbt_fifo_t 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; @@ -671,8 +611,7 @@ void MC_show_stack_safety(xbt_fifo_t stack) } } - if (!raw_mem_set) - MC_SET_STD_HEAP; + mmalloc_set_current_heap(heap); } void MC_show_deadlock(smx_simcall_t req) @@ -714,26 +653,16 @@ void MC_show_stack_liveness(xbt_fifo_t stack) 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); @@ -742,7 +671,7 @@ void MC_print_statistics(mc_stats_t stats) 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); @@ -753,70 +682,73 @@ void MC_print_statistics(mc_stats_t stats) 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; @@ -838,9 +770,7 @@ void MC_dump_stacks(FILE* file) ++nstack; } - - if (raw_mem_set) - MC_SET_MC_HEAP; + mmalloc_set_current_heap(heap); } #endif diff --git a/src/mc/mc_hash.c b/src/mc/mc_hash.c index cc78c3d7e2..b83bc83be8 100644 --- a/src/mc/mc_hash.c +++ b/src/mc/mc_hash.c @@ -81,6 +81,7 @@ static void mc_hash_value(mc_hash_t * hash, mc_hashing_state * state, mc_object_info_t info, const void *address, dw_type_t type) { + mc_process_t process = &mc_model_checker->process; top: switch (type->type) { @@ -171,12 +172,12 @@ top: 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; @@ -220,12 +221,12 @@ static void mc_hash_object_globals(mc_hash_t * hash, mc_hashing_state * state, } 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; @@ -285,12 +286,12 @@ static void mc_hash_stack(mc_hash_t * hash, mc_snapshot_stack_t stack, 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; @@ -328,8 +329,8 @@ uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks) 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); diff --git a/src/mc/mc_ignore.c b/src/mc/mc_ignore.c index 13cab5e2e2..f213822d98 100644 --- a/src/mc/mc_ignore.c +++ b/src/mc/mc_ignore.c @@ -9,13 +9,19 @@ #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; @@ -59,41 +65,22 @@ static void checkpoint_ignore_region_free_voidp(void *r) 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; } @@ -102,39 +89,84 @@ void MC_ignore_heap(void *address, size_t size) 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; @@ -167,44 +199,40 @@ void MC_remove_ignore_heap(void *address, size_t size) 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 @@ -225,7 +253,7 @@ static void mc_ignore_local_variable_in_scope(const char *var_name, { // 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)) { @@ -283,29 +311,34 @@ static void MC_ignore_local_variable_in_object(const char *var_name, } } +// 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 @@ -315,18 +348,10 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name) */ 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 = @@ -339,49 +364,44 @@ void MC_new_stack_area(void *stack, smx_process_t process, void *context, size_t #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; @@ -397,17 +417,14 @@ void MC_ignore(void *addr, size_t size) 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; } diff --git a/src/mc/mc_ignore.h b/src/mc/mc_ignore.h new file mode 100644 index 0000000000..fef9bcd633 --- /dev/null +++ b/src/mc/mc_ignore.h @@ -0,0 +1,22 @@ +/* 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 + +#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(); diff --git a/src/mc/mc_liveness.c b/src/mc/mc_liveness.c index 6a21a60f2c..ec50dad337 100644 --- a/src/mc/mc_liveness.c +++ b/src/mc/mc_liveness.c @@ -27,27 +27,19 @@ xbt_parmap_t parmap; 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); @@ -87,10 +79,7 @@ static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){ 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; } } @@ -112,19 +101,13 @@ static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){ } } - - 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; @@ -147,8 +130,7 @@ static void remove_acceptance_pair(int pair_num) { } - if (!raw_mem_set) - MC_SET_STD_HEAP; + mmalloc_set_current_heap(heap); } @@ -175,7 +157,7 @@ static int MC_automaton_evaluate_label(xbt_automaton_exp_label_t l, 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; @@ -238,12 +220,10 @@ void MC_pre_modelcheck_liveness(void) { 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; diff --git a/src/mc/mc_location.h b/src/mc/mc_location.h index 45657f4551..5c450caae7 100644 --- a/src/mc/mc_location.h +++ b/src/mc/mc_location.h @@ -9,7 +9,6 @@ #include -#define UNW_LOCAL_ONLY #include #include #include @@ -18,6 +17,7 @@ #include "mc_interface.h" #include "mc_object_info.h" #include "mc_forward.h" +#include "mc_address_space.h" SG_BEGIN_DECL() @@ -76,8 +76,8 @@ enum mc_location_type mc_get_location_type(mc_location_t location) { } } -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); @@ -103,7 +103,7 @@ typedef struct s_mc_expression_state { 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; diff --git a/src/mc/mc_member.c b/src/mc/mc_member.c index b5ee0690f0..666a2463a7 100644 --- a/src/mc/mc_member.c +++ b/src/mc/mc_member.c @@ -16,7 +16,7 @@ * @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; @@ -26,7 +26,7 @@ void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member, 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; diff --git a/src/mc/mc_memory.c b/src/mc/mc_memory.c index b474b0ced6..72f51a9159 100644 --- a/src/mc/mc_memory.c +++ b/src/mc/mc_memory.c @@ -8,6 +8,8 @@ #include #include "xbt/log.h" +#include "xbt/dynar.h" +#include "xbt/virtu.h" #include "mc/mc.h" #include "mc_object_info.h" @@ -24,30 +26,26 @@ xbt_mheap_t mc_heap = NULL; /* memory persistent over the MC rollbacks /* 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); } diff --git a/src/mc/mc_memory_map.h b/src/mc/mc_memory_map.h index afa2b58c67..12da85f89c 100644 --- a/src/mc/mc_memory_map.h +++ b/src/mc/mc_memory_map.h @@ -7,6 +7,8 @@ #ifndef MC_MEMORY_MAP_H #define MC_MEMORY_MAP_H +#include + #include #include "mc_forward.h" @@ -39,8 +41,7 @@ struct s_memory_map { }; -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() diff --git a/src/mc/mc_mmu.h b/src/mc/mc_mmu.h index 6740829b8c..1fa7423f35 100644 --- a/src/mc/mc_mmu.h +++ b/src/mc/mc_mmu.h @@ -38,7 +38,7 @@ size_t mc_page_count(size_t size) * @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; @@ -50,7 +50,7 @@ size_t mc_page_number(void* base, void* address) * @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); } @@ -61,13 +61,13 @@ size_t mc_page_offset(void* address) * @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); } diff --git a/src/mc/mc_model_checker.c b/src/mc/mc_model_checker.c new file mode 100644 index 0000000000..e3cc96165c --- /dev/null +++ b/src/mc/mc_model_checker.c @@ -0,0 +1,28 @@ +/* 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); +} diff --git a/src/mc/mc_model_checker.h b/src/mc/mc_model_checker.h index 9ab2813c23..308cf127ff 100644 --- a/src/mc/mc_model_checker.h +++ b/src/mc/mc_model_checker.h @@ -7,9 +7,13 @@ #ifndef MC_MODEL_CHECKER_H #define MC_MODEL_CHECKER_H +#include + #include #include "mc_forward.h" +#include "mc_process.h" +#include "mc_page_store.h" SG_BEGIN_DECL() @@ -27,9 +31,10 @@ struct s_mc_model_checker { 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() diff --git a/src/mc/mc_object_info.c b/src/mc/mc_object_info.c new file mode 100644 index 0000000000..874235c7ed --- /dev/null +++ b/src/mc/mc_object_info.c @@ -0,0 +1,38 @@ +#include + +#include + +#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; +} diff --git a/src/mc/mc_object_info.h b/src/mc/mc_object_info.h index 2e0b68f43e..9914c56dbc 100644 --- a/src/mc/mc_object_info.h +++ b/src/mc/mc_object_info.h @@ -12,6 +12,7 @@ #define MC_OBJECT_INFO_H #include +#include #include #include @@ -19,6 +20,8 @@ #include "mc_forward.h" #include "mc_location.h" +#include "mc_process.h" +#include "../smpi/private.h" SG_BEGIN_DECL(); @@ -58,6 +61,7 @@ enum mc_object_info_flags { 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 @@ -72,6 +76,18 @@ struct s_mc_object_info { 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: @@ -89,10 +105,13 @@ struct s_mc_object_info { 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); @@ -102,12 +121,7 @@ const char* MC_dwarf_tagname(int tag); // 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. */ diff --git a/src/mc/mc_page_snapshot.cpp b/src/mc/mc_page_snapshot.cpp index 499e5f210f..c8aa50fadd 100644 --- a/src/mc/mc_page_snapshot.cpp +++ b/src/mc/mc_page_snapshot.cpp @@ -1,3 +1,5 @@ +#include // pread, pwrite + #include "mc_page_store.h" #include "mc_mmu.h" #include "mc_private.h" @@ -20,10 +22,17 @@ extern "C" { * @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) { @@ -34,10 +43,27 @@ size_t* mc_take_page_snapshot_region(void* data, size_t page_count, uint64_t* pa // 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; } @@ -59,7 +85,8 @@ void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count) * @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) { @@ -73,7 +100,7 @@ void mc_restore_page_snapshot_region(void* start_addr, size_t page_count, size_t // 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); } } @@ -159,15 +186,18 @@ static void mc_read_pagemap(uint64_t* pagemap, size_t page_start, size_t page_co // ***** 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"); @@ -176,22 +206,27 @@ mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* permanent 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"); @@ -200,14 +235,20 @@ void mc_region_restore_sparse(mc_mem_region_t reg, mc_mem_region_t ref_reg) 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); diff --git a/src/mc/mc_page_store.cpp b/src/mc/mc_page_store.cpp index 11022f8991..222f3a7eff 100644 --- a/src/mc/mc_page_store.cpp +++ b/src/mc/mc_page_store.cpp @@ -140,7 +140,6 @@ void s_mc_pages_store::remove_page(size_t pageno) /** 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 @@ -239,7 +238,7 @@ XBT_TEST_UNIT("base", test_mc_page_store, "Test adding/removing pages in the sto { xbt_test_add("Init"); size_t pagesize = (size_t) getpagesize(); - std::auto_ptr store = std::auto_ptr(new s_mc_pages_store(500)); + std::unique_ptr store = std::unique_ptr(new s_mc_pages_store(500)); void* data = getpage(); xbt_test_assert(store->size()==0, "Bad size"); diff --git a/src/mc/mc_private.h b/src/mc/mc_private.h index 4a86245aeb..bcc454fce1 100644 --- a/src/mc/mc_private.h +++ b/src/mc/mc_private.h @@ -7,6 +7,8 @@ #ifndef MC_PRIVATE_H #define MC_PRIVATE_H +#include + #include "simgrid_config.h" #include #include @@ -21,6 +23,7 @@ #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" @@ -38,12 +41,15 @@ SG_BEGIN_DECL() 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; @@ -82,16 +88,13 @@ extern mc_stats_t mc_stats; 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; @@ -107,9 +110,6 @@ void print_comparison_times(void); /********************************** 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 **********************************/ diff --git a/src/mc/mc_process.c b/src/mc/mc_process.c new file mode 100644 index 0000000000..65c77a85db --- /dev/null +++ b/src/mc/mc_process.c @@ -0,0 +1,514 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // PROT_* + +#include + +#include + +#include +#include + +#include + +#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; + } + } +} diff --git a/src/mc/mc_process.h b/src/mc/mc_process.h new file mode 100644 index 0000000000..1e4384d153 --- /dev/null +++ b/src/mc/mc_process.h @@ -0,0 +1,191 @@ +/* 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 +#include + +#include "simgrid_config.h" + +#include + +#include +#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 diff --git a/src/mc/mc_protocol.c b/src/mc/mc_protocol.c new file mode 100644 index 0000000000..405a61a46a --- /dev/null +++ b/src/mc/mc_protocol.c @@ -0,0 +1,64 @@ +/* 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 +#include + +#include +#include + +#include + +#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; +} diff --git a/src/mc/mc_protocol.h b/src/mc/mc_protocol.h new file mode 100644 index 0000000000..251e1842b0 --- /dev/null +++ b/src/mc/mc_protocol.h @@ -0,0 +1,97 @@ +/* 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 + +#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 diff --git a/src/mc/mc_safety.c b/src/mc/mc_safety.c index 83460ff5da..3d0fc9e41b 100644 --- a/src/mc/mc_safety.c +++ b/src/mc/mc_safety.c @@ -20,15 +20,10 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_safety, mc, */ 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); @@ -55,9 +50,7 @@ void MC_pre_modelcheck_safety() } xbt_fifo_unshift(mc_stack, initial_state); - - if (!mc_mem_set) - MC_SET_STD_HEAP; + mmalloc_set_current_heap(heap); } diff --git a/src/mc/mc_server.cpp b/src/mc/mc_server.cpp new file mode 100644 index 0000000000..12ca0a89a3 --- /dev/null +++ b/src/mc/mc_server.cpp @@ -0,0 +1,329 @@ +/* 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 +#include + +#include +#include +#include +#include +#include + +#include + +#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; + } +} diff --git a/src/mc/mc_server.h b/src/mc/mc_server.h new file mode 100644 index 0000000000..a8ea31bcb3 --- /dev/null +++ b/src/mc/mc_server.h @@ -0,0 +1,45 @@ +/* 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 + +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 diff --git a/src/mc/mc_snapshot.c b/src/mc/mc_snapshot.c index 97c4017b0e..0a4f4f564d 100644 --- a/src/mc/mc_snapshot.c +++ b/src/mc/mc_snapshot.c @@ -21,37 +21,35 @@ * @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; @@ -65,7 +63,7 @@ mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int p * @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; @@ -105,14 +103,15 @@ void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* targ * @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) @@ -123,18 +122,20 @@ void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, vo * @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; @@ -156,13 +157,13 @@ int mc_snapshot_region_memcmp( * @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 @@ -219,56 +220,56 @@ static void test_snapshot(bool sparse_checkpoint) { // 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 *
  • flat/dense snapshots are a simple copy of the region;
  • *
  • sparse/per-page snapshots are snaapshots which shared * identical pages.
  • + *
  • privatized (SMPI global variable privatisation). * + * + * 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. @@ -52,23 +82,29 @@ typedef struct s_mc_mem_region{ * */ 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); @@ -78,12 +114,12 @@ static inline __attribute__((always_inline)) 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 * @@ -115,19 +151,30 @@ void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot, int process_i 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); + } } } @@ -151,11 +198,13 @@ typedef struct s_fd_infos{ 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; @@ -166,18 +215,6 @@ struct s_mc_snapshot{ 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) { @@ -203,11 +240,12 @@ typedef struct s_mc_stack_frame { 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; @@ -222,7 +260,7 @@ typedef struct s_mc_checkpoint_ignore_region{ 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); @@ -230,40 +268,42 @@ void MC_free_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 @@ -275,9 +315,10 @@ static inline __attribute__ ((always_inline)) * @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; @@ -285,34 +326,39 @@ void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, 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() diff --git a/src/mc/mc_unw.c b/src/mc/mc_unw.c new file mode 100644 index 0000000000..ee671769fb --- /dev/null +++ b/src/mc/mc_unw.c @@ -0,0 +1,238 @@ +/* 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 + +// On x86_64, libunwind unw_context_t has the same layout as ucontext_t: +#include + +#include + +#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); +} diff --git a/src/mc/mc_unw.h b/src/mc/mc_unw.h new file mode 100644 index 0000000000..267c850ca8 --- /dev/null +++ b/src/mc/mc_unw.h @@ -0,0 +1,82 @@ +/* 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 diff --git a/src/mc/mc_unw_vmread.c b/src/mc/mc_unw_vmread.c new file mode 100644 index 0000000000..742359ef3a --- /dev/null +++ b/src/mc/mc_unw_vmread.c @@ -0,0 +1,108 @@ +#define _GNU_SOURCE + +#include +#include + +#include +#include + +#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 + }; diff --git a/src/mc/mc_visited.c b/src/mc/mc_visited.c index f792c80b1e..77548d8330 100644 --- a/src/mc/mc_visited.c +++ b/src/mc/mc_visited.c @@ -51,9 +51,12 @@ void visited_state_free_voidp(void *s) */ 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; @@ -63,12 +66,15 @@ static mc_visited_state_t visited_state_new() 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; @@ -125,9 +131,7 @@ void MC_visited_pair_delete(mc_visited_pair_t p) 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; @@ -198,16 +202,13 @@ int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max) *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; } @@ -239,9 +240,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state) } } - 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; @@ -251,10 +250,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_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 { @@ -311,8 +307,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state) 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++; @@ -360,11 +355,8 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state) 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; - } } @@ -376,9 +368,7 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) { 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; @@ -452,8 +442,7 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) { } 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; } } @@ -495,8 +484,6 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) { } - if (!mc_mem_set) - MC_SET_STD_HEAP; - + mmalloc_set_current_heap(heap); return -1; } diff --git a/src/mc/memory_map.c b/src/mc/memory_map.c index b867a86d6f..337ed9da2c 100644 --- a/src/mc/memory_map.c +++ b/src/mc/memory_map.c @@ -4,41 +4,35 @@ /* 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 + +#include + #include "mc_memory_map.h" #include "mc_private.h" -#include 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); @@ -48,8 +42,10 @@ memory_map_t MC_get_memory_map(void) /* 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, " "); } @@ -60,10 +56,12 @@ memory_map_t MC_get_memory_map(void) /* 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') @@ -143,6 +141,8 @@ memory_map_t MC_get_memory_map(void) /* 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)); @@ -151,9 +151,7 @@ memory_map_t MC_get_memory_map(void) } free(line); - fclose(fp); - return ret; } diff --git a/src/mc/simgrid_mc.cpp b/src/mc/simgrid_mc.cpp new file mode 100644 index 0000000000..d121fdbf73 --- /dev/null +++ b/src/mc/simgrid_mc.cpp @@ -0,0 +1,154 @@ +/* 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 + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#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; +} diff --git a/src/simgrid/sg_config.c b/src/simgrid/sg_config.c index 3fc88bcb1b..18b73fbd10 100644 --- a/src/simgrid/sg_config.c +++ b/src/simgrid/sg_config.c @@ -695,6 +695,12 @@ void sg_config_init(int *argc, char **argv) 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)", diff --git a/src/simix/popping_generated.c b/src/simix/popping_generated.c index b339a4a1a0..69806ac5df 100644 --- a/src/simix/popping_generated.c +++ b/src/simix/popping_generated.c @@ -15,6 +15,8 @@ #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); @@ -162,6 +164,11 @@ const char* simcall_names[] = { */ 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; diff --git a/src/simix/simcalls.py b/src/simix/simcalls.py index 41bd69d13a..321a63bf9d 100755 --- a/src/simix/simcalls.py +++ b/src/simix/simcalls.py @@ -281,7 +281,8 @@ if __name__=='__main__': 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'); @@ -302,6 +303,11 @@ if __name__=='__main__': 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'); diff --git a/src/simix/smx_global.c b/src/simix/smx_global.c index ecd64f0502..29474e8500 100644 --- a/src/simix/smx_global.c +++ b/src/simix/smx_global.c @@ -4,6 +4,8 @@ /* 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 + #include "smx_private.h" #include "xbt/heap.h" #include "xbt/sysdep.h" @@ -15,6 +17,9 @@ #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" @@ -206,6 +211,20 @@ void SIMIX_global_init(int *argc, char **argv) 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); } diff --git a/src/smpi/smpi_bench.c b/src/smpi/smpi_bench.c index 26f7c542ee..7507e90939 100644 --- a/src/smpi/smpi_bench.c +++ b/src/smpi/smpi_bench.c @@ -638,6 +638,7 @@ void smpi_really_switch_data_segment(int dest) { } } + // 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); diff --git a/src/surf/network_ib.cpp b/src/surf/network_ib.cpp index de303c931d..9c9854c7a7 100644 --- a/src/surf/network_ib.cpp +++ b/src/surf/network_ib.cpp @@ -51,7 +51,7 @@ static void IB_action_init_callback(NetworkActionPtr action,RoutingEdgePtr src, xbt_die("could not find dst node active comms !"); // act_dst->rate=rate; - ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair(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); diff --git a/src/surf/surf_interface.cpp b/src/surf/surf_interface.cpp index 2e799547f8..16b6f4eacf 100644 --- a/src/surf/surf_interface.cpp +++ b/src/surf/surf_interface.cpp @@ -1101,4 +1101,3 @@ void Action::updateRemainingLazy(double now) m_lastUpdate = now; m_lastValue = lmm_variable_getvalue(getVariable()); } - diff --git a/src/xbt/automaton/automaton.c b/src/xbt/automaton/automaton.c index 5c63609816..a961720fde 100644 --- a/src/xbt/automaton/automaton.c +++ b/src/xbt/automaton/automaton.c @@ -9,6 +9,17 @@ #include "xbt/automaton.h" #include /* 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); @@ -197,15 +208,72 @@ xbt_automaton_state_t xbt_automaton_get_current_state(xbt_automaton_t a){ 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*/ @@ -354,7 +422,11 @@ static void xbt_automaton_propositional_symbol_free(xbt_automaton_propositional_ } 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){ diff --git a/src/xbt/mmalloc/mm_legacy.c b/src/xbt/mmalloc/mm_legacy.c index 3d58ba5929..fac98b140d 100644 --- a/src/xbt/mmalloc/mm_legacy.c +++ b/src/xbt/mmalloc/mm_legacy.c @@ -5,11 +5,18 @@ * 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 + +#include + +#include "../../mc/mc_base.h" #include "mmprivate.h" #include "xbt_modinter.h" #include "internal_config.h" #include +#include "../mc/mc_protocol.h" //#define MM_LEGACY_VERBOSE 1 /* define this to see which version of malloc gets used */ @@ -19,6 +26,12 @@ 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. */ @@ -27,196 +40,133 @@ xbt_mheap_t mmalloc_get_current_heap(void) 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 - -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 */ diff --git a/src/xbt/mmalloc/mm_module.c b/src/xbt/mmalloc/mm_module.c index 86c342163b..8490906407 100644 --- a/src/xbt/mmalloc/mm_module.c +++ b/src/xbt/mmalloc/mm_module.c @@ -343,10 +343,6 @@ void *mmalloc_preinit(void) } 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; } @@ -357,27 +353,31 @@ void mmalloc_postexit(void) // 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; diff --git a/src/xbt/mmalloc/mmprivate.h b/src/xbt/mmalloc/mmprivate.h index c652e41965..8a40c4891d 100644 --- a/src/xbt/mmalloc/mmprivate.h +++ b/src/xbt/mmalloc/mmprivate.h @@ -321,4 +321,11 @@ static inline int mmalloc_get_increment(malloc_info* heapinfo) { 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 */ diff --git a/src/xbt/xbt_main.c b/src/xbt/xbt_main.c index c355f497ab..d07d4a3db9 100644 --- a/src/xbt/xbt_main.c +++ b/src/xbt/xbt_main.c @@ -103,9 +103,6 @@ static void xbt_preinit(void) { ++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); diff --git a/src/xbt_modinter.h b/src/xbt_modinter.h index 079e050d76..ed497cc7e2 100644 --- a/src/xbt_modinter.h +++ b/src/xbt_modinter.h @@ -10,6 +10,8 @@ #define XBT_MODINTER_H #include "xbt/misc.h" +SG_BEGIN_DECL() + /* Modules definitions */ void xbt_backtrace_preinit(void); void xbt_backtrace_postexit(void); @@ -29,5 +31,6 @@ void xbt_os_thread_mod_postexit(void); void *mmalloc_preinit(void); void mmalloc_postexit(void); +SG_END_DECL() #endif /* XBT_MODINTER_H */ diff --git a/teshsuite/mc/dwarf/dwarf.c b/teshsuite/mc/dwarf/dwarf.c index 8b22d4be31..c7ad31c335 100644 --- a/teshsuite/mc/dwarf/dwarf.c +++ b/teshsuite/mc/dwarf/dwarf.c @@ -17,6 +17,7 @@ #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; @@ -33,17 +34,6 @@ static dw_type_t find_type_by_name(mc_object_info_t info, const char* name) { 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; @@ -96,15 +86,16 @@ static void test_local_variable(mc_object_info_t info, const char* function, con } -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; @@ -124,30 +115,31 @@ int some_local_variable = 0; 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; @@ -155,15 +147,15 @@ int main(int argc, char** argv) { 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); } diff --git a/teshsuite/mc/dwarf/dwarf.tesh b/teshsuite/mc/dwarf/dwarf.tesh index 93e284be6d..0491dadc2d 100644 --- a/teshsuite/mc/dwarf/dwarf.tesh +++ b/teshsuite/mc/dwarf/dwarf.tesh @@ -1,5 +1,3 @@ #! ./tesh $ $SG_TEST_EXENV ${bindir:=.}/dwarf -> [0.000000] [mc_global/INFO] Get debug information ... -> [0.000000] [mc_global/INFO] Get debug information done ! diff --git a/teshsuite/mc/replay/random_bug.tesh b/teshsuite/mc/replay/random_bug.tesh index 63b5b8f13d..1b79e51dc7 100644 --- a/teshsuite/mc/replay/random_bug.tesh +++ b/teshsuite/mc/replay/random_bug.tesh @@ -1,11 +1,7 @@ #!/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) ************************** diff --git a/teshsuite/mc/replay/random_bug_replay.tesh b/teshsuite/mc/replay/random_bug_replay.tesh index 4f60925ac8..977f595c7a 100644 --- a/teshsuite/mc/replay/random_bug_replay.tesh +++ b/teshsuite/mc/replay/random_bug_replay.tesh @@ -1,5 +1,4 @@ #!/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 diff --git a/teshsuite/smpi/isp/umpire/any_src-can-deadlock10.tesh b/teshsuite/smpi/isp/umpire/any_src-can-deadlock10.tesh index f004859ead..f10e305761 100644 --- a/teshsuite/smpi/isp/umpire/any_src-can-deadlock10.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-can-deadlock10.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 26 > [0.000000] [mc_global/INFO] Executed transitions = 25 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-can-deadlock4.tesh b/teshsuite/smpi/isp/umpire/any_src-can-deadlock4.tesh index cf03096b8d..c8857c90be 100644 --- a/teshsuite/smpi/isp/umpire/any_src-can-deadlock4.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-can-deadlock4.tesh @@ -1,17 +1,9 @@ #! ./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 diff --git a/teshsuite/smpi/isp/umpire/any_src-can-deadlock5.tesh b/teshsuite/smpi/isp/umpire/any_src-can-deadlock5.tesh index bae9bc7f2c..0adf72c474 100644 --- a/teshsuite/smpi/isp/umpire/any_src-can-deadlock5.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-can-deadlock5.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 26 > [0.000000] [mc_global/INFO] Executed transitions = 25 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-can-deadlock6.tesh b/teshsuite/smpi/isp/umpire/any_src-can-deadlock6.tesh index 3f32b3cb37..0122655faf 100644 --- a/teshsuite/smpi/isp/umpire/any_src-can-deadlock6.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-can-deadlock6.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 26 > [0.000000] [mc_global/INFO] Executed transitions = 25 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-wait-deadlock.tesh b/teshsuite/smpi/isp/umpire/any_src-wait-deadlock.tesh index 1567e6b667..fdd9a5f308 100644 --- a/teshsuite/smpi/isp/umpire/any_src-wait-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-wait-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 23 > [0.000000] [mc_global/INFO] Executed transitions = 22 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock2.tesh b/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock2.tesh index 9ae4cbe813..9678f5f789 100644 --- a/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock2.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock2.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 26 > [0.000000] [mc_global/INFO] Executed transitions = 25 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock3.tesh b/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock3.tesh index 173b558fd2..c18b734773 100644 --- a/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock3.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-waitall-deadlock3.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -52,4 +44,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 29 > [0.000000] [mc_global/INFO] Executed transitions = 28 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock.tesh b/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock.tesh index 5a912d83c8..11814348d1 100644 --- a/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -47,4 +39,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 24 > [0.000000] [mc_global/INFO] Executed transitions = 23 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock2.tesh b/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock2.tesh index fa30aa02b0..821c2c355e 100644 --- a/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock2.tesh +++ b/teshsuite/smpi/isp/umpire/any_src-waitany-deadlock2.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -52,4 +44,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 29 > [0.000000] [mc_global/INFO] Executed transitions = 28 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_create.tesh b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_create.tesh index 6e0bd50505..f0f433e1a8 100644 --- a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_create.tesh +++ b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_create.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -47,4 +39,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Executed transitions = 22 > (1) Got MPI_COMM_NULL > Aborted - diff --git a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_dup.tesh b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_dup.tesh index 585b2cfda7..d7810c8f12 100644 --- a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_dup.tesh +++ b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_dup.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 23 > [0.000000] [mc_global/INFO] Executed transitions = 22 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_split.tesh b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_split.tesh index 13b94e3b2c..b540f3ac43 100644 --- a/teshsuite/smpi/isp/umpire/basic-deadlock-comm_split.tesh +++ b/teshsuite/smpi/isp/umpire/basic-deadlock-comm_split.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -59,4 +51,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Executed transitions = 34 > (1) Derived communicator too small (size = 1) > Aborted - diff --git a/teshsuite/smpi/isp/umpire/basic-deadlock.tesh b/teshsuite/smpi/isp/umpire/basic-deadlock.tesh index 9f1e0ce4ae..e35272ad6e 100644 --- a/teshsuite/smpi/isp/umpire/basic-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/basic-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 23 > [0.000000] [mc_global/INFO] Executed transitions = 22 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/bcast-deadlock.tesh b/teshsuite/smpi/isp/umpire/bcast-deadlock.tesh index b3908f903b..dbd8f7fa49 100644 --- a/teshsuite/smpi/isp/umpire/bcast-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/bcast-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 4 > [0.000000] [mc_global/INFO] Executed transitions = 3 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/collective-misorder-allreduce.tesh b/teshsuite/smpi/isp/umpire/collective-misorder-allreduce.tesh index 779979a899..ab2f74b6ef 100644 --- a/teshsuite/smpi/isp/umpire/collective-misorder-allreduce.tesh +++ b/teshsuite/smpi/isp/umpire/collective-misorder-allreduce.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 23 > [0.000000] [mc_global/INFO] Executed transitions = 22 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/collective-misorder.tesh b/teshsuite/smpi/isp/umpire/collective-misorder.tesh index 9401a31e93..7bd71e9a53 100644 --- a/teshsuite/smpi/isp/umpire/collective-misorder.tesh +++ b/teshsuite/smpi/isp/umpire/collective-misorder.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -68,4 +60,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 45 > [0.000000] [mc_global/INFO] Executed transitions = 44 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/complex-deadlock.tesh b/teshsuite/smpi/isp/umpire/complex-deadlock.tesh index a094d85fb8..1ccfc3c323 100644 --- a/teshsuite/smpi/isp/umpire/complex-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/complex-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 26 > [0.000000] [mc_global/INFO] Executed transitions = 25 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/deadlock-config.tesh b/teshsuite/smpi/isp/umpire/deadlock-config.tesh index 5c9869eaba..2d2f1d0535 100644 --- a/teshsuite/smpi/isp/umpire/deadlock-config.tesh +++ b/teshsuite/smpi/isp/umpire/deadlock-config.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -31,4 +23,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 4 > [0.000000] [mc_global/INFO] Executed transitions = 3 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/finalize-deadlock.tesh b/teshsuite/smpi/isp/umpire/finalize-deadlock.tesh index d4476a3960..87c6758afe 100644 --- a/teshsuite/smpi/isp/umpire/finalize-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/finalize-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -45,4 +37,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > (1) Finished normally > (2) Finished normally > Aborted - diff --git a/teshsuite/smpi/isp/umpire/irecv-deadlock.tesh b/teshsuite/smpi/isp/umpire/irecv-deadlock.tesh index 3bc6c8663b..a3670b391b 100644 --- a/teshsuite/smpi/isp/umpire/irecv-deadlock.tesh +++ b/teshsuite/smpi/isp/umpire/irecv-deadlock.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -45,4 +37,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > [0.000000] [mc_global/INFO] Visited states = 22 > [0.000000] [mc_global/INFO] Executed transitions = 21 > Aborted - diff --git a/teshsuite/smpi/isp/umpire/no-error.tesh b/teshsuite/smpi/isp/umpire/no-error.tesh index 9cb94eb226..987bd1d0f0 100644 --- a/teshsuite/smpi/isp/umpire/no-error.tesh +++ b/teshsuite/smpi/isp/umpire/no-error.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -22,4 +14,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > (0) Finished normally > (1) Finished normally > Aborted - diff --git a/teshsuite/smpi/isp/umpire/no-error2.tesh b/teshsuite/smpi/isp/umpire/no-error2.tesh index 9bb6debe8e..9ca59c83ff 100644 --- a/teshsuite/smpi/isp/umpire/no-error2.tesh +++ b/teshsuite/smpi/isp/umpire/no-error2.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > (2) Finished normally > (0) Finished normally > Aborted - diff --git a/teshsuite/smpi/isp/umpire/no-error3-any_src.tesh b/teshsuite/smpi/isp/umpire/no-error3-any_src.tesh index 5cecb6574b..4fc50a3dcd 100644 --- a/teshsuite/smpi/isp/umpire/no-error3-any_src.tesh +++ b/teshsuite/smpi/isp/umpire/no-error3-any_src.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > (2) Finished normally > (0) Finished normally > Aborted - diff --git a/teshsuite/smpi/isp/umpire/no-error3.tesh b/teshsuite/smpi/isp/umpire/no-error3.tesh index 1512434813..a8a67880f5 100644 --- a/teshsuite/smpi/isp/umpire/no-error3.tesh +++ b/teshsuite/smpi/isp/umpire/no-error3.tesh @@ -1,17 +1,9 @@ #! ./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 @@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../ > (2) Finished normally > (0) Finished normally > Aborted -