examples/smpi/mc/smpi_send_deterministic
simgrid.jar_finalized
simgrid_full.jar
-src/mc_page_store_unit.cpp
+src/PageStore_unit.cpp
src/bindings/java/MANIFEST.MF
NATIVE/
VERSION
SET(CMAKE_RC_COMPILER "windres")
endif()
project(SimGrid C)
-if (enable_gtnets OR enable_ns3 OR enable_model-checking)
- enable_language(CXX)
-endif()
enable_language(CXX)
- Rename Process.currentProcess() to Process.getCurrentProcess()
- Rename Task.setDataSize() to Task.setBytesAmount()
- Merge Task.getRemainingDuration() and Task.getComputeDuration() into Task.getFlopsAmount()
+ * Bug fixes:
+ - #18874: Actually allows the GC to reclaim tasks
SIMIX:
* New functions
For example, a communication is a sort of synchronization involving
the communicating processes (that may block until the exchange) and
the platform. The same can be said from computations, etc.
+ * Bug fixes:
+ - #18888: segfault when a process ends before its kill_time
SMPI:
* New functions
ADD_TESH_FACTORIES(msg-sendrecv-Vegas "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Vegas.tesh)
ADD_TESH_FACTORIES(msg-sendrecv-Reno "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Reno.tesh)
ADD_TESH_FACTORIES(msg-suspend "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/suspend/suspend.tesh)
+ # This one is not usable:
+ # ADD_TESH_FACTORIES(msg-exception "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/exception/exception.tesh)
ADD_TESH_FACTORIES(msg-pmm "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/pmm/pmm.tesh)
ADD_TESH_FACTORIES(msg-masterslave-bypass "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_bypass.tesh)
ADD_TESH_FACTORIES(msg-masterslave-kill "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_kill.tesh)
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(
src/include/mc/datatypes.h
src/include/mc/mc.h
src/mc/mc_mmu.h
- src/mc/mc_page_store.h
+ src/mc/PageStore.hpp
src/mc/mc_record.h
src/include/simgrid/platf_interface.h
src/include/simgrid/sg_config.h
tools/tesh/tesh.h
tools/tesh/generate_tesh
examples/smpi/mc/only_send_deterministic.tesh
+ examples/smpi/mc/non_deterministic.tesh
)
set(SMPI_SRC
)
set(MC_SRC_BASE
- src/mc/mc_base.c
+ src/mc/mc_base.cpp
src/mc/mc_base.h
src/mc/mc_record.h
- src/mc/mc_record.c
- src/mc/mc_config.c
- src/mc/mc_global.c
+ src/mc/mc_replay.h
+ src/mc/mc_record.cpp
+ src/mc/mc_config.cpp
+ src/mc/mc_global.cpp
)
set(MC_SRC
+ src/mc/mc_address_space.h
+ src/mc/mc_address_space.cpp
src/mc/mc_forward.h
+ src/mc/mc_process.h
+ src/mc/mc_process.cpp
+ src/mc/mc_unw.h
+ src/mc/mc_unw.cpp
+ src/mc/mc_unw_vmread.cpp
src/mc/mc_mmalloc.h
- src/mc/mc_model_checker.h
+ src/mc/ModelChecker.hpp
+ src/mc/ModelChecker.cpp
src/mc/mc_object_info.h
- src/mc/mc_checkpoint.c
+ src/mc/mc_object_info.cpp
+ src/mc/mc_checkpoint.cpp
src/mc/mc_snapshot.h
- src/mc/mc_snapshot.c
- src/mc/mc_page_store.h
- src/mc/mc_page_store.cpp
+ src/mc/mc_snapshot.cpp
+ src/mc/PageStore.hpp
+ src/mc/PageStore.cpp
src/mc/mc_page_snapshot.cpp
src/mc/mc_comm_pattern.h
- src/mc/mc_comm_determinism.c
+ src/mc/mc_comm_pattern.cpp
+ src/mc/mc_comm_determinism.cpp
src/mc/mc_compare.cpp
- src/mc/mc_diff.c
- src/mc/mc_dwarf.c
+ src/mc/mc_diff.cpp
+ src/mc/mc_dwarf.cpp
src/mc/mc_dwarf_attrnames.h
- src/mc/mc_dwarf_expression.c
+ src/mc/mc_dwarf_expression.cpp
src/mc/mc_dwarf_tagnames.h
- src/mc/mc_hash.c
- src/mc/mc_ignore.c
- src/mc/mc_interface.h
+ src/mc/mc_hash.cpp
+ src/mc/mc_ignore.cpp
+ src/mc/mcer_ignore.cpp
+ src/mc/mcer_ignore.h
+ src/mc/mc_ignore.h
src/mc/mc_liveness.h
src/mc/mc_location.h
- src/mc/mc_liveness.c
- src/mc/mc_record.c
- src/mc/mc_member.c
- src/mc/mc_memory.c
- src/mc/mc_pair.c
+ src/mc/mc_liveness.cpp
+ src/mc/mc_record.cpp
+ src/mc/mc_member.cpp
+ src/mc/mc_memory.cpp
+ src/mc/mc_pair.cpp
src/mc/mc_private.h
src/mc/mc_request.h
- src/mc/mc_request.c
+ src/mc/mc_request.cpp
src/mc/mc_safety.h
- src/mc/mc_safety.c
- src/mc/mc_set.cpp
+ src/mc/mc_safety.cpp
src/mc/mc_state.h
- src/mc/mc_state.c
- src/mc/mc_visited.c
+ src/mc/mc_state.cpp
+ src/mc/mc_visited.cpp
src/mc/mc_memory_map.h
- src/mc/memory_map.c
+ src/mc/memory_map.cpp
+ src/mc/mc_client.cpp
+ src/mc/mc_client_api.cpp
+ src/mc/mc_client.h
+ src/mc/mc_protocol.h
+ src/mc/mc_protocol.cpp
+ src/mc/mc_server.cpp
+ src/mc/mc_server.h
+ src/mc/mc_smx.h
+ src/mc/mc_smx.cpp
)
+set(MC_SIMGRID_MC_SRC
+ src/mc/simgrid_mc.cpp)
+
set(headers_to_install
+ include/msg/msg.h
+ include/msg/datatypes.h
+ include/simdag/simdag.h
+ include/simdag/datatypes.h
+
include/simgrid/instr.h
include/simgrid/msg.h
include/simgrid/simdag.h
${LUA_SRC}
${MC_SRC_BASE}
${MC_SRC}
+ ${MC_SIMGRID_MC_SRC}
${MSG_SRC}
${NS3_SRC}
${RNGSTREAM_SRC}
set(warnCFLAGS "")
set(optCFLAGS "")
+include(CheckCXXCompilerFlag)
+
+if(NOT __VISUALC__ AND NOT __BORLANDC__)
+ CHECK_CXX_COMPILER_FLAG("-std=c++11" HAVE_CXX11)
+ CHECK_CXX_COMPILER_FLAG("-std=c++0x" HAVE_CXX0X)
+ if(HAVE_CXX11)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ elseif(HAVE_CXX0X)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ else()
+ message(STATUS "Missing support for C++11.")
+ endif()
+endif()
+
if(NOT __VISUALC__ AND NOT __BORLANDC__)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}-std=gnu99 -g3")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}-g3")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -g3")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}/Zi")
if(enable_compile_warnings)
set(warnCFLAGS "-fno-common -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wno-unused-function -Wno-unused-parameter -Wno-strict-aliasing -Wno-format-nonliteral -Werror ")
- if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ if(CMAKE_COMPILER_IS_GNUCC)
set(warnCFLAGS "${warnCFLAGS}-Wclobbered -Wno-error=clobbered ")
if(COMPILER_C_VERSION_MAJOR_MINOR STRGREATER "4.5")
set(warnCFLAGS "${warnCFLAGS}-Wno-error=unused-but-set-variable ")
endif()
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wunused -Wpointer-arith -Wchar-subscripts -Wcomment -Wno-unknown-warning-option -Wformat -Wwrite-strings -Wno-unused-function -Wno-unused-parameter -Wno-strict-aliasing -Wclobbered -Wno-error=clobbered -Wno-format-nonliteral -Werror")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wunused -Wpointer-arith -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wno-unused-function -Wno-unused-parameter -Wno-strict-aliasing -Wno-format-nonliteral -Werror")
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wclobbered -Wno-error=clobbered")
+ endif()
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Wall") # FIXME: Q&D hack
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")
set(FLEXML_MIN_MAJOR 1)
set(FLEXML_MIN_MINOR 9)
set(FLEXML_MIN_PATCH 6)
+# Change the following when we need a recent enough version of flex to get the maintainer mode working.
+# Maintainer mode does NOT work with version 2.5.35!
+set(FLEX_MIN_MAJOR 2)
+set(FLEX_MIN_MINOR 5)
+set(FLEX_MIN_PATCH 39)
# the rest should only be changed if you understand what you're doing
if(enable_maintainer_mode AND NOT WIN32)
${CMAKE_HOME_DIRECTORY}/src/simix/popping_bodies.c
${CMAKE_HOME_DIRECTORY}/src/simix/popping_enum.h
${CMAKE_HOME_DIRECTORY}/src/simix/popping_accessors.h
-
+
DEPENDS
${CMAKE_HOME_DIRECTORY}/src/simix/simcalls.py
${CMAKE_HOME_DIRECTORY}/src/simix/simcalls.in
if (FLEXML_VERSION MATCHES "version Id:")
message(FATAL_ERROR "You have an ancient flexml version (${FLEXML_VERSION}). You need at least v${FLEXML_MIN_MAJOR}.${FLEXML_MIN_MINOR}.${FLEXML_MIN_PATCH} to compile in maintainer mode. Upgrade your flexml, or disable the Maintainer mode option in cmake.")
endif()
-
+
string(REGEX MATCH "[0-9]+[.]+[0-9]+[.]+[0-9]+" FLEXML_VERSION "${FLEXML_VERSION}")
string(REGEX MATCH "^[0-9]*" FLEXML_MAJOR_VERSION "${FLEXML_VERSION}")
string(REGEX MATCH "[0-9]+[.]+[0-9]+$" FLEXML_VERSION "${FLEXML_VERSION}")
if(HAVE_FLEXML AND HAVE_FLEX AND SED_EXE)
- message(STATUS "Flex version: ${FLEX_MAJOR_VERSION}.${FLEX_MINOR_VERSION}.${FLEX_PATCH_VERSION}")
+ message(STATUS "Flex version: ${FLEX_MAJOR_VERSION}.${FLEX_MINOR_VERSION}.${FLEX_PATCH_VERSION} (need at least version ${FLEX_MIN_MAJOR}.${FLEX_MIN_MINOR}.${FLEX_MIN_PATCH})")
message(STATUS "Flexml version: ${FLEXML_MAJOR_VERSION}.${FLEXML_MINOR_VERSION}.${FLEXML_PATCH_VERSION} (need at least version ${FLEXML_MIN_MAJOR}.${FLEXML_MIN_MINOR}.${FLEXML_MIN_PATCH})")
- IF( (${FLEXML_MAJOR_VERSION} LESS ${FLEXML_MIN_MAJOR})
+ IF( (${FLEXML_MAJOR_VERSION} LESS ${FLEXML_MIN_MAJOR})
OR ((${FLEXML_MAJOR_VERSION} EQUAL ${FLEXML_MIN_MAJOR}) AND (${FLEXML_MINOR_VERSION} LESS ${FLEXML_MIN_MINOR}) )
- OR ( (${FLEXML_MAJOR_VERSION} EQUAL ${FLEXML_MIN_MAJOR})
- AND (${FLEXML_MINOR_VERSION} EQUAL ${FLEXML_MIN_MINOR})
+ OR ( (${FLEXML_MAJOR_VERSION} EQUAL ${FLEXML_MIN_MAJOR})
+ AND (${FLEXML_MINOR_VERSION} EQUAL ${FLEXML_MIN_MINOR})
AND (${FLEXML_PATCH_VERSION} LESS ${FLEXML_MIN_PATCH}) ))
message(FATAL_ERROR "Your flexml version is too old to compile in maintainer mode (need at least v${FLEXML_MIN_MAJOR}.${FLEXML_MIN_MINOR}.${FLEXML_MIN_PATCH}). Upgrade your flexml, or disable the Maintainer mode option in cmake.")
-
+
+ ENDIF()
+
+ IF( (${FLEX_MAJOR_VERSION} LESS ${FLEX_MIN_MAJOR})
+ OR ((${FLEX_MAJOR_VERSION} EQUAL ${FLEX_MIN_MAJOR}) AND (${FLEX_MINOR_VERSION} LESS ${FLEX_MIN_MINOR}) )
+ OR ( (${FLEX_MAJOR_VERSION} EQUAL ${FLEX_MIN_MAJOR})
+ AND (${FLEX_MINOR_VERSION} EQUAL ${FLEX_MIN_MINOR})
+ AND (${FLEX_PATCH_VERSION} LESS ${FLEX_MIN_PATCH}) ))
+
+ message(FATAL_ERROR "Your flex version is too old to compile in maintainer mode (need at least v${FLEX_MIN_MAJOR}.${FLEX_MIN_MINOR}.${FLEX_MIN_PATCH}). Upgrade your flex, or disable the Maintainer mode option in cmake (run 'ccmake').")
+
ENDIF()
set(string1 "'s/extern *\\([^(]*\\)\\( \\|\\( \\*\\)\\)/XBT_PUBLIC_DATA(\\1\\3) /'")
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")
AND NOT ${CMAKE_SYSTEM_VERSION} VERSION_LESS 10.0
AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# FreeBSD from 10.0 provide a internal C++ stack (unused by gcc)
+ # see https://wiki.freebsd.org/NewC%2B%2BStack
set(SIMGRID_DEP "${SIMGRID_DEP} -lc++")
+elseif(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
+ AND ${CMAKE_SYSTEM_VERSION} VERSION_LESS 10.0
+ AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+ # FreeBSD prior to 10.0 does not necessarily have a compiler
+ # installed that is capable of c++11! Hence, we just assume
+ # here that libc++ was compiled.
+ # FIXME: We should change this behavior; we may want to include
+ # an option of whether libc++ (clang++) or libstdc++ (g++)
+ # should be used.
+ include_directories( "/usr/local/include/c++/v1")
+ set(SIMGRID_DEP "${SIMGRID_DEP} -lc++ -L/usr/local/lib ")
else()
set(SIMGRID_DEP "${SIMGRID_DEP} -lstdc++")
endif()
endif()
if(HAVE_LIBSIGC++)
- SET(SIMGRID_DEP "${SIMGRID_DEP} -lsigc-2.0")
+ SET(SIMGRID_DEP "${SIMGRID_DEP} -lsigc-2.0")
endif()
if(HAVE_GTNETS)
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")
# This is deeply wrong, and should be fixed by manually loading -lunwind-PLAT (FIXME)
if(PROCESSOR_x86_64)
SET(SIMGRID_DEP "${SIMGRID_DEP} -lunwind-x86_64")
- else()
+ else()
SET(SIMGRID_DEP "${SIMGRID_DEP} -lunwind-x86")
endif()
endif()
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("")
if(HAVE_MC)
set(TEST_CFILES ${TEST_CFILES}
- src/mc/mc_page_store.cpp
- src/mc/mc_snapshot.c
+ src/mc/PageStore.cpp
+ src/mc/mc_snapshot.cpp
)
set(TEST_UNITS ${TEST_UNITS}
- ${CMAKE_CURRENT_BINARY_DIR}/src/mc_page_store_unit.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/src/mc_snapshot_unit.c
+ ${CMAKE_CURRENT_BINARY_DIR}/src/PageStore_unit.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/src/mc_snapshot_unit.cpp
)
endif()
/* 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@
@top_srcdir@/src/instr/ \
@bindir@/include \
@top_srcdir@/include/ \
- @top_srcdir@/include/msg \
@top_srcdir@/include/xbt \
@top_srcdir@/include/simgrid \
@top_srcdir@/src/include/surf \
<a href="http://simgrid.gforge.inria.fr/Publications.html">here</a>)
should be enough to get us adding your paper to our list. But if you
remark that your paper is missing on
-<a href="http://simgrid.gforge.inria.fr/Publications-tool.html">our
+<a href="http://simgrid.gforge.inria.fr/Usages.html">our
page listing all papers using SimGrid</a>, please say so. Likewise, if
your paper is badly cited, please drop us an email so that we can fix
it.
This page does not exist yet. In the meanwhile, please refer to the
<a href="http://simgrid.gforge.inria.fr/tutorials.html">tutorials</a>
on the project web page, looking for the
-<a href="http://simgrid.gforge.inria.fr/tutorials/101/simgrid-use-101.pdf">SimGrid
+<a href="http://simgrid.gforge.inria.fr/tutorials/simgrid-use-101.pdf">SimGrid
User 101</a> tutorial.
*/
\ No newline at end of file
for (int i = 0; i < vms.size(); i++) {
vms.get(i).shutdown();
- vms.get(i).destroy();
}
Msg.info("Master done.");
}
> [1000.000000] (1:Master@Jacquelin) Migrate everyone to Fernand
> [1000.000000] (1:Master@Jacquelin) Migrate VM00fromIntelto Fernand
> [1000.000000] (5:__pr_mig_tx:VM00(Intel-Fernand)@Intel) Stage 1: Gonna send 1073741824
-> [3463.797594] (5:__pr_mig_tx:VM00(Intel-Fernand)@Intel) Stage 3: Gonna send 0.000000
-> [3465.751712] (0:@) migrate VM(VM00): set bound (137333000.000000) at Fernand
-> [3465.751712] (5:__pr_mig_tx:VM00(Intel-Fernand)@Intel) mig: tx_done
> [3467.577368] (1:Master@Jacquelin) Migrate VM01fromProvostto Fernand
> [3467.577368] (7:__pr_mig_tx:VM01(Provost-Fernand)@Provost) Stage 1: Gonna send 1073741824
-> [5929.514531] (7:__pr_mig_tx:VM01(Provost-Fernand)@Provost) Stage 3: Gonna send 0.000000
-> [5929.608220] (0:@) migrate VM(VM01): set bound (137333000.000000) at Fernand
-> [5929.608220] (7:__pr_mig_tx:VM01(Provost-Fernand)@Provost) mig: tx_done
> [5931.433875] (0:@) MSG_main finished; Cleaning up the simulation...
> [5931.433875] (1:Master@Jacquelin) Let's shut down the simulation and kill everyone.
> [5931.433875] (1:Master@Jacquelin) Master done.
Msg.info(" - End of Migration from host 1 to host 0 (duration:"+(endTime-startTime)+")");
Main.setEndOfTest();
- Msg.info("Destroy VMs");
+ Msg.info("Forcefully destroy VMs");
for (VM vm: vms)
- vm.destroy();
+ vm.finalize();
+
}
}
Process.sleep(50000);
Msg.info("Destroy VMs");
vm0.shutdown();
- vm0.destroy();
Process.sleep(20000);
}
public static void test_vm_shutdown_destroy () throws HostFailureException {
- Msg.info("**** **** **** ***** ***** Test shutdown /destroy a VM ***** ***** **** **** ****");
+ Msg.info("**** **** **** ***** ***** Test shutdown a VM ***** ***** **** **** ****");
Msg.info("Turn on host1, assign a VM on host1, launch a process inside the VM, and turn off the vm, " +
- "destroy it and check whether you can reallocate the same VM");
+ "and check whether you can reallocate the same VM");
// Create VM0
Msg.info("Shutdown VM0");
vm0.shutdown();
Process.sleep(5000);
- Msg.info("Destroy VM0");
- vm0.destroy();
- Process.sleep(5000);
Msg.info("Restart VM0");
vm0 = new XVM(
host1,
Process.sleep(5000);
vm0.shutdown();
- Process.sleep(5000);
- vm0.destroy();
}
}
> [host0:cloud/migration/Test:(1) 0.000000] [jmsg/INFO] Start migration of VM vm0 to host1
> [host0:cloud/migration/Test:(1) 0.000000] [jmsg/INFO] currentLoad:90/ramSize:2048/dpIntensity:70/remaining:8.10E+11
> [host0:__pr_mig_tx:vm0(host0-host1):(16) 0.000000] [msg_vm/INFO] Stage 1: Gonna send 2147483648
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 18.598067] [msg_vm/INFO] Stage 2, gonna send 1009084906
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 27.337835] [msg_vm/INFO] Stage 2, gonna send 474198119
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 31.445594] [msg_vm/INFO] Stage 2, gonna send 222876798
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 33.376962] [msg_vm/INFO] Stage 2, gonna send 104791237
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 34.285733] [msg_vm/INFO] Stage 2, gonna send 49307685
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 34.714029] [msg_vm/INFO] Stage 2, gonna send 23238243
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 34.916568] [msg_vm/INFO] Stage 2, gonna send 10989284
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 35.013034] [msg_vm/INFO] Stage 2, gonna send 5234001
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 35.059660] [msg_vm/INFO] Stage 3: Gonna send 2529831.000000
-> [host0:__pr_mig_tx:vm0(host0-host1):(16) 35.082869] [msg_vm/INFO] mig: tx_done
-> [35.082869] [surf_vm_workstation/INFO] migrate VM(vm0): set bound (7285500000.000000) at host1
> [host0:cloud/migration/Test:(1) 35.084170] [jmsg/INFO] End of migration of VM vm0 to node host1
> [host0:cloud/migration/Test:(1) 35.084170] [jmsg/INFO] - End of Migration from host 0 to host 1 (duration:35.0841702956701)
> [host0:cloud/migration/Test:(1) 35.084170] [jmsg/INFO] - Launch migration from host 1 to host 0
> [host0:cloud/migration/Test:(1) 35.084170] [jmsg/INFO] Start migration of VM vm0 to host0
> [host0:cloud/migration/Test:(1) 35.084170] [jmsg/INFO] currentLoad:90/ramSize:2048/dpIntensity:70/remaining:6.22E+11
> [host1:__pr_mig_tx:vm0(host1-host0):(18) 35.084170] [msg_vm/INFO] Stage 1: Gonna send 2147483648
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 53.682237] [msg_vm/INFO] Stage 2, gonna send 917349915
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 61.627599] [msg_vm/INFO] Stage 2, gonna send 391905106
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 65.022717] [msg_vm/INFO] Stage 2, gonna send 167464266
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 66.474224] [msg_vm/INFO] Stage 2, gonna send 71595605
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 67.095529] [msg_vm/INFO] Stage 2, gonna send 30645837
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 67.362216] [msg_vm/INFO] Stage 2, gonna send 13154371
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 67.477431] [msg_vm/INFO] Stage 2, gonna send 5682988
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 67.527946] [msg_vm/INFO] Stage 3: Gonna send 2491628.000000
-> [host1:__pr_mig_tx:vm0(host1-host0):(18) 67.550824] [msg_vm/INFO] mig: tx_done
-> [67.550824] [surf_vm_workstation/INFO] migrate VM(vm0): set bound (7285500000.000000) at host0
> [host0:cloud/migration/Test:(1) 67.551019] [jmsg/INFO] End of migration of VM vm0 to node host0
> [host0:cloud/migration/Test:(1) 67.551019] [jmsg/INFO] - End of Migration from host 1 to host 0 (duration:32.46684874546391)
> [host0:cloud/migration/Test:(1) 67.551019] [jmsg/INFO]
> [host0:cloud/migration/Test:(1) 67.551019] [jmsg/INFO] Start migration of VM vm0 to host1
> [host0:cloud/migration/Test:(1) 67.551019] [jmsg/INFO] currentLoad:80/ramSize:2048/dpIntensity:70/remaining:4.64E+11
> [host0:__pr_mig_tx:vm0(host0-host1):(20) 67.551019] [msg_vm/INFO] Stage 1: Gonna send 2147483648
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 86.149086] [msg_vm/INFO] Stage 2, gonna send 1009084906
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 94.888854] [msg_vm/INFO] Stage 2, gonna send 474198119
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 98.996613] [msg_vm/INFO] Stage 2, gonna send 222876798
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 100.927981] [msg_vm/INFO] Stage 2, gonna send 104791237
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 101.836752] [msg_vm/INFO] Stage 2, gonna send 49307685
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 102.265048] [msg_vm/INFO] Stage 2, gonna send 23238243
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 102.467587] [msg_vm/INFO] Stage 2, gonna send 10989284
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 102.564053] [msg_vm/INFO] Stage 2, gonna send 5234001
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 102.610680] [msg_vm/INFO] Stage 3: Gonna send 2529831.000000
-> [host0:__pr_mig_tx:vm0(host0-host1):(20) 102.633888] [msg_vm/INFO] mig: tx_done
-> [102.633888] [surf_vm_workstation/INFO] migrate VM(vm0): set bound (6476000000.000000) at host1
> [host0:cloud/migration/Test:(1) 102.635189] [jmsg/INFO] End of migration of VM vm0 to node host1
> [host0:cloud/migration/Test:(1) 102.635189] [jmsg/INFO] - End of Migration from host 0 to host 1 (duration:35.08417029567006)
> [host0:cloud/migration/Test:(1) 102.635189] [jmsg/INFO] - Launch migration from host 1 to host 0
> [host0:cloud/migration/Test:(1) 102.635189] [jmsg/INFO] Start migration of VM vm0 to host0
> [host0:cloud/migration/Test:(1) 102.635189] [jmsg/INFO] currentLoad:80/ramSize:2048/dpIntensity:70/remaining:2.77E+11
> [host1:__pr_mig_tx:vm0(host1-host0):(22) 102.635189] [msg_vm/INFO] Stage 1: Gonna send 2147483648
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 121.233256] [msg_vm/INFO] Stage 2, gonna send 917349915
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 129.178618] [msg_vm/INFO] Stage 2, gonna send 391905106
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 132.573736] [msg_vm/INFO] Stage 2, gonna send 167464266
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 134.025243] [msg_vm/INFO] Stage 2, gonna send 71595605
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 134.646548] [msg_vm/INFO] Stage 2, gonna send 30645837
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 134.913235] [msg_vm/INFO] Stage 2, gonna send 13154371
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 135.028450] [msg_vm/INFO] Stage 2, gonna send 5682988
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 135.078965] [msg_vm/INFO] Stage 3: Gonna send 2491628.000000
-> [host1:__pr_mig_tx:vm0(host1-host0):(22) 135.101843] [msg_vm/INFO] mig: tx_done
-> [135.101843] [surf_vm_workstation/INFO] migrate VM(vm0): set bound (6476000000.000000) at host0
> [host0:cloud/migration/Test:(1) 135.102038] [jmsg/INFO] End of migration of VM vm0 to node host0
> [host0:cloud/migration/Test:(1) 135.102038] [jmsg/INFO] - End of Migration from host 1 to host 0 (duration:32.46684874546395)
-> [host0:cloud/migration/Test:(1) 135.102038] [jmsg/INFO] Destroy VMs
+> [host0:cloud/migration/Test:(1) 135.102038] [jmsg/INFO] Forcefully destroy VMs
> [135.102038] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
#include "xbt/asserts.h"
#include "simgrid/modelchecker.h"
#include <xbt/RngStream.h>
+#include "mc/mc_replay.h"
/** @addtogroup MSG_examples
*
> [Intel:__pr_mig_tx:VM00(Intel-Intel):(7) 1097.307521] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Intel:__pr_mig_tx:VM00(Intel-Intel):(7) 1097.307521] [msg_vm/INFO] Stage 1: Gonna send 1073741824
> [VM01:WRK03:(5) 1097.380336] [msg_test/INFO] WRK03 executed task(Task03)
-> [Intel:__pr_mig_tx:VM00(Intel-Intel):(7) 1099.463824] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Intel:__pr_mig_tx:VM00(Intel-Intel):(7) 1099.464019] [msg_vm/INFO] mig: tx_done
-> [1099.464019] [surf_vm_workstation/INFO] migrate VM(VM00): set bound (137333000.000000) at Intel
> [Provost:__pr_mig_tx:VM01(Provost-Intel):(9) 1100.382717] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Provost:__pr_mig_tx:VM01(Provost-Intel):(9) 1100.382717] [msg_vm/INFO] Stage 1: Gonna send 1073741824
-> [Provost:__pr_mig_tx:VM01(Provost-Intel):(9) 3564.234309] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Provost:__pr_mig_tx:VM01(Provost-Intel):(9) 3566.242426] [msg_vm/INFO] mig: tx_done
-> [3566.242426] [surf_vm_workstation/INFO] migrate VM(VM01): set bound (137333000.000000) at Intel
> [Jacquelin:master:(1) 3567.161124] [msg_test/INFO] # Migrate all VMs to PM(Provost)
> [Intel:__pr_mig_tx:VM00(Intel-Provost):(11) 3567.161124] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Intel:__pr_mig_tx:VM00(Intel-Provost):(11) 3567.161124] [msg_vm/INFO] Stage 1: Gonna send 1073741824
-> [Intel:__pr_mig_tx:VM00(Intel-Provost):(11) 6031.012716] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Intel:__pr_mig_tx:VM00(Intel-Provost):(11) 6033.020833] [msg_vm/INFO] mig: tx_done
-> [6033.020833] [surf_vm_workstation/INFO] migrate VM(VM00): set bound (137333000.000000) at Provost
> [Intel:__pr_mig_tx:VM01(Intel-Provost):(13) 6034.900487] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Intel:__pr_mig_tx:VM01(Intel-Provost):(13) 6034.900487] [msg_vm/INFO] Stage 1: Gonna send 1073741824
-> [Intel:__pr_mig_tx:VM01(Intel-Provost):(13) 8498.752079] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Intel:__pr_mig_tx:VM01(Intel-Provost):(13) 8500.760196] [msg_vm/INFO] mig: tx_done
-> [8500.760196] [surf_vm_workstation/INFO] migrate VM(VM01): set bound (137333000.000000) at Provost
> [Jacquelin:master:(1) 8502.639850] [msg_test/INFO] # Shutdown the half of worker processes gracefuly. The remaining half will be forcibly killed.
> [VM00:WRK00:(2) 8504.519504] [msg_test/INFO] WRK00 received task(finalize) from mailbox(MBOX:WRK00)
> [VM01:WRK01:(3) 8506.399157] [msg_test/INFO] WRK01 received task(finalize) from mailbox(MBOX:WRK01)
> [Fafard:__pr_mig_tx:VM0(Fafard-Tremblay):(38) 49.010000] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Fafard:__pr_mig_tx:VM0(Fafard-Tremblay):(38) 49.010000] [msg_vm/INFO] Stage 1: Gonna send 1073741824
> [Bourassa:comm_rx:(36) 49.204993] [msg_test/INFO] VM0:comm_tx to Bourassa:comm_rx => 0.204993 sec
-> [Fafard:__pr_mig_tx:VM0(Fafard-Tremblay):(38) 191.612841] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Fafard:__pr_mig_tx:VM0(Fafard-Tremblay):(38) 191.638550] [msg_vm/INFO] mig: tx_done
-> [191.638550] [surf_vm_workstation/INFO] migrate VM(VM0): set bound (76296000.000000) at Tremblay
> [Tremblay:__pr_mig_tx:VM0(Tremblay-Fafard):(40) 191.674258] [msg_vm/WARNING] use the default max_downtime value 30ms
> [Tremblay:__pr_mig_tx:VM0(Tremblay-Fafard):(40) 191.674258] [msg_vm/INFO] Stage 1: Gonna send 1073741824
-> [Tremblay:__pr_mig_tx:VM0(Tremblay-Fafard):(40) 334.173348] [msg_vm/INFO] Stage 3: Gonna send 0.000000
-> [Tremblay:__pr_mig_tx:VM0(Tremblay-Fafard):(40) 334.199056] [msg_vm/INFO] mig: tx_done
> [334.199056] [surf_vm_workstation/CRITICAL] FIXME: may need a proper handling, 1
-> [334.199056] [surf_vm_workstation/INFO] migrate VM(VM0): set bound (76296000.000000) at Fafard
> [Fafard:master_:(1) 339.199251] [msg_test/INFO] ## Test 6 (ended)
> [339.199251] [msg_test/INFO] Bye (simulation time 339.199)
static int victim(int argc, char *argv[]) {
xbt_ex_t e;
- XBT_INFO("Let's get suspended.");
+ msg_error_t res = MSG_OK;
+
+ XBT_INFO("Let's work.");
TRY {
- MSG_process_suspend(MSG_process_self());
+ res = MSG_task_execute(MSG_task_create("Task", 1e14, 0, NULL));
+ if (res != MSG_OK) {
+ XBT_INFO("The MSG_task_execute caught the exception for me and returned %d)",res);
+ } else {
+ xbt_die("I was expecting an exception during my execution!");
+ }
} CATCH(e) {
XBT_INFO("The received exception resumed my execution. Good. Here is it: ----------------------->8----");
xbt_ex_display(&e);
xbt_ex_free(e);
}
- msg_error_t res = MSG_OK;
+
+ XBT_INFO("Let's get suspended.");
int gotit = 0;
+ TRY {
+ MSG_process_suspend(MSG_process_self());
+ } CATCH(e) {
+ XBT_INFO("The received exception resumed my suspension. Good. Here is it: ----------------------->8----");
+ xbt_ex_display(&e);
+ XBT_INFO("(end of the second exception) ----8<------------------------");
+ gotit = 1;
+ xbt_ex_free(e);
+ }
+ if(!gotit) {
+ xbt_die("I was expecting an exception during my suspension!");
+ }
+
XBT_INFO("Let's sleep for 10 seconds.");
TRY {
res = MSG_process_sleep(10);
+ if (res != MSG_OK) {
+ XBT_INFO("The MSG_process_sleep caught the exception for me and returned %d)",res);
+ } else {
+ xbt_die("I was expecting to get an exception during my nap.");
+ }
} CATCH(e) {
XBT_INFO("Got the second exception: ----------------------->8----");
xbt_ex_display(&e);
- XBT_INFO("(end of the second exception) ----8<------------------------");
+ XBT_INFO("(end of the third exception) ----8<------------------------");
xbt_ex_free(e);
}
- if (res != MSG_TASK_CANCELED)
- xbt_die("Sleep action not canceled through the exception. This is not a method. (retval: %d)",res);
- if (!gotit)
- xbt_die("I was expecting to get an exception during my nap.");
- XBT_INFO("My little nap got canceled through a raw exception. Excellent.");
+ XBT_INFO("Let's try a last time to do something on something");
+ MSG_process_sleep(10);
XBT_INFO("That's enough now. I quit.");
+
return 0;
}
XBT_INFO("Let's create a victim.");
victim_process = MSG_process_create("victim", victim, NULL, MSG_host_self());
+
+ XBT_INFO("Going to sleep for 1 second");
if (MSG_process_sleep(1) != MSG_OK)
xbt_die("What's going on??? I failed to sleep!");
XBT_INFO("Send a first exception (host failure)");
- SIMIX_process_throw(victim_process, host_error, 0, "Let's pretend that the host failed");
+ SIMIX_process_throw(victim_process, host_error, 0, "First Trick: Let's pretend that the host failed");
+
+
+ XBT_INFO("Sweet, let's prepare a second trick!");
+ XBT_INFO("Going to sleep for 2 seconds");
+
+ if (MSG_process_sleep(2) != MSG_OK)
+ xbt_die("What's going on??? I failed to sleep!");
+ XBT_INFO("Send a second exception (host failure)");
+ SIMIX_process_throw(victim_process, host_error, 0, "Second Trick: Let's pretend again that the host failed");
+
+ XBT_INFO("Sweet, let's prepare a third trick!");
+ XBT_INFO("Going to sleep for 3 seconds");
if (MSG_process_sleep(3) != MSG_OK)
xbt_die("What's going on??? I failed to sleep!");
- XBT_INFO("Send a second exception (cancellation)");
- SIMIX_process_throw(victim_process, cancel_error, 0, "Let's pretend this time that someone canceled something");
+ XBT_INFO("Send a third exception (cancellation)");
+ SIMIX_process_throw(victim_process, cancel_error, 0, "Third Trick: Let's pretend this time that someone canceled something");
XBT_INFO("OK, goodbye now.");
return 0;
p Testing the remote exception raising feature
! output sort
-$ $SG_TEST_EXENV exception/exception ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/exception/deployment_exception.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
+$ $SG_TEST_EXENV exception/exception ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/exception/deployment_exception.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" "--cfg=exception/cutpath:1"
+> [ 0.000000] (1:terrorist@Jacquelin) Let's create a victim.
+> [ 0.000000] (2:victim@Jacquelin) Let's work.
+> [ 0.000000] (1:terrorist@Jacquelin) Going to sleep for 1 second
+> [ 1.000000] (1:terrorist@Jacquelin) Send a first exception (host failure)
+> [ 1.000000] (1:terrorist@Jacquelin) Sweet, let's prepare a second trick!
+> [ 1.000000] (1:terrorist@Jacquelin) Going to sleep for 2 seconds
+> [ 1.000000] (2:victim@Jacquelin) The MSG_task_execute caught the exception for me and returned 8)
+> [ 1.000000] (2:victim@Jacquelin) Let's get suspended.
+> [ 3.000000] (1:terrorist@Jacquelin) Send a second exception (host failure)
+> [ 3.000000] (1:terrorist@Jacquelin) Sweet, let's prepare a third trick!
+> [ 3.000000] (1:terrorist@Jacquelin) Going to sleep for 3 seconds
+> [ 3.000000] (2:victim@Jacquelin) The received exception resumed my suspension. Good. Here is it: ----------------------->8----
+> ** SimGrid: UNCAUGHT EXCEPTION received on exception/exception(2): category: action canceled; value: 0
+> ** Canceled
+> ** Thrown by () on process 0
+> [ 0.000000] (0:@) Configuration change: Set 'exception/cutpath' to '1'
+> [ 3.000000] (2:victim@Jacquelin) Canceled
+>
+> ** In SIMIX_execution_finish() at smx_host.c
+> ** In SIMIX_run() at smx_global.c
+> ** In MSG_main() at msg_global.c
+> ** In main() at exception.c
+> [ 3.000000] (2:victim@Jacquelin) (end of the second exception) ----8<------------------------
+> [ 3.000000] (2:victim@Jacquelin) Let's sleep for 10 seconds.
+> [ 6.000000] (1:terrorist@Jacquelin) Send a third exception (cancellation)
+> [ 6.000000] (1:terrorist@Jacquelin) OK, goodbye now.
+> [ 6.000000] (2:victim@Jacquelin) The MSG_process_sleep caught the exception for me and returned 8)
+> [ 6.000000] (2:victim@Jacquelin) Let's try a last time to do something on something
+> [ 16.000000] (2:victim@Jacquelin) That's enough now. I quit.
+> [ 16.000000] (0:@) Simulation time 16
/* which is incorrect because the message ordering is non-deterministic */
/******************************************************************************/
-#include <msg/msg.h>
+#include <simgrid/msg.h>
#include <simgrid/modelchecker.h>
#define N 3
! expect signal SIGABRT
! timeout 20
-$ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check a safety property
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@HostB) Sent!
> [ 0.000000] (3:client@HostC) Sent!
> [ 0.000000] (1:server@HostA) OK
> [ 0.000000] (2:client@HostB) Sent!
> [ 0.000000] (3:client@HostC) Sent!
> [ 0.000000] (2:client@HostB) Sent!
-> [ 0.000000] (1:server@HostA) **************************
-> [ 0.000000] (1:server@HostA) *** PROPERTY NOT VALID ***
-> [ 0.000000] (1:server@HostA) **************************
-> [ 0.000000] (1:server@HostA) Counter-example execution trace:
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(2)HostB (client)] iSend(src=(2)HostB (client), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(2)HostB (client)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) [(4)HostD (client)] iSend(src=(4)HostD (client), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(4)HostD (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) Expanded states = 22
-> [ 0.000000] (1:server@HostA) Visited states = 56
-> [ 0.000000] (1:server@HostA) Executed transitions = 52
-
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) *** PROPERTY NOT VALID ***
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) Counter-example execution trace:
+> [ 0.000000] (0:@) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(2)HostB (client)] iSend(src=(2)HostB (client), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(1)HostA (server)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(2)HostB (client)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) [(4)HostD (client)] iSend(src=(4)HostD (client), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(1)HostA (server)] Wait(comm=(verbose only) [(4)HostD (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) Expanded states = 22
+> [ 0.000000] (0:@) Visited states = 56
+> [ 0.000000] (0:@) Executed transitions = 52
int r=0;
int cs=0;
-int predR(){
- return r;
-}
-
-int predCS(){
- return cs;
-}
-
#ifdef GARBAGE_STACK
/** Do not use a clean stack */
static void garbage_stack(void) {
int coordinator(int argc, char *argv[])
{
-
int CS_used = 0;
msg_task_t task = NULL, answer = NULL;
xbt_dynar_t requests = xbt_dynar_new(sizeof(char *), NULL);
int main(int argc, char *argv[])
{
-
MSG_init(&argc, 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];
-
+
MSG_create_environment(platform_file);
+
MSG_function_register("coordinator", coordinator);
MSG_function_register("client", raw_client);
MSG_launch_application(application_file);
+
MSG_main();
return 0;
! 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 --cfg=model-check/property:promela_bugged1_liveness
> [ 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
> [ 0.000000] (1:coordinator@Tremblay) CS release. resource now idle
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
-> [ 0.000000] (0:@) Pair 22 already reached (equal to pair 10) !
+> [ 0.000000] (0:@) Pair 23 already reached (equal to pair 11) !
> [ 0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
> [ 0.000000] (0:@) | ACCEPTANCE CYCLE |
> [ 0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
> [ 0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
> [ 0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
> [ 0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
-> [ 0.000000] (0:@) Expanded pairs = 22
-> [ 0.000000] (0:@) Visited pairs = 20
-> [ 0.000000] (0:@) Executed transitions = 20
-> [ 0.000000] (0:@) Counter-example depth : 21
-
+> [ 0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) Expanded pairs = 23
+> [ 0.000000] (0:@) Visited pairs = 21
+> [ 0.000000] (0:@) Executed transitions = 21
+> [ 0.000000] (0:@) Counter-example depth : 22
! 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 --cfg=model-check/property:promela_bugged1_liveness
> [ 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
> [ 0.000000] (1:coordinator@Tremblay) CS release. resource now idle
> [ 0.000000] (3:client@Fafard) Ask the request
> [ 0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
-> [ 0.000000] (0:@) Pair 22 already reached (equal to pair 10) !
+> [ 0.000000] (0:@) Pair 23 already reached (equal to pair 11) !
> [ 0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
> [ 0.000000] (0:@) | ACCEPTANCE CYCLE |
> [ 0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
> [ 0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
> [ 0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
> [ 0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
-> [ 0.000000] (0:@) Expanded pairs = 22
-> [ 0.000000] (0:@) Visited pairs = 20
-> [ 0.000000] (0:@) Executed transitions = 20
-> [ 0.000000] (0:@) Counter-example depth : 21
+> [ 0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) Expanded pairs = 23
+> [ 0.000000] (0:@) Visited pairs = 21
+> [ 0.000000] (0:@) Executed transitions = 21
+> [ 0.000000] (0:@) Counter-example depth : 22
! 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 --cfg=model-check/property:promela_bugged1_liveness
> [ 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
> [ 0.000000] (0:@) Visited pairs = 201
> [ 0.000000] (0:@) Executed transitions = 207
> [ 0.000000] (0:@) Counter-example depth : 51
-
! 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 --cfg=model-check/property:promela_bugged1_liveness
> [ 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
/* which is incorrect because the message ordering is non-deterministic */
/******************************************************************************/
-#include <msg/msg.h>
+#include <simgrid/msg.h>
#include <simgrid/modelchecker.h>
#define N 3
! expect signal SIGABRT
! timeout 20
-$ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
> [ 0.000000] (0:@) Check a safety property
-> [ 0.000000] (0:@) Get debug information ...
-> [ 0.000000] (0:@) Get debug information done !
> [ 0.000000] (2:client@HostB) Send 1!
> [ 0.000000] (3:client@HostC) Send 2!
> [ 0.000000] (1:server@HostA) Received 1
> [ 0.000000] (1:server@HostA) Received 2
> [ 0.000000] (3:client@HostC) Send 2!
> [ 0.000000] (1:server@HostA) Received 2
-> [ 0.000000] (1:server@HostA) **************************
-> [ 0.000000] (1:server@HostA) *** PROPERTY NOT VALID ***
-> [ 0.000000] (1:server@HostA) **************************
-> [ 0.000000] (1:server@HostA) Counter-example execution trace:
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) [(3)HostC (client)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
-> [ 0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
-> [ 0.000000] (1:server@HostA) Expanded states = 461
-> [ 0.000000] (1:server@HostA) Visited states = 2271
-> [ 0.000000] (1:server@HostA) Executed transitions = 2117
-
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) *** PROPERTY NOT VALID ***
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) Counter-example execution trace:
+> [ 0.000000] (0:@) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) [(3)HostC (client)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [ 0.000000] (0:@) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [ 0.000000] (0:@) Expanded states = 461
+> [ 0.000000] (0:@) Visited states = 2271
+> [ 0.000000] (0:@) Executed transitions = 2117
int cs = 0;
-int predCS(){
- return cs;
-}
-
-
int coordinator(int argc, char **argv);
int client(int argc, char **argv);
MSG_init(&argc, argv);
- MSG_config("model-check/property","promela_bugged2_liveness");
- MC_automaton_new_propositional_symbol("cs", &predCS);
+ MC_automaton_new_propositional_symbol_pointer("cs", &cs);
MSG_create_environment("../msg_platform.xml");
MSG_function_register("coordinator", coordinator);
/* same buffer for reception (task1). */
/******************************************************************************/
-#include <msg/msg.h>
+#include <simgrid/msg.h>
#include <simgrid/modelchecker.h>
XBT_LOG_NEW_DEFAULT_CATEGORY(bugged3, "this example");
/* --cfg=model-check/max_depth:) is reached. */
/******************************************************************************/
-#include <msg/msg.h>
+#include <simgrid/msg.h>
#include <simgrid/modelchecker.h>
#define N 2
<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
<platform version="3">
- <process host="node-0.acme.org" function="master"/>
- <process host="node-1.acme.org" function="slave"/>
- <process host="node-2.acme.org" function="slave"/>
- <process host="node-3.acme.org" function="slave"/>
- <process host="node-4.acme.org" function="slave"/>
- <process host="node-5.acme.org" function="slave"/>
+ <!-- Just sleeps for 10 seconds and quits -->
+ <process host="node-0.acme.org" function="sleeper">
+ <argument value="10"/>
+ </process>
</platform>
<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
<platform version="3">
- <process host="node-0.acme.org" function="master"/>
- <process host="node-1.acme.org" function="slave" kill_time="6"/>
- <process host="node-2.acme.org" function="slave" kill_time="6"/>
- <process host="node-3.acme.org" function="slave" kill_time="6"/>
- <process host="node-4.acme.org" function="slave" kill_time="6"/>
- <process host="node-5.acme.org" function="slave" kill_time="6"/>
+ <process host="node-1.acme.org" function="sleeper" kill_time="6"> <argument value="10"/></process>
+ <process host="node-2.acme.org" function="sleeper" kill_time="6"> <argument value="6"/></process>
+ <process host="node-3.acme.org" function="sleeper" kill_time="10"> <argument value="6"/></process>
</platform>
<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
<platform version="3">
- <process host="node-0.acme.org" function="master"/>
- <process host="node-1.acme.org" function="slave" start_time="1"/>
- <process host="node-2.acme.org" function="slave" start_time="2"/>
- <process host="node-3.acme.org" function="slave" start_time="3"/>
- <process host="node-4.acme.org" function="slave" start_time="4"/>
- <process host="node-5.acme.org" function="slave" start_time="5"/>
+ <process host="node-0.acme.org" function="sleeper" start_time="0"> <argument value="10"/></process>
+ <process host="node-1.acme.org" function="sleeper" start_time="1"> <argument value="10"/></process>
+ <process host="node-2.acme.org" function="sleeper" start_time="2"> <argument value="10"/></process>
+ <process host="node-3.acme.org" function="sleeper" start_time="3"> <argument value="10"/></process>
+ <process host="node-4.acme.org" function="sleeper" start_time="4"> <argument value="10"/></process>
+ <process host="node-5.acme.org" function="sleeper" start_time="5"> <argument value="10"/></process>
</platform>
<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
<platform version="3">
- <process host="node-0.acme.org" function="master"/>
- <process host="node-1.acme.org" function="slave" start_time="1" kill_time="5"/>
- <process host="node-2.acme.org" function="slave" start_time="2" kill_time="6"/>
- <process host="node-3.acme.org" function="slave" start_time="3" kill_time="7"/>
- <process host="node-4.acme.org" function="slave" start_time="4" kill_time="8"/>
- <process host="node-5.acme.org" function="slave" start_time="5" kill_time="9"/>
+ <process host="node-0.acme.org" function="sleeper" start_time="0" kill_time="5"> <argument value="10"/></process>
+ <process host="node-1.acme.org" function="sleeper" start_time="1" kill_time="6"> <argument value="10"/></process>
+ <process host="node-2.acme.org" function="sleeper" start_time="2" kill_time="7"> <argument value="4" /></process>
+ <process host="node-3.acme.org" function="sleeper" start_time="3" kill_time="8"> <argument value="4" /></process>
+ <process host="node-4.acme.org" function="sleeper" start_time="4" kill_time="9"> <argument value="5" /></process>
+ <process host="node-5.acme.org" function="sleeper" start_time="5" kill_time="10"> <argument value="5"/></process>
</platform>
-/* Copyright (c) 2007, 2009-2010, 2012-2014. The SimGrid Team.
+/* Copyright (c) 2007, 2009-2010, 2012-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 "simgrid/msg.h" /* Yeah! If you want to use msg, you need to include simgrid/msg.h */
+#include "simgrid/msg.h" /* Yeah! If you want to use msg, you need to include simgrid/msg.h */
#include "xbt/sysdep.h" /* calloc */
/* Create a log channel to have nice outputs. */
XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
"Messages specific for this msg example");
-/** Lazy guy function. This process suspends itself asap. */
-static int slave(int argc, char *argv[])
-{
- XBT_INFO("Hello!");
- MSG_process_sleep(10.0);
- XBT_INFO("OK, goodbye now.");
+static int my_onexit(void* ignored1, void *ignored2) {
+ XBT_INFO("Exiting now (done sleeping or got killed).");
return 0;
-} /* end_of_lazy_guy */
+}
-static int master(int argc, char *argv[])
+static int sleeper(int argc, char *argv[])
{
- XBT_INFO("Hello!");
- MSG_process_sleep(10.0);
- XBT_INFO("OK, goodbye now.");
+ XBT_INFO("Hello! I go to sleep.");
+ MSG_process_on_exit(my_onexit, NULL);
+
+ MSG_process_sleep(atoi(argv[1]));
+ XBT_INFO("Done sleeping.");
return 0;
-} /* end_of_dram_master */
+}
/** Test function */
static msg_error_t test_all(const char *platform_file,
msg_error_t res = MSG_OK;
MSG_create_environment(platform_file);
- MSG_function_register("master", master);
- MSG_function_register("slave", slave);
+ MSG_function_register("sleeper", sleeper);
MSG_launch_application(application_file);
res = MSG_main();
p Test0 Process without time
$ $SG_TEST_EXENV ${bindir:=.}/start_kill_time/sk_time ${srcdir:=.}/examples/platforms/cluster.xml ${srcdir:=.}/examples/msg/start_kill_time/deployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [ 0.000000] (1:master@node-0.acme.org) Hello!
-> [ 0.000000] (2:slave@node-1.acme.org) Hello!
-> [ 0.000000] (3:slave@node-2.acme.org) Hello!
-> [ 0.000000] (4:slave@node-3.acme.org) Hello!
-> [ 0.000000] (5:slave@node-4.acme.org) Hello!
-> [ 0.000000] (6:slave@node-5.acme.org) Hello!
-> [ 10.000000] (6:slave@node-5.acme.org) OK, goodbye now.
-> [ 10.000000] (1:master@node-0.acme.org) OK, goodbye now.
-> [ 10.000000] (2:slave@node-1.acme.org) OK, goodbye now.
-> [ 10.000000] (3:slave@node-2.acme.org) OK, goodbye now.
-> [ 10.000000] (4:slave@node-3.acme.org) OK, goodbye now.
-> [ 10.000000] (5:slave@node-4.acme.org) OK, goodbye now.
+> [ 0.000000] (1:sleeper@node-0.acme.org) Hello! I go to sleep.
+> [ 10.000000] (1:sleeper@node-0.acme.org) Done sleeping.
+> [ 10.000000] (1:sleeper@node-0.acme.org) Exiting now (done sleeping or got killed).
> [ 10.000000] (0:@) Simulation time 10
p Test1 Process with start time
$ $SG_TEST_EXENV ${bindir:=.}/start_kill_time/sk_time ${srcdir:=.}/examples/platforms/cluster.xml ${srcdir:=.}/examples/msg/start_kill_time/deployment_start.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [ 0.000000] (1:master@node-0.acme.org) Hello!
-> [ 1.000000] (2:slave@node-1.acme.org) Hello!
-> [ 2.000000] (3:slave@node-2.acme.org) Hello!
-> [ 3.000000] (4:slave@node-3.acme.org) Hello!
-> [ 4.000000] (5:slave@node-4.acme.org) Hello!
-> [ 5.000000] (6:slave@node-5.acme.org) Hello!
-> [ 10.000000] (1:master@node-0.acme.org) OK, goodbye now.
-> [ 11.000000] (2:slave@node-1.acme.org) OK, goodbye now.
-> [ 12.000000] (3:slave@node-2.acme.org) OK, goodbye now.
-> [ 13.000000] (4:slave@node-3.acme.org) OK, goodbye now.
-> [ 14.000000] (5:slave@node-4.acme.org) OK, goodbye now.
-> [ 15.000000] (6:slave@node-5.acme.org) OK, goodbye now.
+> [ 0.000000] (1:sleeper@node-0.acme.org) Hello! I go to sleep.
+> [ 1.000000] (2:sleeper@node-1.acme.org) Hello! I go to sleep.
+> [ 2.000000] (3:sleeper@node-2.acme.org) Hello! I go to sleep.
+> [ 3.000000] (4:sleeper@node-3.acme.org) Hello! I go to sleep.
+> [ 4.000000] (5:sleeper@node-4.acme.org) Hello! I go to sleep.
+> [ 5.000000] (6:sleeper@node-5.acme.org) Hello! I go to sleep.
+> [ 10.000000] (1:sleeper@node-0.acme.org) Done sleeping.
+> [ 10.000000] (1:sleeper@node-0.acme.org) Exiting now (done sleeping or got killed).
+> [ 11.000000] (2:sleeper@node-1.acme.org) Done sleeping.
+> [ 11.000000] (2:sleeper@node-1.acme.org) Exiting now (done sleeping or got killed).
+> [ 12.000000] (3:sleeper@node-2.acme.org) Done sleeping.
+> [ 12.000000] (3:sleeper@node-2.acme.org) Exiting now (done sleeping or got killed).
+> [ 13.000000] (4:sleeper@node-3.acme.org) Done sleeping.
+> [ 13.000000] (4:sleeper@node-3.acme.org) Exiting now (done sleeping or got killed).
+> [ 14.000000] (5:sleeper@node-4.acme.org) Done sleeping.
+> [ 14.000000] (5:sleeper@node-4.acme.org) Exiting now (done sleeping or got killed).
+> [ 15.000000] (6:sleeper@node-5.acme.org) Done sleeping.
+> [ 15.000000] (6:sleeper@node-5.acme.org) Exiting now (done sleeping or got killed).
> [ 15.000000] (0:@) Simulation time 15
p Test1 Process with kill time
$ $SG_TEST_EXENV ${bindir:=.}/start_kill_time/sk_time ${srcdir:=.}/examples/platforms/cluster.xml ${srcdir:=.}/examples/msg/start_kill_time/deployment_kill.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [ 0.000000] (1:master@node-0.acme.org) Hello!
-> [ 0.000000] (2:slave@node-1.acme.org) Hello!
-> [ 0.000000] (3:slave@node-2.acme.org) Hello!
-> [ 0.000000] (4:slave@node-3.acme.org) Hello!
-> [ 0.000000] (5:slave@node-4.acme.org) Hello!
-> [ 0.000000] (6:slave@node-5.acme.org) Hello!
-> [ 10.000000] (1:master@node-0.acme.org) OK, goodbye now.
-> [ 10.000000] (0:@) Simulation time 10
+> [ 0.000000] (1:sleeper@node-1.acme.org) Hello! I go to sleep.
+> [ 0.000000] (2:sleeper@node-2.acme.org) Hello! I go to sleep.
+> [ 0.000000] (3:sleeper@node-3.acme.org) Hello! I go to sleep.
+> [ 6.000000] (1:sleeper@node-1.acme.org) Exiting now (done sleeping or got killed).
+> [ 6.000000] (2:sleeper@node-2.acme.org) Exiting now (done sleeping or got killed).
+> [ 6.000000] (3:sleeper@node-3.acme.org) Done sleeping.
+> [ 6.000000] (3:sleeper@node-3.acme.org) Exiting now (done sleeping or got killed).
+> [ 6.000000] (0:@) Simulation time 6
p Test2 Process with start and kill times
$ $SG_TEST_EXENV ${bindir:=.}/start_kill_time/sk_time ${srcdir:=.}/examples/platforms/cluster.xml ${srcdir:=.}/examples/msg/start_kill_time/deployment_start_kill.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [ 0.000000] (1:master@node-0.acme.org) Hello!
-> [ 1.000000] (2:slave@node-1.acme.org) Hello!
-> [ 2.000000] (3:slave@node-2.acme.org) Hello!
-> [ 3.000000] (4:slave@node-3.acme.org) Hello!
-> [ 4.000000] (5:slave@node-4.acme.org) Hello!
-> [ 5.000000] (6:slave@node-5.acme.org) Hello!
-> [ 10.000000] (1:master@node-0.acme.org) OK, goodbye now.
+> [ 0.000000] (1:sleeper@node-0.acme.org) Hello! I go to sleep.
+> [ 1.000000] (2:sleeper@node-1.acme.org) Hello! I go to sleep.
+> [ 2.000000] (3:sleeper@node-2.acme.org) Hello! I go to sleep.
+> [ 3.000000] (4:sleeper@node-3.acme.org) Hello! I go to sleep.
+> [ 4.000000] (5:sleeper@node-4.acme.org) Hello! I go to sleep.
+> [ 5.000000] (1:sleeper@node-0.acme.org) Exiting now (done sleeping or got killed).
+> [ 5.000000] (6:sleeper@node-5.acme.org) Hello! I go to sleep.
+> [ 6.000000] (2:sleeper@node-1.acme.org) Exiting now (done sleeping or got killed).
+> [ 6.000000] (3:sleeper@node-2.acme.org) Done sleeping.
+> [ 6.000000] (3:sleeper@node-2.acme.org) Exiting now (done sleeping or got killed).
+> [ 7.000000] (4:sleeper@node-3.acme.org) Done sleeping.
+> [ 7.000000] (4:sleeper@node-3.acme.org) Exiting now (done sleeping or got killed).
+> [ 9.000000] (5:sleeper@node-4.acme.org) Exiting now (done sleeping or got killed).
+> [ 10.000000] (6:sleeper@node-5.acme.org) Exiting now (done sleeping or got killed).
> [ 10.000000] (0:@) Simulation time 10
int r, cs;
-static int predR(){
- return r;
-}
-
-static int predCS(){
- return cs;
-}
-
-
int main(int argc, char **argv){
int err, size, rank;
exit(1);
}
- MC_automaton_new_propositional_symbol("r", &predR);
- MC_automaton_new_propositional_symbol("cs", &predCS);
+ MC_automaton_new_propositional_symbol_pointer("r", &r);
+ MC_automaton_new_propositional_symbol_pointer("cs", &cs);
MC_ignore(&(status.count), sizeof(status.count));
--- /dev/null
+#! ./tesh
+
+! timeout 60
+$ ../../../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_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 *****
+> [0.000000] [mc_comm_determinism/INFO] ****************************************************
+> [0.000000] [mc_comm_determinism/INFO] ** Initial communications pattern (per process): **
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 1:
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org <- (2) node-2.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org -> (2) node-2.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org <- (3) node-3.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org -> (3) node-3.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 2:
+> [0.000000] [mc_comm_determinism/INFO] [(2) node-2.acme.org -> (1) node-1.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(2) node-2.acme.org <- (1) node-1.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 3:
+> [0.000000] [mc_comm_determinism/INFO] [(3) node-3.acme.org -> (1) node-1.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(3) node-3.acme.org <- (1) node-1.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] ** Communications pattern counter-example (per process): **
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 1:
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org <- (3) node-3.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org -> (3) node-3.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org <- (2) node-2.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] [(1) node-1.acme.org -> (2) node-2.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 2:
+> [0.000000] [mc_comm_determinism/INFO] [(2) node-2.acme.org -> (1) node-1.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(2) node-2.acme.org <- (1) node-1.acme.org] iRecv
+> [0.000000] [mc_comm_determinism/INFO] Communications from the process 3:
+> [0.000000] [mc_comm_determinism/INFO] [(3) node-3.acme.org -> (1) node-1.acme.org] iSend
+> [0.000000] [mc_comm_determinism/INFO] [(3) node-3.acme.org <- (1) node-1.acme.org] iRecv
+> [0.000000] [mc_global/INFO] Expanded states = 16037
+> [0.000000] [mc_global/INFO] Visited states = 80801
+> [0.000000] [mc_global/INFO] Executed transitions = 76048
+> [0.000000] [mc_global/INFO] Communication-deterministic : No
#! ./tesh
! timeout 60
-$ ../../../smpi_script/bin/smpirun -hostfile ${srcdir:=.}/hostfile_only_send_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_only_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/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" --log=xbt_cfg.thresh:warning -hostfile ${srcdir:=.}/hostfile_only_send_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_only_send_deterministic
+> [0.000000] [mc_comm_determinism/INFO] Check communication determinism
> [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] ******************************************************
> [0.000000] [mc_global/INFO] **** Only-send-deterministic communication pattern ****
> [0.000000] [mc_global/INFO] ******************************************************
> [0.000000] [mc_global/INFO] Executed transitions = 3360
> [0.000000] [mc_global/INFO] Send-deterministic : Yes
> [0.000000] [mc_global/INFO] Recv-deterministic : No
-
-
--- /dev/null
+#warning You should now include directly simgrid/msg.h instead of msg/datatypes.h
+#include "simgrid/msg.h"
--- /dev/null
+#warning You should now include directly simgrid/msg.h instead of msg/msg.h
+#include "simgrid/msg.h"
--- /dev/null
+#warning You should now include directly simgrid/simdag.h instead of simdag/datatypes.h
+#include "simgrid/simdag.h"
--- /dev/null
+#warning You should now include directly simgrid/simdag.h instead of simdag/simdag.h
+#include "simgrid/simdag.h"
#define MC_visited_reduction() _sg_mc_visited
XBT_PUBLIC(void) MC_assert(int);
-XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, void* fct);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, int(*fct)(void));
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_pointer(const char *id, int* value);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_callback(const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
XBT_PUBLIC(void *) MC_snapshot(void);
XBT_PUBLIC(int) MC_compare_snapshots(void *s1, void *s2);
XBT_PUBLIC(void) MC_cut(void);
#define MC_assert(a) xbt_assert(a)
#define MC_automaton_new_propositional_symbol(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_pointer(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_callback(id,callback,data,free_function) \
+ if(free_function) free_function(data);
#define MC_snapshot() ((void*)0)
#define MC_compare_snapshots(a, b) 0
#define MC_cut() ((void)0)
#endif
-/** Replay path (if any) in string representation
- *
- * This is a path as generated by `MC_record_stack_to_string()`.
- */
-XBT_PUBLIC_DATA(char*) MC_record_path;
-
-/** Whether the replay mode is enabled */
-static inline bool MC_record_replay_is_active(void) {
- return MC_record_path;
-}
-
SG_END_DECL()
#endif /* SIMGRID_MODELCHECKER_H */
} e_smx_state_t;
/** @} */
-typedef struct s_smx_timer* smx_timer_t;
-
/* ******************************** Synchro ************************************ */
/**
* \ingroup simix_synchro_management
XBT_PUBLIC(double) SIMIX_get_clock(void);
/* Timer functions FIXME: should these be public? */
-XBT_PUBLIC(void) SIMIX_timer_set(double date, void *function, void *arg);
+typedef struct s_smx_timer* smx_timer_t;
+
+XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, void *function, void *arg);
+XBT_PUBLIC(void) SIMIX_timer_remove(smx_timer_t timer);
XBT_PUBLIC(double) SIMIX_timer_next(void);
+XBT_PUBLIC(double) SIMIX_timer_get_date(smx_timer_t timer);
XBT_PUBLIC(void) SIMIX_display_process_status(void);
integer MPI_MAX_DATAREP_STRIN, MPI_MAX_INFO_KEY
integer MPI_MAX_INFO_VAL, MPI_MAX_OBJECT_NAME, MPI_MAX_PORT_NAME
integer MPI_ANY_SOURCE, MPI_PROC_NULL, MPI_ANY_TAG, MPI_UNDEFINED
- integer MPI_TAG_UB, MPI_TAG_LB
integer MPI_SOURCE, MPI_TAG, MPI_ERROR
integer MPI_VERSION, MPI_SUBVERSION
parameter(MPI_MAX_PROCESSOR_NAME=100)
parameter(MPI_SOURCE=1)
parameter(MPI_TAG=2)
parameter(MPI_ERROR=3)
- parameter(MPI_TAG_UB=0)
- parameter(MPI_TAG_LB=0)
parameter(MPI_VERSION=1)
parameter(MPI_SUBVERSION=1)
integer MPI_MODE_NOSTORE, MPI_MODE_NOPUT, MPI_MODE_NOPRECEDE
integer MPI_ERR_REQUEST, MPI_ERR_INTERN, MPI_ERR_COUNT
integer MPI_ERR_RANK, MPI_ERR_OTHER, MPI_ERR_UNKNOWN
integer MPI_ERR_TAG, MPI_ERR_TRUNCATE, MPI_ERR_GROUP, MPI_ERR_OP
- integer MPI_LASTUSEDCODE, MPI_ERR_LASTCODE
+ integer MPI_ERR_LASTCODE
integer MPI_IDENT, MPI_SIMILAR, MPI_UNEQUAL, MPI_CONGRUENT
- integer MPI_WTIME_IS_GLOBAL
parameter(MPI_SUCCESS=0)
parameter(MPI_ERR_COMM=1)
parameter(MPI_ERR_ARG=2)
parameter(MPI_ERR_OP=11)
parameter(MPI_ERR_OTHER=12)
parameter(MPI_ERR_UNKNOWN=13)
- parameter(MPI_LASTUSEDCODE=0)
- parameter(MPI_ERR_LASTCODE=0)
+ parameter(MPI_ERR_LASTCODE=74)
parameter(MPI_IDENT=0)
parameter(MPI_SIMILAR=1)
parameter(MPI_UNEQUAL=2)
parameter(MPI_CONGRUENT=3)
- parameter(MPI_WTIME_IS_GLOBAL=1)
+
integer MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN
parameter(MPI_NULL_COPY_FN =0)
integer MPI_COMM_NULL_DUP_FN, MPI_COMM_DUP_FN
parameter(MPI_COMM_NULL_DUP_FN =0)
parameter(MPI_COMM_DUP_FN =0)
- integer MPI_APPNUM, MPI_HOST, MPI_IO
- parameter(MPI_APPNUM=0)
- parameter(MPI_HOST=0)
- parameter(MPI_IO=0)
+
+
+
integer MPI_ROOT, MPI_INFO_NULL,MPI_COMM_TYPE_SHARED
parameter(MPI_ROOT=0)
parameter(MPI_INFO_NULL=0)
parameter(MPI_COMM_TYPE_SHARED=1)
+! Attribute keys
+ integer MPI_IO, MPI_HOST, MPI_WTIME_IS_GLOBAL, MPI_APPNUM
+ integer MPI_TAG_UB, MPI_TAG_LB
+ integer MPI_UNIVERSE_SIZE, MPI_LASTUSEDCODE
+ parameter(MPI_IO=-1)
+ parameter(MPI_HOST=-2)
+ parameter(MPI_WTIME_IS_GLOBAL=-3)
+ parameter(MPI_APPNUM=-4)
+ parameter(MPI_TAG_UB=-5)
+ parameter(MPI_TAG_LB=-6)
+ parameter(MPI_UNIVERSE_SIZE=-7)
+ parameter(MPI_LASTUSEDCODE=-8)
+
! These should be ordered as in smpi_f77.c
integer MPI_COMM_NULL, MPI_COMM_WORLD, MPI_COMM_SELF
- integer MPI_UNIVERSE_SIZE
parameter(MPI_COMM_NULL=-1)
parameter(MPI_COMM_SELF=-2)
parameter(MPI_COMM_WORLD=0)
- parameter(MPI_UNIVERSE_SIZE=0)
-
integer MPI_GROUP_NULL, MPI_GROUP_EMPTY
parameter(MPI_GROUP_NULL=-1)
#define MPI_IN_PLACE (void *)-222
// errorcodes
-#define MPI_SUCCESS 0
-#define MPI_ERR_COMM 1
-#define MPI_ERR_ARG 2
-#define MPI_ERR_TYPE 3
-#define MPI_ERR_REQUEST 4
-#define MPI_ERR_INTERN 5
-#define MPI_ERR_COUNT 6
-#define MPI_ERR_RANK 7
-#define MPI_ERR_TAG 8
-#define MPI_ERR_TRUNCATE 9
-#define MPI_ERR_GROUP 10
-#define MPI_ERR_OP 11
-#define MPI_ERR_OTHER 12
-#define MPI_ERR_IN_STATUS 13
-#define MPI_ERR_PENDING 14
-#define MPI_ERR_BUFFER 15
-#define MPI_ERR_NAME 16
-#define MPI_ERR_DIMS 17
-#define MPI_ERR_TOPOLOGY 18
-#define MPI_ERR_NO_MEM 19
-#define MPI_ERR_WIN 20
-#define MPI_ERR_INFO_VALUE 21
-#define MPI_ERR_INFO_KEY 22
-#define MPI_ERR_INFO_NOKEY 23
+#define MPI_SUCCESS 0
+#define MPI_ERR_COMM 1
+#define MPI_ERR_ARG 2
+#define MPI_ERR_TYPE 3
+#define MPI_ERR_REQUEST 4
+#define MPI_ERR_INTERN 5
+#define MPI_ERR_COUNT 6
+#define MPI_ERR_RANK 7
+#define MPI_ERR_TAG 8
+#define MPI_ERR_TRUNCATE 9
+#define MPI_ERR_GROUP 10
+#define MPI_ERR_OP 11
+#define MPI_ERR_OTHER 12
+#define MPI_ERR_IN_STATUS 13
+#define MPI_ERR_PENDING 14
+#define MPI_ERR_BUFFER 15
+#define MPI_ERR_NAME 16
+#define MPI_ERR_DIMS 17
+#define MPI_ERR_TOPOLOGY 18
+#define MPI_ERR_NO_MEM 19
+#define MPI_ERR_WIN 20
+#define MPI_ERR_INFO_VALUE 21
+#define MPI_ERR_INFO_KEY 22
+#define MPI_ERR_INFO_NOKEY 23
+#define MPI_ERR_ROOT 24
+#define MPI_ERR_UNKNOWN 25
+#define MPI_ERR_KEYVAL 26
+#define MPI_ERR_BASE 27
+#define MPI_ERR_SPAWN 28
+#define MPI_ERR_PORT 29
+#define MPI_ERR_SERVICE 30
+#define MPI_ERR_SIZE 31
+#define MPI_ERR_DISP 32
+#define MPI_ERR_INFO 33
+#define MPI_ERR_LOCKTYPE 34
+#define MPI_ERR_ASSERT 35
+#define MPI_RMA_CONFLICT 36
+#define MPI_RMA_SYNC 37
+#define MPI_ERR_FILE 38
+#define MPI_ERR_NOT_SAME 39
+#define MPI_ERR_AMODE 40
+#define MPI_ERR_UNSUPPORTED_DATAREP 41
+#define MPI_ERR_UNSUPPORTED_OPERATION 42
+#define MPI_ERR_NO_SUCH_FILE 43
+#define MPI_ERR_FILE_EXISTS 44
+#define MPI_ERR_BAD_FILE 45
+#define MPI_ERR_ACCESS 46
+#define MPI_ERR_NO_SPACE 47
+#define MPI_ERR_QUOTA 48
+#define MPI_ERR_READ_ONLY 49
+#define MPI_ERR_FILE_IN_USE 50
+#define MPI_ERR_DUP_DATAREP 51
+#define MPI_ERR_CONVERSION 52
+#define MPI_ERR_IO 53
+#define MPI_ERR_RMA_ATTACH 54
+#define MPI_ERR_RMA_CONFLICT 55
+#define MPI_ERR_RMA_RANGE 56
+#define MPI_ERR_RMA_SHARED 57
+#define MPI_ERR_RMA_SYNC 58
+#define MPI_ERR_RMA_FLAVOR 59
+#define MPI_T_ERR_CANNOT_INIT 60
+#define MPI_T_ERR_NOT_INITIALIZED 61
+#define MPI_T_ERR_MEMORY 62
+#define MPI_T_ERR_INVALID_INDEX 63
+#define MPI_T_ERR_INVALID_ITEM 64
+#define MPI_T_ERR_INVALID_SESSION 65
+#define MPI_T_ERR_INVALID_HANDLE 66
+#define MPI_T_ERR_OUT_OF_HANDLES 67
+#define MPI_T_ERR_OUT_OF_SESSIONS 68
+#define MPI_T_ERR_CVAR_SET_NOT_NOW 69
+#define MPI_T_ERR_CVAR_SET_NEVER 70
+#define MPI_T_ERR_PVAR_NO_WRITE 71
+#define MPI_T_ERR_PVAR_NO_STARTSTOP 72
+#define MPI_T_ERR_PVAR_NO_ATOMIC 73
+
+
#define MPI_ERRCODES_IGNORE (int *)0
#define MPI_IDENT 0
#define MPI_SIMILAR 1
#define MPI_UNEQUAL 2
#define MPI_CONGRUENT 3
-#define MPI_WTIME_IS_GLOBAL 1
-#define MPI_TAG_UB 1000000
-#define MPI_HOST 0
-#define MPI_IO 0
+
+
#define MPI_BSEND_OVERHEAD 0
+/* Attribute keys */
+#define MPI_IO -1
+#define MPI_HOST -2
+#define MPI_WTIME_IS_GLOBAL -3
+#define MPI_APPNUM -4
+#define MPI_TAG_UB -5
+#define MPI_TAG_LB -6
+#define MPI_UNIVERSE_SIZE -7
+#define MPI_LASTUSEDCODE -8
#define MPI_MODE_NOSTORE 0x1
#define MPI_MODE_NOPUT 0x2
#define MPI_MODE_NOSUCCEED 0x8
#define MPI_MODE_NOCHECK 0x10
-
#define MPI_KEYVAL_INVALID 0
#define MPI_NULL_COPY_FN NULL
#define MPI_NULL_DELETE_FN NULL
-#define MPI_APPNUM 0
-#define MPI_LASTUSEDCODE MPI_SUCCESS
-#define MPI_ERR_LASTCODE MPI_SUCCESS
+#define MPI_ERR_LASTCODE 74
#define MPI_CXX_BOOL MPI_DATATYPE_NULL
#define MPI_CXX_FLOAT_COMPLEX MPI_DATATYPE_NULL
#define MPI_COMM_NULL ((MPI_Comm)NULL)
XBT_PUBLIC_DATA( MPI_Comm ) MPI_COMM_WORLD;
-XBT_PUBLIC_DATA( int ) MPI_UNIVERSE_SIZE;
#define MPI_COMM_SELF smpi_process_comm_self()
struct s_smpi_mpi_request;
typedef struct xbt_automaton_transition* xbt_automaton_transition_t;
-typedef struct xbt_automaton_propositional_symbol{
- char* pred;
- void* function;
-} s_xbt_automaton_propositional_symbol;
-
+typedef struct xbt_automaton_propositional_symbol s_xbt_automaton_propositional_symbol;
typedef struct xbt_automaton_propositional_symbol* xbt_automaton_propositional_symbol_t;
+typedef int (*xbt_automaton_propositional_symbol_callback_type)(void*);
+typedef void (*xbt_automaton_propositional_symbol_free_function_type)(void*);
XBT_PUBLIC(xbt_automaton_t) xbt_automaton_new(void);
XBT_PUBLIC(void) xbt_automaton_exp_label_display(xbt_automaton_exp_label_t l);
-XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct);
+// xbt_automaton_propositional_symbol constructors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void));
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value);
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+ xbt_automaton_t a, const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
+
+// xbt_automaton_propositional_symbol accessors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol);
+
+// xbt_automaton_propositional_symbol methods!
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol);
XBT_PUBLIC(xbt_automaton_state_t) xbt_automaton_get_current_state(xbt_automaton_t a);
_xbt_dynar_cursor_get(_dynar,_cursor,&_data) ; \
(_cursor)++ )
+#ifndef __cplusplus
+#define xbt_dynar_foreach_ptr(_dynar,_cursor,_ptr) \
+ for (_xbt_dynar_cursor_first(_dynar,&(_cursor)) ; \
+ (_ptr = _cursor < _dynar->used ? xbt_dynar_get_ptr(_dynar,_cursor) : NULL) ; \
+ (_cursor)++ )
+#else
+#define xbt_dynar_foreach_ptr(_dynar,_cursor,_ptr) \
+ for (_xbt_dynar_cursor_first(_dynar,&(_cursor)) ; \
+ (_ptr = _cursor < _dynar->used ? (decltype(_ptr)) xbt_dynar_get_ptr(_dynar,_cursor) : NULL) ; \
+ (_cursor)++ )
+#endif
/** @} */
SG_END_DECL()
{ \
xbt_running_ctx_t *__xbt_ex_ctx_ptr = __xbt_running_ctx_fetch(); \
int __ex_cleanup = 0; \
- __ex_mctx_t *__ex_mctx_en; \
__ex_mctx_t __ex_mctx_me; \
- __ex_mctx_en = __xbt_ex_ctx_ptr->ctx_mctx; \
+ __ex_mctx_t * __ex_mctx_en = __xbt_ex_ctx_ptr->ctx_mctx; \
__xbt_ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \
if (__ex_mctx_save(&__ex_mctx_me)) { \
if (1)
*/
#define xbt_fifo_foreach(f,i,n,type) \
for(i=xbt_fifo_get_first_item(f); \
- ((i)?(n=(type)(xbt_fifo_get_item_content(i))):(NULL)); \
+ ((i)?(n=(type)(xbt_fifo_get_item_content(i)),1):(0)); \
i=xbt_fifo_get_next_item(i))
/** @} */
XBT_PUBLIC(void) xbt_heap_push(xbt_heap_t H, void *content, double key);
XBT_PUBLIC(void *) xbt_heap_pop(xbt_heap_t H);
+XBT_PUBLIC(void) xbt_heap_rm_elm(xbt_heap_t H, void *content, double key);
XBT_PUBLIC(double) xbt_heap_maxkey(xbt_heap_t H);
XBT_PUBLIC(void *) xbt_heap_maxcontent(xbt_heap_t H);
#endif
+#ifdef _XBT_WIN32
+#define XBT_INTERNAL
+#else
+#define XBT_INTERNAL __attribute__((visibility ("hidden")))
+#endif
+
#if !defined (max) && !defined(__cplusplus)
# define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
XBT_PUBLIC_DATA(int) xbt_pagesize;
/** Cache the number of bits of addresses inside a given page, log2(xbt_pagesize). */
- XBT_PUBLIC_DATA(int) xbt_pagebits;
+XBT_PUBLIC_DATA(int) xbt_pagebits;
XBT_PUBLIC(const char *) xbt_procname(void);
*
* The heap structure itself is an opaque object that shouldnt be messed with.
*/
+typedef struct mdesc s_xbt_mheap_t;
typedef struct mdesc *xbt_mheap_t;
/* Allocate SIZE bytes of memory (and memset it to 0). */
XBT_PUBLIC( xbt_mheap_t ) mmalloc_get_default_md(void);
/* To change the heap used when using the legacy version malloc/free/realloc and such */
-void mmalloc_set_current_heap(xbt_mheap_t new_heap);
+xbt_mheap_t mmalloc_set_current_heap(xbt_mheap_t new_heap);
xbt_mheap_t mmalloc_get_current_heap(void);
struct s_mc_snapshot;
int mmalloc_compare_heap(struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2);
int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2);
int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t to_ignore1, xbt_dynar_t to_ignore2);
-int compare_heap_area(int process_index, void *area1, void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
+int compare_heap_area(int process_index, const void *area1, const void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
void reset_heap_information(void);
size_t mmalloc_get_bytes_used(xbt_mheap_t);
ssize_t mmalloc_get_busy_size(xbt_mheap_t, void *ptr);
+void* malloc_no_memset(size_t n);
+
SG_END_DECL()
#endif
#ifdef DJB2_HASH_FUNCTION
/* fast implementation of djb2 algorithm */
int c;
- register unsigned int hash = 5381;
+ unsigned int hash = 5381;
while (str_len--) {
c = *str++;
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
# elif defined(FNV_HASH_FUNCTION)
- register unsigned int hash = 0x811c9dc5;
+ unsigned int hash = 0x811c9dc5;
unsigned char *bp = (unsigned char *) str; /* start of buffer */
unsigned char *be = bp + str_len; /* beyond end of buffer */
}
# else
- register unsigned int hash = 0;
+ unsigned int hash = 0;
while (str_len--) {
hash += (*str) * (*str);
#ifdef DJB2_HASH_FUNCTION
/* fast implementation of djb2 algorithm */
int c;
- register unsigned int hash = 5381;
+ unsigned int hash = 5381;
while ((c = *str++)) {
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
# elif defined(FNV_HASH_FUNCTION)
- register unsigned int hash = 0x811c9dc5;
+ unsigned int hash = 0x811c9dc5;
while (*str) {
/* multiply by the 32 bit FNV magic prime mod 2^32 */
}
# else
- register unsigned int hash = 0;
+ unsigned int hash = 0;
while (*str) {
hash += (*str) * (*str);
#endif
return hash;
}
-
+
/**@}*/
SG_END_DECL()
* @param swag what to iterate over
* @warning you cannot modify the \a swag while using this loop
* @hideinitializer */
+#ifndef __cplusplus
#define xbt_swag_foreach(obj,swag) \
for((obj)=xbt_swag_getFirst((swag)); \
(obj)!=NULL; \
(obj)=xbt_swag_getNext((obj),(swag)->offset))
-
+#else
+#define xbt_swag_foreach(obj,swag) \
+ for((obj)=(decltype(obj)) xbt_swag_getFirst((swag)); \
+ (obj)!=NULL; \
+ (obj)=(decltype(obj)) xbt_swag_getNext((obj),(swag)->offset))
+#endif
/**
* @brief A safe swag iterator
* @param obj the indice of the loop
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Comm_destroy(JNIEnv *env, jobject jcomm) {
+Java_org_simgrid_msg_Comm_nativeFinalize(JNIEnv *env, jobject jcomm) {
msg_comm_t comm;
msg_task_t *task_received;
Java_org_simgrid_msg_Comm_nativeInit(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Comm_destroy(JNIEnv *env, jobject jcomm);
+Java_org_simgrid_msg_Comm_nativeFinalize(JNIEnv *env, jobject jcomm);
JNIEXPORT jboolean JNICALL
Java_org_simgrid_msg_Comm_test(JNIEnv *env, jobject jcomm);
(*env)->ReleaseStringUTFChars(env, jname, name);
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_RngStream_destroy(JNIEnv *env, jobject jrngstream) {
+Java_org_simgrid_msg_RngStream_nativeFinalize(JNIEnv *env, jobject jrngstream) {
RngStream rngstream = jrngstream_to_native(env, jrngstream);
RngStream_DeleteStream(&rngstream);
(*env)->SetLongField(env, jrngstream, jrngstream_bind, (intptr_t)NULL);
Java_org_simgrid_msg_RngStream_create(JNIEnv *env, jobject jrngstream, jstring name);
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_RngStream_destroy(JNIEnv *env, jobject jrngstream);
+Java_org_simgrid_msg_RngStream_nativeFinalize(JNIEnv *env, jobject jrngstream);
JNIEXPORT jboolean JNICALL
Java_org_simgrid_msg_RngStream_setPackageSeed(JNIEnv *env, jobject jrngstream, jintArray seed);
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Mutex_exit(JNIEnv * env, jobject obj) {
+Java_org_simgrid_msg_Mutex_nativeFinalize(JNIEnv * env, jobject obj) {
xbt_mutex_t mutex;
mutex = (xbt_mutex_t) (long) (*env)->GetLongField(env, obj, jsyncro_field_Mutex_bind);
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Mutex_destroy(JNIEnv * env, jobject obj) {
+Java_org_simgrid_msg_Semaphore_nativeFinalize(JNIEnv * env, jobject obj) {
msg_sem_t sem;
sem = (msg_sem_t) (long) (*env)->GetLongField(env, obj, jsyncro_field_Semaphore_bind);
Java_org_simgrid_msg_Mutex_release(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Mutex_exit(JNIEnv * env, jobject obj);
+Java_org_simgrid_msg_Mutex_nativeFinalize(JNIEnv * env, jobject obj);
+
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Semaphore_nativeInit(JNIEnv *env, jclass cls);
JNIEXPORT jboolean JNICALL
Java_org_simgrid_msg_Semaphore_wouldBlock(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Mutex_destroy(JNIEnv * env, jobject obj);
+Java_org_simgrid_msg_Semaphore_nativeFinalize(JNIEnv * env, jobject obj);
#endif /* !MSG_JPROCESS_H */
return jcomm;
}
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_Task_nativeFinalize(JNIEnv * env, jobject jtask) {
+ msg_task_t task = jtask_to_native_task(jtask, env);
+
+ if (!task) {
+ jxbt_throw_notbound(env, "task", jtask);
+ return;
+ }
+ MSG_task_destroy(task);
+}
static void msg_task_cancel_on_failed_dsend(void*t) {
msg_task_t task = t;
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Task_create
(JNIEnv * env, jobject jtask, jstring jname, jdouble jcomputeDuration, jdouble jmessageSize);
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_Task_nativeFinalize(JNIEnv * env, jobject jtask);
/*
* Class org_simgrid_msg_Task
* Method parallelCreate
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_destroy(JNIEnv *env, jobject jvm) {
+Java_org_simgrid_msg_VM_nativeFinalize(JNIEnv *env, jobject jvm) {
msg_vm_t vm = jvm_get_native(env,jvm);
MSG_vm_destroy(vm);
}
* Signature ()V
*/
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_destroy(JNIEnv *env, jobject jvm);
+Java_org_simgrid_msg_VM_nativeFinalize(JNIEnv *env, jobject jvm);
/**
* Class org_simgrid_msg_VM
* Method start
protected Comm() {
}
- /**
- * Finalize the communication object, destroying it.
- */
- protected void finalize() throws Throwable {
- destroy();
+ /** Destroy the C communication object, when the GC reclaims the java part. */
+ @Override
+ protected void finalize() {
+ try {
+ nativeFinalize();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
- /**
- * Unbind the communication object
- */
- protected native void destroy() throws NativeException;
+ protected native void nativeFinalize();
/**
* Returns if the communication is finished or not.
* If the communication has finished and there was an error,
* raise an exception.
*/
public native boolean test() throws TransferFailureException, HostFailureException, TimeoutException ;
- /**
- * Wait for the complemetion of the communication for an indefinite time
- */
+ /** Wait infinitely for the completion of the communication (infinite timeout) */
public void waitCompletion() throws TransferFailureException, HostFailureException, TimeoutException {
waitCompletion(-1);
}
/**
* Wait for the completion of the communication.
* Throws an exception if there were an error in the communication.
- * @param timeout Time before giving up
+ * @param timeout Time before giving up (infinite time if negative)
*/
public native void waitCompletion(double timeout) throws TransferFailureException, HostFailureException, TimeoutException;
public Mutex() {
init();
}
+ @Override
protected void finalize() {
- exit();
+ try {
+ nativeFinalize();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
- private native void exit();
+ private native void nativeFinalize();
private native void init();
public native void acquire();
public native void release();
/**
* Makes the current process sleep until millis milliseconds and nanos nanoseconds
* have elapsed.
- * You should note that unlike "waitFor" which takes seconds, this method takes milliseconds and nanoseconds.
+ * Unlike {@link #waitFor(double)} which takes seconds, this method takes
+ * milliseconds and nanoseconds.
* Overloads Thread.sleep.
* @param millis the length of time to sleep in milliseconds.
* @param nanos additionnal nanoseconds to sleep.
* The natively implemented method to create a C RngStream object.
*/
private native void create(String name);
- /**
- * Destructor
- */
+ @Override
protected void finalize() {
- destroy();
+ try {
+ nativeFinalize();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
/**
* Release the C RngStream object
*/
- private native void destroy();
+ private native void nativeFinalize();
/**
* Sets the initial seed of the package RngStreams to the six integers in the vector seed. This will
}
- /** Deletes this semaphore
- */
+ /** Deletes this semaphore when the GC reclaims it */
+ @Override
protected void finalize() {
- destroy();
+ try {
+ nativeFinalize();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
- /** The native implementation for destroying a semaphore
- */
- private native void destroy();
+ private native void nativeFinalize();
/**
* Class initializer, to initialize various JNI stuff
*/
/** Cancels a task. */
public native void cancel();
- /** Deletes a task.
- *
- * @exception NativeException if the destruction failed.
- */
- protected void finalize() throws NativeException {
- destroy();
+ /** Deletes a task once the garbage collector reclaims it */
+ @Override
+ protected void finalize() {
+ try {
+ // Exceptions in finalizers lead to bad situations:
+ // http://stackoverflow.com/questions/7644556/troubleshooting-a-java-memory-leak-finalization
+ nativeFinalize();
+ bind=0; // to avoid segfaults if the impossible happens yet again making this task surviving its finalize()
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
- /**
- * The natively implemented method to destroy a MSG task.
- */
- protected native void destroy();
+ protected native void nativeFinalize();
/* * * *
* * Communication-related * *
* * * */
}
return null;
}
- protected void finalize() {
- destroy();
+ @Override
+ public void finalize() {
+ try {
+ nativeFinalize();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
}
+ private native void nativeFinalize();
/* JNI / Native code */
public native void restore();
- /**
- * Destroy the VM
- */
- public native void destroy();
-
-
-
/**
* Class initializer, to initialize various JNI stuff
*/
#ifndef MC_DATATYPE_H
#define MC_DATATYPE_H
-#define UNW_LOCAL_ONLY
-
#include "xbt/misc.h"
#include "xbt/swag.h"
#include "xbt/fifo.h"
+#if HAVE_MC
#include <libunwind.h>
#include <dwarf.h>
+#endif
SG_BEGIN_DECL()
typedef struct s_stack_region{
void *address;
- char *process_name;
void *context;
size_t size;
int block;
extern int _sg_do_model_check_record;
extern int _sg_mc_checkpoint;
extern int _sg_mc_sparse_checkpoint;
-extern int _sg_mc_soft_dirty;
extern char* _sg_mc_property_file;
extern int _sg_mc_timeout;
extern int _sg_mc_hash;
extern int _sg_mc_send_determinism;
extern int _sg_mc_safety;
extern int _sg_mc_liveness;
+extern int _sg_mc_snapshot_fds;
extern int _sg_mc_termination;
extern xbt_dynar_t mc_heap_comparison_ignore;
extern xbt_dynar_t stacks_areas;
-extern void *maestro_stack_start;
-extern void *maestro_stack_end;
/********************************* Global *************************************/
void _mc_cfg_cb_reduce(const char *name, int pos);
void _mc_cfg_cb_checkpoint(const char *name, int pos);
void _mc_cfg_cb_sparse_checkpoint(const char *name, int pos);
-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);
void _mc_cfg_cb_send_determinism(const char *name, int pos);
void _mc_cfg_cb_termination(const char *name, int pos);
-XBT_PUBLIC(void) MC_do_the_modelcheck_for_real(void);
+XBT_PUBLIC(void) MC_run(void);
XBT_PUBLIC(void) MC_init(void);
XBT_PUBLIC(void) MC_exit(void);
XBT_PUBLIC(void) MC_process_clock_add(smx_process_t, double);
XBT_PUBLIC(void) MC_remove_ignore_heap(void *address, size_t size);
XBT_PUBLIC(void) MC_ignore_local_variable(const char *var_name, const char *frame);
XBT_PUBLIC(void) MC_ignore_global_variable(const char *var_name);
-XBT_PUBLIC(void) MC_new_stack_area(void *stack, smx_process_t process, void *context, size_t size);
+XBT_PUBLIC(void) MC_register_stack_area(void *stack, smx_process_t process, void *context, size_t size);
/********************************* Memory *************************************/
XBT_PUBLIC(void) MC_memory_init(void); /* Initialize the memory subsystem */
XBT_PUBLIC(void) MC_memory_exit(void);
+XBT_PUBLIC(void) MC_memory_init_server(void);
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2008-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 <cassert>
+
+#include "ModelChecker.hpp"
+#include "PageStore.hpp"
+
+::simgrid::mc::ModelChecker* mc_model_checker = NULL;
+
+namespace simgrid {
+namespace mc {
+
+ModelChecker::ModelChecker(pid_t pid, int socket)
+ : page_store_(500)
+{
+ this->hostnames_ = xbt_dict_new();
+ MC_process_init(&this->process(), pid, socket);
+}
+
+ModelChecker::~ModelChecker()
+{
+ MC_process_clear(&this->process_);
+ xbt_dict_free(&this->hostnames_);
+}
+
+const char* ModelChecker::get_host_name(const char* hostname)
+{
+ // Lookup the host name in the dictionary (or create it):
+ xbt_dictelm_t elt = xbt_dict_get_elm_or_null(this->hostnames_, hostname);
+ if (!elt) {
+ xbt_dict_set(this->hostnames_, hostname, NULL, NULL);
+ elt = xbt_dict_get_elm_or_null(this->hostnames_, hostname);
+ assert(elt);
+ }
+ return elt->key;
+}
+
+}
+}
--- /dev/null
+/* Copyright (c) 2007-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_MODEL_CHECKER_H
+#define MC_MODEL_CHECKER_H
+
+#include <sys/types.h>
+
+#include <simgrid_config.h>
+#include <xbt/dynar.h>
+
+#include "mc_forward.h"
+#include "mc_process.h"
+#include "PageStore.hpp"
+#include "mc_protocol.h"
+
+namespace simgrid {
+namespace mc {
+
+/** State of the model-checker (global variables for the model checker)
+ *
+ * Each part of the state of the model chercker represented as a global
+ * variable prevents some sharing between snapshots and must be ignored.
+ * By moving as much state as possible in this structure allocated
+ * on the model-checker heap, we avoid those issues.
+ */
+class ModelChecker {
+ // This is the parent snapshot of the current state:
+ s_mc_pages_store_t page_store_;
+ s_mc_process_t process_;
+ /** String pool for host names */
+ // TODO, use std::unordered_set with heterogeneous comparison lookup (C++14)
+ xbt_dict_t /* <hostname, NULL> */ hostnames_;
+public:
+ ModelChecker(ModelChecker const&) = delete;
+ ModelChecker& operator=(ModelChecker const&) = delete;
+ ModelChecker(pid_t pid, int socket);
+ ~ModelChecker();
+ s_mc_process_t& process()
+ {
+ return process_;
+ }
+ PageStore& page_store()
+ {
+ return page_store_;
+ }
+ const char* get_host_name(const char* name);
+};
+
+}
+}
+
+#endif
-/* Copyright (c) 2014. The SimGrid Team.
+/* Copyright (c) 2015. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#include <xbt.h>
-#include "mc_page_store.h"
+#include "PageStore.hpp"
#ifdef MC_PAGE_STORE_MD4
#include <nettle/md4.h>
#include "mc_mmu.h"
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_page_snapshot, mc,
"Logging specific to mc_page_snapshot");
-// ***** Utility:
+namespace simgrid {
+namespace mc {
/** @brief Compte a hash for the given memory page
*
* @return hash off the page
*/
static inline __attribute__ ((always_inline))
-s_mc_pages_store::hash_type mc_hash_page(const void* data)
+PageStore::hash_type mc_hash_page(const void* data)
{
#ifdef MC_PAGE_STORE_MD4
boost::array<uint64_t,2> result;
// ***** snapshot_page_manager
-s_mc_pages_store::s_mc_pages_store(size_t size) :
+PageStore::PageStore(size_t size) :
memory_(NULL), capacity_(0), top_index_(0)
{
// Using mmap in order to be able to expand the region
this->page_counts_.resize(size);
}
-s_mc_pages_store::~s_mc_pages_store()
+PageStore::~PageStore()
{
::munmap(this->memory_, this->capacity_ << xbt_pagebits);
}
-void s_mc_pages_store::resize(size_t size)
+void PageStore::resize(size_t size)
{
size_t old_bytesize = this->capacity_ << xbt_pagebits;
size_t new_bytesize = size << xbt_pagebits;
*
* @return index of the free page
*/
-size_t s_mc_pages_store::alloc_page()
+size_t PageStore::alloc_page()
{
if (this->free_pages_.empty()) {
}
}
-void s_mc_pages_store::remove_page(size_t pageno)
+void PageStore::remove_page(size_t pageno)
{
this->free_pages_.push_back(pageno);
const void* page = this->get_page(pageno);
}
/** Store a page in memory */
-size_t s_mc_pages_store::store_page(void* page)
+size_t PageStore::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
return pageno;
}
-// ***** Main C API
-
-extern "C" {
-
-mc_pages_store_t mc_pages_store_new()
-{
- return new s_mc_pages_store_t(500);
-}
-
-void mc_pages_store_delete(mc_pages_store_t store)
-{
- delete store;
}
-
}
#ifdef SIMGRID_TEST
#include <memory>
-#include "mc/mc_page_store.h"
+#include "mc/PageStore.hpp"
static int value = 0;
{
xbt_test_add("Init");
size_t pagesize = (size_t) getpagesize();
- std::auto_ptr<s_mc_pages_store_t> store = std::auto_ptr<s_mc_pages_store_t>(new s_mc_pages_store(500));
+ std::unique_ptr<simgrid::mc::PageStore> store
+ = std::unique_ptr<simgrid::mc::PageStore>(new simgrid::mc::PageStore(500));
void* data = getpage();
xbt_test_assert(store->size()==0, "Bad size");
}
#endif /* SIMGRID_TEST */
+
+}
-/* Copyright (c) 2014. The SimGrid Team.
+/* Copyright (c) 2015. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#ifndef MC_PAGE_STORE_H
#define MC_PAGE_STORE_H
-struct s_mc_pages_store;
-
-#ifdef __cplusplus
+namespace simgrid {
+namespace mc {
/** @brief Storage for snapshot memory pages
*
* we must be able to store multiple indices for the same hash.
*
*/
-struct s_mc_pages_store {
+class PageStore {
public: // Types
#ifdef MC_PAGE_STORE_MD4
typedef boost::array<uint64_t,2> hash_type;
void remove_page(size_t pageno);
public: // Constructors
- explicit s_mc_pages_store(size_t size);
- ~s_mc_pages_store();
+ PageStore(PageStore const&) = delete;
+ PageStore& operator=(PageStore const&) = delete;
+ explicit PageStore(size_t size);
+ ~PageStore();
public: // Methods
};
inline __attribute__((always_inline))
-void s_mc_pages_store::unref_page(size_t pageno) {
+void PageStore::unref_page(size_t pageno) {
if ((--this->page_counts_[pageno]) == 0) {
this->remove_page(pageno);
}
}
inline __attribute__((always_inline))
-void s_mc_pages_store::ref_page(size_t pageno) {
+void PageStore::ref_page(size_t pageno) {
++this->page_counts_[pageno];
}
inline __attribute__((always_inline))
-const void* s_mc_pages_store::get_page(size_t pageno) const {
+const void* PageStore::get_page(size_t pageno) const {
return mc_page_from_number(this->memory_, pageno);
}
inline __attribute__((always_inline))
-size_t s_mc_pages_store::get_ref(size_t pageno) {
+size_t PageStore::get_ref(size_t pageno) {
return this->page_counts_[pageno];
}
inline __attribute__((always_inline))
-size_t s_mc_pages_store::size() {
+size_t PageStore::size() {
return this->top_index_ - this->free_pages_.size();
}
inline __attribute__((always_inline))
-size_t s_mc_pages_store::capacity() {
+size_t PageStore::capacity() {
return this->capacity_;
}
-#endif
-
-SG_BEGIN_DECL()
-
-mc_pages_store_t mc_pages_store_new(void);
-void mc_pages_store_delete(mc_pages_store_t store);
-
-/**
- */
-static inline __attribute__((always_inline))
-const void* mc_page_store_get_page(mc_pages_store_t page_store, size_t pageno)
-{
- // This is page_store->memory_:
- void* memory = *(void**)page_store;
- return mc_page_from_number(memory, pageno);
}
-
-SG_END_DECL()
+}
#endif
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "mc_address_space.h"
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_ADDRESS_SPACE_H
+#define MC_ADDRESS_SPACE_H
+
+#include <xbt/misc.h>
+
+#include <stdint.h>
+
+#include "mc_forward.h"
+
+SG_BEGIN_DECL()
+
+// ***** Data types
+
+/** Options for the read() operation
+ *
+ * - MC_ADDRESS_SPACE_READ_FLAGS_LAZY, avoid a copy when the data is
+ * available in the current process. In this case, the return value
+ * of MC_address_space_read might be different from the provided one.
+ */
+typedef int adress_space_read_flags_t;
+#define MC_ADDRESS_SPACE_READ_FLAGS_NONE 0
+#define MC_ADDRESS_SPACE_READ_FLAGS_LAZY 1
+
+/** 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, 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);
+};
+
+typedef const void* (*mc_address_space_class_read_callback_t)(
+ mc_address_space_t address_space, adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size,
+ int process_index);
+typedef mc_process_t (*mc_address_space_class_get_process_callback_t)(mc_address_space_t address_space);
+
+// ***** Virtual/non-final methods
+
+/** Read data from the given address space
+ *
+ * Dysnamic dispatch.
+ */
+static inline __attribute__((always_inline))
+const void* MC_address_space_read(
+ mc_address_space_t address_space, 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)
+{
+ if (address_space->address_space_class->get_process)
+ return address_space->address_space_class->get_process(address_space);
+ else
+ return NULL;
+}
+
+SG_END_DECL()
+
+#endif
+++ /dev/null
-/* Copyright (c) 2008-2014. The SimGrid Team.
- * All rights reserved. */
-
-/* This program is free software; you can redistribute it and/or modify it
- * under the terms of the license (GNU LGPL) which comes with this package. */
-
-#include <simgrid/simix.h>
-
-#include "mc_base.h"
-#include "../simix/smx_private.h"
-#include "mc_record.h"
-
-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;
- smx_simcall_t req;
- unsigned int iter;
-
- while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
- SIMIX_process_runall();
- xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
- req = &process->simcall;
- if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
- SIMIX_simcall_handle(req, 0);
- }
- }
-}
-
-int MC_request_is_enabled(smx_simcall_t req)
-{
- unsigned int index = 0;
- smx_synchro_t act = 0;
- smx_mutex_t mutex = NULL;
-
- switch (req->call) {
- case SIMCALL_NONE:
- return FALSE;
-
- case SIMCALL_COMM_WAIT:
- /* FIXME: check also that src and dst processes are not suspended */
- act = simcall_comm_wait__get__comm(req);
- if (simcall_comm_wait__get__timeout(req) >= 0) {
- /* If it has a timeout it will be always be enabled, because even if the
- * communication is not ready, it can timeout and won't block. */
- if (_sg_mc_timeout == 1)
- return TRUE;
- } else {
- /* On the other hand if it hasn't a timeout, check if the comm is ready.*/
- if (act->comm.detached && act->comm.src_proc == NULL
- && act->comm.type == SIMIX_COMM_READY)
- return (act->comm.dst_proc != NULL);
- }
- return (act->comm.src_proc && act->comm.dst_proc);
-
- case SIMCALL_COMM_WAITANY:
- /* Check if it has at least one communication ready */
- xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act)
- if (act->comm.src_proc && act->comm.dst_proc)
- return TRUE;
- return FALSE;
-
- case SIMCALL_MUTEX_LOCK:
- mutex = simcall_mutex_lock__get__mutex(req);
- if(mutex->owner == NULL)
- return TRUE;
- else
- return (mutex->owner->pid == req->issuer->pid);
-
- default:
- /* The rest of the requests are always enabled */
- return TRUE;
- }
-}
-
-int MC_request_is_visible(smx_simcall_t req)
-{
- return req->call == SIMCALL_COMM_ISEND
- || req->call == SIMCALL_COMM_IRECV
- || req->call == SIMCALL_COMM_WAIT
- || req->call == SIMCALL_COMM_WAITANY
- || req->call == SIMCALL_COMM_TEST
- || req->call == SIMCALL_COMM_TESTANY
- || req->call == SIMCALL_MC_RANDOM
- || req->call == SIMCALL_MUTEX_LOCK
-#ifdef HAVE_MC
- || req->call == SIMCALL_MC_SNAPSHOT
- || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS
-#endif
- ;
-}
-
-int MC_random(int min, int max)
-{
- /*FIXME: return mc_current_state->executed_transition->random.value; */
- return simcall_mc_random(min, max);
-}
-
-static int prng_random(int min, int max)
-{
- unsigned long output_size = ((unsigned long) max - (unsigned long) min) + 1;
- unsigned long input_size = (unsigned long) RAND_MAX + 1;
- unsigned long reject_size = input_size % output_size;
- unsigned long accept_size = input_size - reject_size; // module*accept_size
-
- // Use rejection in order to avoid skew
- long x;
- do {
-#ifndef _XBT_WIN32
- x = random();
-#else
- x = rand();
-#endif
- } while( x >= accept_size );
- return min + (x % output_size);
-}
-
-int simcall_HANDLER_mc_random(smx_simcall_t simcall, int min, int max)
-{
- if (!MC_is_active() && !MC_record_path){
- return prng_random(min, max);
- }
-
- return simcall->mc_value;
-}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <assert.h>
+
+#include <simgrid/simix.h>
+
+#include "mc_base.h"
+#include "../simix/smx_private.h"
+#include "mc/mc_record.h"
+#include "mc/mc_replay.h"
+#include "mc/mc.h"
+
+#ifdef HAVE_MC
+#include "mc_process.h"
+#include "ModelChecker.hpp"
+#include "mc_protocol.h"
+#include "mc_smx.h"
+#include "mc_server.h"
+#endif
+
+extern "C" {
+
+XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
+
+void MC_wait_for_requests(void)
+{
+#ifdef HAVE_MC
+ if (mc_mode == MC_MODE_SERVER) {
+ MC_server_wait_client(&mc_model_checker->process());
+ return;
+ }
+#endif
+
+ smx_process_t process;
+ smx_simcall_t req;
+ unsigned int iter;
+
+ while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
+ SIMIX_process_runall();
+ xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
+ req = &process->simcall;
+ if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
+ SIMIX_simcall_handle(req, 0);
+ }
+ }
+}
+
+// Called from both MCer and MCed:
+int MC_request_is_enabled(smx_simcall_t req)
+{
+ unsigned int index = 0;
+ smx_synchro_t act = 0;
+#ifdef HAVE_MC
+ s_smx_synchro_t temp_synchro;
+#endif
+
+ switch (req->call) {
+ case SIMCALL_NONE:
+ return FALSE;
+
+ case SIMCALL_COMM_WAIT:
+ /* FIXME: check also that src and dst processes are not suspended */
+ act = simcall_comm_wait__get__comm(req);
+
+#ifdef HAVE_MC
+ // Fetch from MCed memory:
+ if (mc_mode == MC_MODE_SERVER) {
+ MC_process_read(&mc_model_checker->process(), MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &temp_synchro, act, sizeof(temp_synchro),
+ MC_PROCESS_INDEX_ANY);
+ act = &temp_synchro;
+ }
+#endif
+
+ if (simcall_comm_wait__get__timeout(req) >= 0) {
+ /* If it has a timeout it will be always be enabled, because even if the
+ * communication is not ready, it can timeout and won't block. */
+ if (_sg_mc_timeout == 1)
+ return TRUE;
+ } else {
+ /* On the other hand if it hasn't a timeout, check if the comm is ready.*/
+ if (act->comm.detached && act->comm.src_proc == NULL
+ && act->comm.type == SIMIX_COMM_READY)
+ return (act->comm.dst_proc != NULL);
+ }
+ return (act->comm.src_proc && act->comm.dst_proc);
+
+ case SIMCALL_COMM_WAITANY: {
+ xbt_dynar_t comms;
+#ifdef HAVE_MC
+
+ s_xbt_dynar_t comms_buffer;
+ size_t buffer_size = 0;
+ if (mc_mode == MC_MODE_SERVER) {
+ // Read dynar:
+ MC_process_read_simple(&mc_model_checker->process(),
+ &comms_buffer, simcall_comm_waitany__get__comms(req), sizeof(comms_buffer));
+ assert(comms_buffer.elmsize == sizeof(act));
+ buffer_size = comms_buffer.elmsize * comms_buffer.used;
+ comms = &comms_buffer;
+ } else {
+ comms = simcall_comm_waitany__get__comms(req);
+ }
+ // Read all the dynar buffer:
+ char buffer[buffer_size];
+ if (mc_mode == MC_MODE_SERVER)
+ MC_process_read_simple(&mc_model_checker->process(),
+ buffer, comms->data, sizeof(buffer));
+#else
+ comms = simcall_comm_waitany__get__comms(req);
+#endif
+
+ for (index = 0; index < comms->used; ++index) {
+#ifdef HAVE_MC
+ // Fetch act from MCed memory:
+ if (mc_mode == MC_MODE_SERVER) {
+ memcpy(&act, buffer + comms->elmsize * index, sizeof(act));
+ MC_process_read(&mc_model_checker->process(), MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &temp_synchro, act, sizeof(temp_synchro),
+ MC_PROCESS_INDEX_ANY);
+ act = &temp_synchro;
+ }
+ else
+#endif
+ act = xbt_dynar_get_as(comms, index, smx_synchro_t);
+ if (act->comm.src_proc && act->comm.dst_proc)
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ case SIMCALL_MUTEX_LOCK: {
+ smx_mutex_t mutex = simcall_mutex_lock__get__mutex(req);
+#ifdef HAVE_MC
+ s_smx_mutex_t temp_mutex;
+ if (mc_mode == MC_MODE_SERVER) {
+ MC_process_read(&mc_model_checker->process(), MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &temp_mutex, mutex, sizeof(temp_mutex),
+ MC_PROCESS_INDEX_ANY);
+ mutex = &temp_mutex;
+ }
+#endif
+ if(mutex->owner == NULL)
+ return TRUE;
+ else
+#ifdef HAVE_MC
+ // TODO, *(mutex->owner) :/
+ return MC_smx_resolve_process(mutex->owner)->pid ==
+ MC_smx_resolve_process(req->issuer)->pid;
+#else
+ return mutex->owner->pid == req->issuer->pid;
+#endif
+ }
+
+ default:
+ /* The rest of the requests are always enabled */
+ return TRUE;
+ }
+}
+
+int MC_request_is_visible(smx_simcall_t req)
+{
+ return req->call == SIMCALL_COMM_ISEND
+ || req->call == SIMCALL_COMM_IRECV
+ || req->call == SIMCALL_COMM_WAIT
+ || req->call == SIMCALL_COMM_WAITANY
+ || req->call == SIMCALL_COMM_TEST
+ || req->call == SIMCALL_COMM_TESTANY
+ || req->call == SIMCALL_MC_RANDOM
+ || req->call == SIMCALL_MUTEX_LOCK
+#ifdef HAVE_MC
+ || req->call == SIMCALL_MC_SNAPSHOT
+ || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS
+#endif
+ ;
+}
+
+int MC_random(int min, int max)
+{
+ /*FIXME: return mc_current_state->executed_transition->random.value; */
+ return simcall_mc_random(min, max);
+}
+
+static int prng_random(int min, int max)
+{
+ unsigned long output_size = ((unsigned long) max - (unsigned long) min) + 1;
+ unsigned long input_size = (unsigned long) RAND_MAX + 1;
+ unsigned long reject_size = input_size % output_size;
+ unsigned long accept_size = input_size - reject_size; // module*accept_size
+
+ // Use rejection in order to avoid skew
+ unsigned long x;
+ do {
+#ifndef _XBT_WIN32
+ x = (unsigned long) random();
+#else
+ x = (unsigned long) rand();
+#endif
+ } while( x >= accept_size );
+ return min + (x % output_size);
+}
+
+int simcall_HANDLER_mc_random(smx_simcall_t simcall, int min, int max)
+{
+ if (!MC_is_active() && !MC_record_path){
+ return prng_random(min, max);
+ }
+
+ return simcall->mc_value;
+}
+
+void MC_simcall_handle(smx_simcall_t req, int value)
+{
+#ifndef HAVE_MC
+ SIMIX_simcall_handle(req, value);
+#else
+ if (mc_mode == MC_MODE_CLIENT) {
+ SIMIX_simcall_handle(req, value);
+ return;
+ }
+
+ unsigned i;
+ mc_smx_process_info_t pi = NULL;
+
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, i, pi) {
+ if (req == &pi->copy.simcall) {
+ MC_server_simcall_handle(&mc_model_checker->process(), pi->copy.pid, value);
+ return;
+ }
+ }
+
+ xbt_die("Could not find the request");
+#endif
+}
+
+}
#ifndef MC_BASE_H
#define MC_BASE_H
+#include <xbt/misc.h>
#include <simgrid/simix.h>
#include "simgrid_config.h"
#include "internal_config.h"
#include "../simix/smx_private.h"
+// Marker for symbols which should be defined as XBT_PRIVATE but are used in
+// unit tests:
+#define MC_SHOULD_BE_INTERNAL
+
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;
+XBT_INTERNAL extern double *mc_time;
SG_END_DECL()
/* 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. */
-#define _GNU_SOURCE
-#define UNW_LOCAL_ONLY
-
#include <unistd.h>
#include <string.h>
#include "../simix/smx_private.h"
-#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <libelf.h>
#include "mc_snapshot.h"
#include "mc_object_info.h"
#include "mc_mmu.h"
+#include "mc_unw.h"
+#include "mc_protocol.h"
+#include "mc_smx.h"
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc,
"Logging specific to mc_checkpoint");
-char *libsimgrid_path;
-
/************************************ Free functions **************************************/
/*****************************************************************************************/
if (s) {
xbt_dynar_free(&(s->local_variables));
xbt_dynar_free(&(s->stack_frames));
+ mc_unw_destroy_context(s->context);
+ xbt_free(s->context);
xbt_free(s);
}
}
static void MC_snapshot_stack_free_voidp(void *s)
{
- MC_snapshot_stack_free((mc_snapshot_stack_t) * (void **) s);
+ mc_snapshot_stack_t stack = (mc_snapshot_stack_t) * (void **) s;
+ MC_snapshot_stack_free(stack);
}
static void local_variable_free(local_variable_t v)
local_variable_free((local_variable_t) * (void **) v);
}
-void MC_region_destroy(mc_mem_region_t reg)
+void MC_region_destroy(mc_mem_region_t region)
{
- if (!reg)
+ if (!region)
return;
-
- //munmap(reg->data, reg->size);
- xbt_free(reg->data);
- if (reg->page_numbers) {
- mc_free_page_snapshot_region(reg->page_numbers, mc_page_count(reg->size));
+ switch(region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ break;
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ xbt_free(region->flat.data);
+ break;
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
+ mc_free_page_snapshot_region(region->chunked.page_numbers, mc_page_count(region->size));
+ xbt_free(region->chunked.page_numbers);
+ break;
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ {
+ size_t regions_count = region->privatized.regions_count;
+ for (size_t i=0; i!=regions_count; ++i) {
+ MC_region_destroy(region->privatized.regions[i]);
+ }
+ free(region->privatized.regions);
+ break;
+ }
}
- xbt_free(reg);
+ xbt_free(region);
}
void MC_free_snapshot(mc_snapshot_t snapshot)
{
- unsigned int i;
- for (i = 0; i < NB_REGIONS; i++) {
- MC_region_destroy(snapshot->regions[i]);
+ for (size_t i = 0; i < snapshot->snapshot_regions_count; i++) {
+ MC_region_destroy(snapshot->snapshot_regions[i]);
}
-
+ xbt_free(snapshot->snapshot_regions);
xbt_free(snapshot->stack_sizes);
xbt_dynar_free(&(snapshot->stacks));
xbt_dynar_free(&(snapshot->to_ignore));
xbt_dynar_free(&snapshot->ignored_data);
-
- if (snapshot->privatization_regions) {
- size_t n = xbt_dynar_length(snapshot->enabled_processes);
- for (i = 0; i != n; ++i) {
- MC_region_destroy(snapshot->privatization_regions[i]);
- }
- xbt_free(snapshot->privatization_regions);
- }
-
xbt_free(snapshot);
}
/******************************* Snapshot regions ********************************/
/*********************************************************************************/
-static mc_mem_region_t mc_region_new_dense(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+static mc_mem_region_t mc_region_new_dense(
+ mc_region_type_t region_type,
+ void *start_addr, void* permanent_addr, size_t size)
{
- mc_mem_region_t new_reg = xbt_new(s_mc_mem_region_t, 1);
- new_reg->start_addr = start_addr;
- new_reg->permanent_addr = permanent_addr;
- new_reg->data = NULL;
- new_reg->size = size;
- new_reg->page_numbers = NULL;
- new_reg->data = xbt_malloc(size);
- memcpy(new_reg->data, permanent_addr, size);
+ mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ region->region_type = region_type;
+ region->storage_type = MC_REGION_STORAGE_TYPE_FLAT;
+ region->start_addr = start_addr;
+ region->permanent_addr = permanent_addr;
+ region->size = size;
+ region->flat.data = xbt_malloc(size);
+ MC_process_read(&mc_model_checker->process(), MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ region->flat.data, permanent_addr, size,
+ MC_PROCESS_INDEX_DISABLED);
XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu",
- type, new_reg->data, permanent_addr, size);
- return new_reg;
-
+ region_type, region->flat.data, permanent_addr, size);
+ return region;
}
/** @brief Take a snapshot of a given region
* @param start_addr Address of the region in the simulated process
* @param permanent_addr Permanent address of this data (for privatized variables, this is the virtual address of the privatized mapping)
* @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)
{
if (_sg_mc_sparse_checkpoint) {
- return mc_region_new_sparse(type, start_addr, permanent_addr, size, ref_reg);
+ return mc_region_new_sparse(type, start_addr, permanent_addr, size);
} else {
- return mc_region_new_dense(type, start_addr, permanent_addr, size, ref_reg);
+ return mc_region_new_dense(type, start_addr, permanent_addr, size);
}
}
/** @brief Restore a region from a snapshot
- *
- * If we are using per page snapshots, it is possible to use the reference
- * region in order to do an incremental restoration of the region: the
- * softclean pages which are shared between the two snapshots do not need
- * to be restored.
*
* @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)
{
- /*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);
+ break;
+
+ case 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]);
+ }
+ break;
+ }
}
- return;
}
-static void MC_snapshot_add_region(mc_snapshot_t snapshot, int type,
- void *start_addr, void* permanent_addr, size_t size)
+static mc_mem_region_t MC_region_new_privatized(
+ mc_region_type_t region_type, void *start_addr, void* permanent_addr, size_t size
+ )
+{
+ size_t process_count = MC_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);
+
+ // Read smpi_privatisation_regions from MCed:
+ smpi_privatisation_region_t remote_smpi_privatisation_regions;
+ MC_process_read_variable(&mc_model_checker->process(),
+ "smpi_privatisation_regions",
+ &remote_smpi_privatisation_regions, sizeof(remote_smpi_privatisation_regions));
+ s_smpi_privatisation_region_t privatisation_regions[process_count];
+ MC_process_read_simple(&mc_model_checker->process(), &privatisation_regions,
+ remote_smpi_privatisation_regions, sizeof(privatisation_regions));
+
+ for (size_t i = 0; i < process_count; i++) {
+ region->privatized.regions[i] =
+ MC_region_new(region_type, start_addr,
+ privatisation_regions[i].address, size);
+ }
+
+ 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 region;
+ const bool privatization_aware = MC_object_info_is_privatized(object_info);
+ if (privatization_aware && MC_smpi_process_count())
+ region = MC_region_new_privatized(type, start_addr, permanent_addr, size);
+ else
+ region = MC_region_new(type, start_addr, permanent_addr, size);
+
+ 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);
- }
- snapshot->privatization_index = smpi_loaded_page;
- snapshot->regions[2] = NULL;
+ if (smpi_privatize_global_variables && MC_smpi_process_count()) {
+ // snapshot->privatization_index = smpi_loaded_page
+ MC_process_read_variable(&mc_model_checker->process(),
+ "smpi_loaded_page", &snapshot->privatization_index,
+ sizeof(snapshot->privatization_index));
} 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;
+ ssize_t i = 0;
s_map_region_t reg;
const char *name = basename(result->file_name);
while (i < maps->mapsize) {
xbt_assert(!result->start_rw,
"Multiple read-write segments for %s, not supported",
maps->regions[i].pathname);
- result->start_rw = reg.start_addr;
- result->end_rw = reg.end_addr;
+ result->start_rw = (char*) reg.start_addr;
+ result->end_rw = (char*) reg.end_addr;
// .bss is usually after the .data:
s_map_region_t *next = &(maps->regions[i + 1]);
if (next->pathname == NULL && (next->prot & PROT_WRITE)
&& next->start_addr == reg.end_addr) {
- result->end_rw = maps->regions[i + 1].end_addr;
+ result->end_rw = (char*) maps->regions[i + 1].end_addr;
}
} else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)) {
xbt_assert(!result->start_exec,
"Multiple executable segments for %s, not supported",
maps->regions[i].pathname);
- result->start_exec = reg.start_addr;
- result->end_exec = reg.end_addr;
+ result->start_exec = (char*) reg.start_addr;
+ result->end_exec = (char*) reg.end_addr;
} else if ((reg.prot & PROT_READ) && !(reg.prot & PROT_EXEC)) {
xbt_assert(!result->start_ro,
"Multiple read only segments for %s, not supported",
maps->regions[i].pathname);
- result->start_ro = reg.start_addr;
- result->end_ro = reg.end_addr;
+ result->start_ro = (char*) reg.start_addr;
+ result->end_ro = (char*) reg.end_addr;
}
i++;
}
+ result->start = result->start_rw;
+ if ((const void*) result->start_ro > result->start)
+ result->start = result->start_ro;
+ if ((const void*) result->start_exec > result->start)
+ result->start = result->start_exec;
+
+ result->end = result->end_rw;
+ if (result->end_ro && (const void*) result->end_ro < result->end)
+ result->end = result->end_ro;
+ if (result->end_exec && (const void*) result->end_exec > result->end)
+ result->end = result->end_exec;
+
xbt_assert(result->file_name);
xbt_assert(result->start_rw);
xbt_assert(result->start_exec);
static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
dw_frame_t scope, int process_index, xbt_dynar_t result)
{
+ mc_process_t process = &mc_model_checker->process();
+
void *ip = (void *) stack_frame->ip;
if (ip < scope->low_pc || ip >= scope->high_pc)
return;
continue;
int region_type;
- if ((long) stack_frame->ip > (long) mc_libsimgrid_info->start_exec)
+ // FIXME, get rid of `region_type`
+ if ((long) stack_frame->ip > (long) process->libsimgrid_info->start_exec)
region_type = 1;
else
region_type = 2;
new_var->address = current_variable->address;
} else if (current_variable->locations.size != 0) {
s_mc_location_t location;
- mc_dwarf_resolve_locations(&location, ¤t_variable->locations,
- current_variable->object_info,
- &(stack_frame->unw_cursor),
- (void *) stack_frame->frame_base,
- NULL, process_index);
+ mc_dwarf_resolve_locations(
+ &location, ¤t_variable->locations,
+ current_variable->object_info,
+ &(stack_frame->unw_cursor),
+ (void *) stack_frame->frame_base,
+ (mc_address_space_t) &mc_model_checker->process(), process_index);
switch(mc_get_location_type(&location)) {
case MC_LOCATION_TYPE_ADDRESS:
}
}
-static xbt_dynar_t MC_unwind_stack_frames(void *stack_context)
+static xbt_dynar_t MC_unwind_stack_frames(mc_unw_context_t stack_context)
{
+ mc_process_t process = &mc_model_checker->process();
xbt_dynar_t result =
xbt_dynar_new(sizeof(mc_stack_frame_t), MC_stack_frame_free_voipd);
unw_cursor_t c;
// TODO, check condition check (unw_init_local==0 means end of frame)
- if (unw_init_local(&c, (unw_context_t *) stack_context) != 0) {
+ if (mc_unw_init_cursor(&c, stack_context) != 0) {
xbt_die("Could not initialize stack unwinding");
// TODO, use real addresses in frame_t instead of fixing it here
- dw_frame_t frame = MC_find_function_by_ip((void *) ip);
+ dw_frame_t frame = MC_process_find_function(process, (void *) ip);
stack_frame->frame = frame;
if (frame) {
&& !strcmp(frame->name, "smx_ctx_sysv_wrapper"))
break;
- int ret = ret = unw_step(&c);
+ int ret = unw_step(&c);
if (ret == 0) {
xbt_die("Unexpected end of stack.");
} else if (ret < 0) {
- xbt_die("Error while unwinding stack.");
+ xbt_die("Error while unwinding stack");
}
}
unsigned int cursor = 0;
stack_region_t current_stack;
+ // FIXME, cross-process support (stack_areas)
xbt_dynar_foreach(stacks_areas, cursor, current_stack) {
mc_snapshot_stack_t st = xbt_new(s_mc_snapshot_stack_t, 1);
- st->stack_frames = MC_unwind_stack_frames(current_stack->context);
+
+ // Read the context from remote process:
+ unw_context_t context;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &context, (unw_context_t*) current_stack->context, sizeof(context));
+
+ st->context = xbt_new0(s_mc_unw_context_t, 1);
+ if (mc_unw_init_context(st->context, &mc_model_checker->process(),
+ &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;
unw_word_t sp = xbt_dynar_get_as(st->stack_frames, 0, mc_stack_frame_t)->sp;
xbt_dynar_push(res, &st);
- (*snapshot)->stack_sizes =
+ (*snapshot)->stack_sizes = (size_t*)
xbt_realloc((*snapshot)->stack_sizes, (cursor + 1) * sizeof(size_t));
(*snapshot)->stack_sizes[cursor] =
(char*) current_stack->address + current_stack->size - (char*) sp;
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) {
+ xbt_dynar_foreach (mc_model_checker->process().checkpoint_ignore, cursor, region) {
s_mc_snapshot_ignored_data_t ignored_data;
ignored_data.start = region->addr;
ignored_data.size = region->size;
ignored_data.data = malloc(region->size);
- memcpy(ignored_data.data, region->addr, region->size);
+ // TODO, we should do this once per privatization segment:
+ MC_process_read(snapshot->process,
+ MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ ignored_data.data, region->addr, region->size, MC_PROCESS_INDEX_DISABLED);
xbt_dynar_push(snapshot->ignored_data, &ignored_data);
}
// Zero the memory:
- xbt_dynar_foreach (mc_checkpoint_ignore, cursor, region) {
- memset(region->addr, 0, region->size);
+ xbt_dynar_foreach (mc_model_checker->process().checkpoint_ignore, cursor, region) {
+ MC_process_clear_memory(snapshot->process, region->addr, region->size);
}
}
unsigned int cursor = 0;
s_mc_snapshot_ignored_data_t ignored_data;
xbt_dynar_foreach (snapshot->ignored_data, cursor, ignored_data) {
- memcpy(ignored_data.start, ignored_data.data, ignored_data.size);
+ MC_process_write(snapshot->process,
+ ignored_data.data, ignored_data.start, ignored_data.size);
}
}
-/** @brief Can we remove this snapshot?
- *
- * Some snapshots cannot be removed (yet) because we need them
- * at this point.
- *
- * @param snapshot
- */
-int mc_important_snapshot(mc_snapshot_t snapshot)
+static void MC_get_current_fd(mc_snapshot_t snapshot)
{
- // We need this snapshot in order to know which
- // pages needs to be stored in the next snapshot.
- // This field is only non-NULL when using soft-dirty
- // page tracking.
- if (snapshot == mc_model_checker->parent_snapshot)
- return true;
-
- return false;
-}
-
-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)
+ int res = snprintf(fd_dir_path, fd_dir_path_size,
+ "/proc/%lli/fd", (long long int) snapshot->process->pid);
+ xbt_assert(res >= 0);
+ if ((size_t) res > fd_dir_path_size)
xbt_die("Unexpected buffer is too small for fd_dir_path");
- DIR* fd_dir = opendir (fd_dir_path);
+ DIR* fd_dir = opendir(fd_dir_path);
if (fd_dir == NULL)
xbt_die("Cannot open directory '/proc/self/fd'\n");
const size_t source_size = 25;
char source[25];
- if (snprintf(source, source_size, "/proc/self/fd/%s", fd_number->d_name) > source_size)
+ int res = snprintf(source, source_size, "/proc/%lli/fd/%s",
+ (long long int) snapshot->process->pid, fd_number->d_name);
+ xbt_assert(res >= 0);
+ if ((size_t) res > source_size)
xbt_die("Unexpected buffer is too small for fd %s", fd_number->d_name);
const size_t link_size = 200;
char link[200];
- int res = readlink(source, link, link_size);
+ res = readlink(source, link, link_size);
if (res<0) {
xbt_die("Could not read link for %s", source);
}
fd->number = fd_value;
fd->flags = fcntl(fd_value, F_GETFL) | fcntl(fd_value, F_GETFD) ;
fd->current_position = lseek(fd_value, 0, SEEK_CUR);
- snapshot->current_fd = xbt_realloc(snapshot->current_fd, (total_fd + 1) * sizeof(fd_infos_t));
+ snapshot->current_fd = (fd_infos_t*) xbt_realloc(snapshot->current_fd, (total_fd + 1) * sizeof(fd_infos_t));
snapshot->current_fd[total_fd] = fd;
total_fd++;
}
closedir (fd_dir);
}
+static s_mc_address_space_class_t mc_snapshot_class = {
+ (mc_address_space_class_read_callback_t) &MC_snapshot_read,
+ NULL
+};
+
mc_snapshot_t MC_take_snapshot(int num_state)
{
+ XBT_DEBUG("Taking snapshot %i", 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->num_state = num_state;
+ snapshot->address_space.address_space_class = &mc_snapshot_class;
+
snapshot->enabled_processes = xbt_dynar_new(sizeof(int), NULL);
+
smx_process_t process;
- xbt_swag_foreach(process, simix_global->process_list) {
- xbt_dynar_push_as(snapshot->enabled_processes, int, (int)process->pid);
- }
+ MC_EACH_SIMIX_PROCESS(process,
+ 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);
/* 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_softdirty_reset();
- }
+ MC_get_memory_regions(mc_process, snapshot);
snapshot->to_ignore = MC_take_snapshot_ignore();
}
MC_snapshot_ignore_restore(snapshot);
- if (_sg_mc_sparse_checkpoint && _sg_mc_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]);
}
#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);
- }
- }
- }
+ // TODO, send a message to implement this in the MCed process
if(snapshot->privatization_index >= 0) {
// We just rewrote the global variables.
// The privatisation segment SMPI thinks
smpi_really_switch_data_segment(snapshot->privatization_index);
}
#endif
+}
+
+static inline
+void MC_restore_snapshot_fds(mc_snapshot_t snapshot)
+{
+ if (mc_mode == MC_MODE_SERVER)
+ xbt_die("FD snapshot not implemented in client/server mode.");
- for(i=0; i < snapshot->total_fd; i++){
+ int new_fd;
+ for (int i=0; i < snapshot->total_fd; i++) {
new_fd = open(snapshot->current_fd[i]->filename, snapshot->current_fd[i]->flags);
if (new_fd <0) {
};
lseek(snapshot->current_fd[i]->number, snapshot->current_fd[i]->current_position, SEEK_SET);
}
+}
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
- mc_softdirty_reset();
- }
-
+void MC_restore_snapshot(mc_snapshot_t snapshot)
+{
+ XBT_DEBUG("Restore snapshot %i", snapshot->num_state);
+ MC_restore_snapshot_regions(snapshot);
+ if (_sg_mc_snapshot_fds)
+ MC_restore_snapshot_fds(snapshot);
MC_snapshot_ignore_restore(snapshot);
- if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
- mc_model_checker->parent_snapshot = snapshot;
- }
-
+ mc_model_checker->process().cache_flags = 0;
}
mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)
return MC_take_snapshot(1);
}
-void *MC_snapshot(void)
-{
- return simcall_mc_snapshot();
}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <xbt/log.h>
+#include <xbt/sysdep.h>
+#include <xbt/mmalloc.h>
+
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+// We won't need those once the separation MCer/MCed is complete:
+#include "mc_mmalloc.h"
+#include "mc_ignore.h"
+#include "mc_private.h" // MC_deadlock_check()
+#include "mc_smx.h"
+
+extern "C" {
+
+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");
+ 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)
+{
+ if (MC_protocol_hello(mc_client->fd) != 0)
+ xbt_die("Could not say hello 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_send_simple_message(e_mc_message_type type)
+{
+ if (MC_protocol_send_simple_message(mc_client->fd, type))
+ xbt_die("Could not send message %i", type);
+}
+
+void MC_client_handle_messages(void)
+{
+ while (1) {
+ XBT_DEBUG("Waiting messages from model-checker");
+
+ char message_buffer[MC_MESSAGE_LENGTH];
+ ssize_t s;
+ if ((s = MC_receive_message(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) < 0)
+ xbt_die("Could not receive commands from the model-checker");
+
+ s_mc_message_t message;
+ if ((size_t) s < sizeof(message))
+ xbt_die("Received message is too small");
+ memcpy(&message, message_buffer, sizeof(message));
+ switch (message.type) {
+
+ case MC_MESSAGE_DEADLOCK_CHECK:
+ {
+ int result = MC_deadlock_check();
+ s_mc_int_message_t answer;
+ answer.type = MC_MESSAGE_DEADLOCK_CHECK_REPLY;
+ answer.value = result;
+ if (MC_protocol_send(mc_client->fd, &answer, sizeof(answer)))
+ xbt_die("Could not send response");
+ }
+ break;
+
+ case MC_MESSAGE_CONTINUE:
+ return;
+
+ case MC_MESSAGE_SIMCALL_HANDLE:
+ {
+ s_mc_simcall_handle_message_t message;
+ if (s != sizeof(message))
+ xbt_die("Unexpected size for SIMCALL_HANDLE");
+ memcpy(&message, message_buffer, sizeof(message));
+ smx_process_t process = SIMIX_process_from_PID(message.pid);
+ if (!process)
+ xbt_die("Invalid pid %lu", (unsigned long) message.pid);
+ SIMIX_simcall_handle(&process->simcall, message.value);
+ MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
+ }
+ break;
+
+ default:
+ xbt_die("%s received unexpected message %s (%i)",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(message.type),
+ message.type
+ );
+ }
+ }
+}
+
+void MC_client_main_loop(void)
+{
+ while (1) {
+ MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
+ MC_client_handle_messages();
+ MC_wait_for_requests();
+ }
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_CLIENT_H
+#define MC_CLIENT_H
+
+#include <xbt/misc.h>
+#include "mc_protocol.h"
+
+SG_BEGIN_DECL()
+
+typedef struct s_mc_client {
+ int active;
+ int fd;
+} s_mc_client_t, *mc_client_t;
+
+extern XBT_INTERNAL mc_client_t mc_client;
+
+XBT_INTERNAL void MC_client_init(void);
+XBT_INTERNAL void MC_client_hello(void);
+XBT_INTERNAL void MC_client_handle_messages(void);
+XBT_INTERNAL void MC_client_send_message(void* message, size_t size);
+XBT_INTERNAL void MC_client_send_simple_message(e_mc_message_type type);
+
+#ifdef HAVE_MC
+void MC_ignore(void* addr, size_t size);
+#endif
+
+void MC_client_main_loop(void);
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+/* Copyright (c) 2008-2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/log.h>
+#include <xbt/fifo.h>
+#include <xbt/sysdep.h>
+#include <simgrid/modelchecker.h>
+
+#include "mc_record.h"
+#include "mc_private.h"
+#include "mc_mmalloc.h"
+#include "mc_ignore.h"
+#include "mc_protocol.h"
+#include "mc_client.h"
+#include "ModelChecker.hpp"
+
+extern "C" {
+
+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) {
+ MC_client_send_simple_message(MC_MESSAGE_ASSERTION_FAILED);
+ MC_client_handle_messages();
+ }
+}
+
+// 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));
+ }
+}
+
+}
#include "mc_safety.h"
#include "mc_private.h"
#include "mc_record.h"
+#include "mc_smx.h"
+#include "mc_client.h"
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_comm_determinism, mc,
"Logging specific to MC communication determinism detection");
/********** Static functions ***********/
-static void comm_pattern_free(mc_comm_pattern_t p)
-{
- xbt_free(p->rdv);
- xbt_free(p->data);
- xbt_free(p);
- p = NULL;
-}
-
-static void list_comm_pattern_free(mc_list_comm_pattern_t l)
-{
- xbt_dynar_free(&(l->list));
- xbt_free(l);
- l = NULL;
-}
-
static e_mc_comm_pattern_difference_t compare_comm_pattern(mc_comm_pattern_t comm1, mc_comm_pattern_t comm2) {
if(comm1->type != comm2->type)
return TYPE_DIFF;
if (comm1->data_size != comm2->data_size)
return DATA_SIZE_DIFF;
if(comm1->data == NULL && comm2->data == NULL)
- return 0;
+ return NONE_DIFF;
if(comm1->data != NULL && comm2->data !=NULL) {
if (!memcmp(comm1->data, comm2->data, comm1->data_size))
- return 0;
+ return NONE_DIFF;
return DATA_DIFF;
}else{
return DATA_DIFF;
}
- return 0;
+ return NONE_DIFF;
}
static char* print_determinism_result(e_mc_comm_pattern_difference_t diff, int process, mc_comm_pattern_t comm, unsigned int cursor) {
return res;
}
-static void update_comm_pattern(mc_comm_pattern_t comm_pattern, smx_synchro_t comm)
+static void update_comm_pattern(mc_comm_pattern_t comm_pattern, smx_synchro_t comm_addr)
{
- void *addr_pointed;
- comm_pattern->src_proc = comm->comm.src_proc->pid;
- comm_pattern->dst_proc = comm->comm.dst_proc->pid;
- comm_pattern->src_host = simcall_host_get_name(comm->comm.src_proc->smx_host);
- comm_pattern->dst_host = simcall_host_get_name(comm->comm.dst_proc->smx_host);
- if (comm_pattern->data_size == -1 && comm->comm.src_buff != NULL) {
- comm_pattern->data_size = *(comm->comm.dst_buff_size);
+ s_smx_synchro_t comm;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &comm, comm_addr, sizeof(comm));
+
+ smx_process_t src_proc = MC_smx_resolve_process(comm.comm.src_proc);
+ smx_process_t dst_proc = MC_smx_resolve_process(comm.comm.dst_proc);
+ comm_pattern->src_proc = src_proc->pid;
+ comm_pattern->dst_proc = dst_proc->pid;
+ comm_pattern->src_host = MC_smx_process_get_host_name(src_proc);
+ comm_pattern->dst_host = MC_smx_process_get_host_name(dst_proc);
+ if (comm_pattern->data_size == -1 && comm.comm.src_buff != NULL) {
+ size_t buff_size;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &buff_size, comm.comm.dst_buff_size, sizeof(buff_size));
+ comm_pattern->data_size = 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)
- memcpy(comm_pattern->data, addr_pointed, comm_pattern->data_size);
- else
- memcpy(comm_pattern->data, comm->comm.src_buff, comm_pattern->data_size);
+ MC_process_read_simple(&mc_model_checker->process(),
+ comm_pattern->data, comm.comm.src_buff, comm_pattern->data_size);
}
}
static void deterministic_comm_pattern(int process, mc_comm_pattern_t comm, int backtracking) {
- mc_list_comm_pattern_t list_comm_pattern = (mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, process, mc_list_comm_pattern_t);
+ mc_list_comm_pattern_t list =
+ xbt_dynar_get_as(initial_communications_pattern, process, mc_list_comm_pattern_t);
if(!backtracking){
- mc_comm_pattern_t initial_comm = xbt_dynar_get_as(list_comm_pattern->list, list_comm_pattern->index_comm, mc_comm_pattern_t);
- e_mc_comm_pattern_difference_t diff;
-
- if((diff = compare_comm_pattern(initial_comm, comm)) != NONE_DIFF){
+ mc_comm_pattern_t initial_comm =
+ xbt_dynar_get_as(list->list, list->index_comm, mc_comm_pattern_t);
+ e_mc_comm_pattern_difference_t diff =
+ compare_comm_pattern(initial_comm, comm);
+
+ if (diff != NONE_DIFF) {
if (comm->type == SIMIX_COMM_SEND){
initial_global_state->send_deterministic = 0;
if(initial_global_state->send_diff != NULL)
xbt_free(initial_global_state->send_diff);
- initial_global_state->send_diff = print_determinism_result(diff, process, comm, list_comm_pattern->index_comm + 1);
+ initial_global_state->send_diff = print_determinism_result(diff, process, comm, list->index_comm + 1);
}else{
initial_global_state->recv_deterministic = 0;
if(initial_global_state->recv_diff != NULL)
xbt_free(initial_global_state->recv_diff);
- initial_global_state->recv_diff = print_determinism_result(diff, process, comm, list_comm_pattern->index_comm + 1);
+ initial_global_state->recv_diff = print_determinism_result(diff, process, comm, list->index_comm + 1);
}
if(_sg_mc_send_determinism && !initial_global_state->send_deterministic){
XBT_INFO("*********************************************************");
}
}
- comm_pattern_free(comm);
+ MC_comm_pattern_free(comm);
}
/********** Non Static functions ***********/
-void comm_pattern_free_voidp(void *p) {
- comm_pattern_free((mc_comm_pattern_t) * (void **) p);
-}
-
-void list_comm_pattern_free_voidp(void *p) {
- list_comm_pattern_free((mc_list_comm_pattern_t) * (void **) p);
-}
-
-void get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, e_mc_call_type_t call_type, int backtracking)
+void MC_get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, e_mc_call_type_t call_type, int backtracking)
{
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(request);
+ mc_list_comm_pattern_t initial_pattern = xbt_dynar_get_as(
+ initial_communications_pattern, issuer->pid, mc_list_comm_pattern_t);
+ xbt_dynar_t incomplete_pattern = xbt_dynar_get_as(
+ incomplete_communications_pattern, issuer->pid, xbt_dynar_t);
- mc_comm_pattern_t pattern = NULL;
- pattern = xbt_new0(s_mc_comm_pattern_t, 1);
+ mc_comm_pattern_t pattern = xbt_new0(s_mc_comm_pattern_t, 1);
pattern->data_size = -1;
pattern->data = NULL;
-
- void *addr_pointed;
-
+ pattern->index =
+ initial_pattern->index_comm + xbt_dynar_length(incomplete_pattern);
+
if (call_type == MC_CALL_TYPE_SEND) {
/* Create comm pattern */
pattern->type = SIMIX_COMM_SEND;
- pattern->comm = simcall_comm_isend__get__result(request);
- pattern->rdv = (pattern->comm->comm.rdv != NULL) ? strdup(pattern->comm->comm.rdv->name) : strdup(pattern->comm->comm.rdv_cpy->name);
- pattern->src_proc = pattern->comm->comm.src_proc->pid;
- pattern->src_host = simcall_host_get_name(request->issuer->smx_host);
- pattern->tag = ((MPI_Request)simcall_comm_isend__get__data(request))->tag;
- if(pattern->comm->comm.src_buff != NULL){
- pattern->data_size = pattern->comm->comm.src_buff_size;
+ pattern->comm_addr = simcall_comm_isend__get__result(request);
+
+ s_smx_synchro_t synchro;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &synchro, pattern->comm_addr, sizeof(synchro));
+
+ char* remote_name;
+ MC_process_read_simple(&mc_model_checker->process(), &remote_name,
+ synchro.comm.rdv ? &synchro.comm.rdv->name : &synchro.comm.rdv_cpy->name,
+ sizeof(remote_name));
+ pattern->rdv =
+ MC_process_read_string(&mc_model_checker->process(), remote_name);
+ pattern->src_proc = MC_smx_resolve_process(synchro.comm.src_proc)->pid;
+ pattern->src_host = MC_smx_process_get_host_name(issuer);
+
+ struct s_smpi_mpi_request mpi_request;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &mpi_request, (MPI_Request) simcall_comm_isend__get__data(request),
+ sizeof(mpi_request));
+ pattern->tag = mpi_request.tag;
+
+ if(synchro.comm.src_buff != NULL){
+ pattern->data_size = synchro.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)
- memcpy(pattern->data, addr_pointed, pattern->data_size);
- else
- memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size);
+ MC_process_read_simple(&mc_model_checker->process(),
+ pattern->data, synchro.comm.src_buff, pattern->data_size);
}
- if(((MPI_Request)simcall_comm_isend__get__data(request))->detached){
+ if(mpi_request.detached){
if (!initial_global_state->initial_communications_pattern_done) {
/* Store comm pattern */
- xbt_dynar_push(((mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, pattern->src_proc, mc_list_comm_pattern_t))->list, &pattern);
+ xbt_dynar_push(
+ xbt_dynar_get_as(
+ initial_communications_pattern, pattern->src_proc, mc_list_comm_pattern_t
+ )->list,
+ &pattern);
} else {
/* Evaluate comm determinism */
deterministic_comm_pattern(pattern->src_proc, pattern, backtracking);
- ((mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, pattern->src_proc, mc_list_comm_pattern_t))->index_comm++;
+ xbt_dynar_get_as(
+ initial_communications_pattern, pattern->src_proc, mc_list_comm_pattern_t
+ )->index_comm++;
}
return;
}
} else if (call_type == MC_CALL_TYPE_RECV) {
pattern->type = SIMIX_COMM_RECEIVE;
- pattern->comm = simcall_comm_irecv__get__result(request);
- pattern->tag = ((MPI_Request)simcall_comm_irecv__get__data(request))->tag;
- pattern->rdv = (pattern->comm->comm.rdv != NULL) ? strdup(pattern->comm->comm.rdv->name) : strdup(pattern->comm->comm.rdv_cpy->name);
- pattern->dst_proc = pattern->comm->comm.dst_proc->pid;
- pattern->dst_host = simcall_host_get_name(request->issuer->smx_host);
+ pattern->comm_addr = simcall_comm_irecv__get__result(request);
+
+ struct s_smpi_mpi_request mpi_request;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &mpi_request, (MPI_Request) simcall_comm_irecv__get__data(request),
+ sizeof(mpi_request));
+ pattern->tag = mpi_request.tag;
+
+ s_smx_synchro_t synchro;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &synchro, pattern->comm_addr, sizeof(synchro));
+
+ char* remote_name;
+ MC_process_read_simple(&mc_model_checker->process(), &remote_name,
+ synchro.comm.rdv ? &synchro.comm.rdv->name : &synchro.comm.rdv_cpy->name,
+ sizeof(remote_name));
+ pattern->rdv =
+ MC_process_read_string(&mc_model_checker->process(), remote_name);
+ pattern->dst_proc = MC_smx_resolve_process(synchro.comm.dst_proc)->pid;
+ pattern->dst_host = MC_smx_process_get_host_name(issuer);
} else {
xbt_die("Unexpected call_type %i", (int) call_type);
}
- xbt_dynar_push((xbt_dynar_t)xbt_dynar_get_as(incomplete_communications_pattern, request->issuer->pid, xbt_dynar_t), &pattern);
+ xbt_dynar_push(
+ xbt_dynar_get_as(incomplete_communications_pattern, issuer->pid, xbt_dynar_t),
+ &pattern);
- XBT_DEBUG("Insert incomplete comm pattern %p for process %lu", pattern, request->issuer->pid);
+ XBT_DEBUG("Insert incomplete comm pattern %p for process %lu", pattern, issuer->pid);
}
-void complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm, unsigned int issuer, int backtracking) {
-
+void MC_complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm_addr, unsigned int issuer, int backtracking) {
mc_comm_pattern_t current_comm_pattern;
unsigned int cursor = 0;
mc_comm_pattern_t comm_pattern;
int completed = 0;
/* Complete comm pattern */
- xbt_dynar_foreach((xbt_dynar_t)xbt_dynar_get_as(incomplete_communications_pattern, issuer, xbt_dynar_t), cursor, current_comm_pattern) {
- if (current_comm_pattern-> comm == comm) {
- update_comm_pattern(current_comm_pattern, comm);
+ xbt_dynar_foreach(xbt_dynar_get_as(incomplete_communications_pattern, issuer, xbt_dynar_t), cursor, current_comm_pattern) {
+ if (current_comm_pattern->comm_addr == comm_addr) {
+ update_comm_pattern(current_comm_pattern, comm_addr);
completed = 1;
- xbt_dynar_remove_at((xbt_dynar_t)xbt_dynar_get_as(incomplete_communications_pattern, issuer, xbt_dynar_t), cursor, &comm_pattern);
+ xbt_dynar_remove_at(
+ xbt_dynar_get_as(incomplete_communications_pattern, issuer, xbt_dynar_t),
+ cursor, &comm_pattern);
XBT_DEBUG("Remove incomplete comm pattern for process %u at cursor %u", issuer, cursor);
break;
}
if(!completed)
xbt_die("Corresponding communication not found!");
+ mc_list_comm_pattern_t pattern = xbt_dynar_get_as(
+ initial_communications_pattern, issuer, mc_list_comm_pattern_t);
+
if (!initial_global_state->initial_communications_pattern_done) {
/* Store comm pattern */
- xbt_dynar_push(((mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, issuer, mc_list_comm_pattern_t))->list, &comm_pattern);
+ xbt_dynar_push(pattern->list, &comm_pattern);
} else {
/* Evaluate comm determinism */
deterministic_comm_pattern(issuer, comm_pattern, backtracking);
- ((mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, issuer, mc_list_comm_pattern_t))->index_comm++;
+ pattern->index_comm++;
}
}
/************************ Main algorithm ************************/
-void MC_pre_modelcheck_comm_determinism(void)
-{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
+static void MC_modelcheck_comm_determinism_main(void);
+static void MC_pre_modelcheck_comm_determinism(void)
+{
mc_state_t initial_state = NULL;
smx_process_t process;
int i;
-
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
+ const int maxpid = MC_smx_get_maxpid();
if (_sg_mc_visited > 0)
visited_states = xbt_dynar_new(sizeof(mc_visited_state_t), visited_state_free_voidp);
- initial_communications_pattern = xbt_dynar_new(sizeof(mc_list_comm_pattern_t), list_comm_pattern_free_voidp);
- for (i=0; i<simix_process_maxpid; i++){
+ // Create initial_communications_pattern elements:
+ initial_communications_pattern = xbt_dynar_new(sizeof(mc_list_comm_pattern_t), MC_list_comm_pattern_free_voidp);
+ for (i=0; i < maxpid; i++){
mc_list_comm_pattern_t process_list_pattern = xbt_new0(s_mc_list_comm_pattern_t, 1);
- process_list_pattern->list = xbt_dynar_new(sizeof(mc_comm_pattern_t), comm_pattern_free_voidp);
+ process_list_pattern->list = xbt_dynar_new(sizeof(mc_comm_pattern_t), MC_comm_pattern_free_voidp);
process_list_pattern->index_comm = 0;
xbt_dynar_insert_at(initial_communications_pattern, i, &process_list_pattern);
}
+
+ // Create incomplete_communications_pattern elements:
incomplete_communications_pattern = xbt_dynar_new(sizeof(xbt_dynar_t), xbt_dynar_free_voidp);
- for (i=0; i<simix_process_maxpid; i++){
+ for (i=0; i < maxpid; i++){
xbt_dynar_t process_pattern = xbt_dynar_new(sizeof(mc_comm_pattern_t), NULL);
xbt_dynar_insert_at(incomplete_communications_pattern, i, &process_pattern);
}
initial_state = MC_state_new();
- MC_SET_STD_HEAP;
XBT_DEBUG("********* Start communication determinism verification *********");
/* Wait for requests (schedules processes) */
MC_wait_for_requests();
- MC_SET_MC_HEAP;
-
/* Get an enabled process and insert it in the interleave set of the initial state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(initial_state, process);
}
- }
+ );
xbt_fifo_unshift(mc_stack, initial_state);
-
- MC_SET_STD_HEAP;
-
}
-void MC_modelcheck_comm_determinism(void)
+static void MC_modelcheck_comm_determinism_main(void)
{
char *req_str = NULL;
&& (req = MC_state_get_request(state, &value))
&& (visited_state == NULL)) {
- req_str = MC_request_to_string(req, value);
- XBT_DEBUG("Execute: %s", req_str);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_SIMIX);
+ XBT_DEBUG("Execute: %s", req_str);
xbt_free(req_str);
if (dot_output != NULL) {
- MC_SET_MC_HEAP;
req_str = MC_request_get_dot_output(req, value);
- MC_SET_STD_HEAP;
}
MC_state_set_executed_request(state, req, value);
/* TODO : handle test and testany simcalls */
e_mc_call_type_t call = MC_CALL_TYPE_NONE;
if (_sg_mc_comms_determinism || _sg_mc_send_determinism) {
- call = mc_get_call_type(req);
+ call = MC_get_call_type(req);
}
/* Answer the request */
- SIMIX_simcall_handle(req, value); /* After this call req is no longer useful */
+ MC_simcall_handle(req, value); /* After this call req is no longer useful */
- MC_SET_MC_HEAP;
if(!initial_global_state->initial_communications_pattern_done)
- handle_comm_pattern(call, req, value, initial_communications_pattern, 0);
+ MC_handle_comm_pattern(call, req, value, initial_communications_pattern, 0);
else
- handle_comm_pattern(call, req, value, NULL, 0);
- MC_SET_STD_HEAP;
+ MC_handle_comm_pattern(call, req, value, NULL, 0);
/* Wait for requests (schedules processes) */
MC_wait_for_requests();
/* Create the new expanded state */
- MC_SET_MC_HEAP;
-
next_state = MC_state_new();
if ((visited_state = is_visited_state(next_state)) == NULL) {
/* Get enabled processes and insert them in the interleave set of the next state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(next_state, process);
}
- }
+ );
if (dot_output != NULL)
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, next_state->num, req_str);
if (dot_output != NULL)
xbt_free(req_str);
- MC_SET_STD_HEAP;
-
} else {
if (xbt_fifo_size(mc_stack) > _sg_mc_max_depth) {
XBT_DEBUG("There are no more processes to interleave. (depth %d)", xbt_fifo_size(mc_stack));
}
- MC_SET_MC_HEAP;
-
if (!initial_global_state->initial_communications_pattern_done)
initial_global_state->initial_communications_pattern_done = 1;
MC_state_delete(state, !state->in_visited_states ? 1 : 0);
XBT_DEBUG("Delete state %d at depth %d", state->num, xbt_fifo_size(mc_stack) + 1);
- MC_SET_STD_HEAP;
-
visited_state = NULL;
/* Check for deadlocks */
return;
}
- MC_SET_MC_HEAP;
-
- while ((state = xbt_fifo_shift(mc_stack)) != NULL) {
+ while ((state = (mc_state_t) xbt_fifo_shift(mc_stack)) != NULL) {
if (MC_state_interleave_size(state) && xbt_fifo_size(mc_stack) < _sg_mc_max_depth) {
/* We found a back-tracking point, let's loop */
XBT_DEBUG("Back-tracking to state %d at depth %d", state->num, xbt_fifo_size(mc_stack) + 1);
xbt_fifo_unshift(mc_stack, state);
- MC_SET_STD_HEAP;
MC_replay(mc_stack);
MC_state_delete(state, !state->in_visited_states ? 1 : 0);
}
}
-
- MC_SET_STD_HEAP;
}
}
MC_print_statistics(mc_stats);
- MC_SET_STD_HEAP;
+ exit(0);
+}
+
+void MC_modelcheck_comm_determinism(void)
+{
+ XBT_INFO("Check communication determinism");
+ mc_reduce_kind = e_mc_reduce_none;
+ MC_wait_for_requests();
+
+ if (mc_mode == MC_MODE_CLIENT) {
+ // This will move somehwere else:
+ MC_client_handle_messages();
+ }
+
+ /* Create exploration stack */
+ mc_stack = xbt_fifo_new();
+
+ MC_pre_modelcheck_comm_determinism();
+
+ initial_global_state = xbt_new0(s_mc_global_t, 1);
+ initial_global_state->snapshot = MC_take_snapshot(0);
+ initial_global_state->initial_communications_pattern_done = 0;
+ initial_global_state->recv_deterministic = 1;
+ initial_global_state->send_deterministic = 1;
+ initial_global_state->recv_diff = NULL;
+ initial_global_state->send_diff = NULL;
+
+ MC_modelcheck_comm_determinism_main();
+}
- return;
}
--- /dev/null
+/* Copyright (c) 2007-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 <string.h>
+
+#include <xbt/sysdep.h>
+#include <xbt/dynar.h>
+
+#include "mc_comm_pattern.h"
+#include "mc_smx.h"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_comm_pattern, mc,
+ "Logging specific to MC communication patterns");
+
+mc_comm_pattern_t MC_comm_pattern_dup(mc_comm_pattern_t comm)
+{
+ mc_comm_pattern_t res = xbt_new0(s_mc_comm_pattern_t, 1);
+ res->index = comm->index;
+ res->type = comm->type;
+ res->comm_addr = comm->comm_addr;
+ res->rdv = strdup(comm->rdv);
+ res->data_size = -1;
+ res->data = NULL;
+ if (comm->type == SIMIX_COMM_SEND) {
+ res->src_proc = comm->src_proc;
+ res->src_host = comm->src_host;
+ if (comm->data != NULL) {
+ res->data_size = comm->data_size;
+ res->data = xbt_malloc0(comm->data_size);
+ memcpy(res->data, comm->data, comm->data_size);
+ }
+ } else {
+ res->dst_proc = comm->dst_proc;
+ res->dst_host = comm->dst_host;
+ }
+ return res;
+}
+
+xbt_dynar_t MC_comm_patterns_dup(xbt_dynar_t patterns)
+{
+ xbt_dynar_t res = xbt_dynar_new(sizeof(mc_comm_pattern_t), MC_comm_pattern_free_voidp);
+
+ mc_comm_pattern_t comm;
+ unsigned int cursor;
+ xbt_dynar_foreach(patterns, cursor, comm) {
+ mc_comm_pattern_t copy_comm = MC_comm_pattern_dup(comm);
+ xbt_dynar_push(res, ©_comm);
+ }
+
+ return res;
+}
+
+static void MC_patterns_copy(xbt_dynar_t dest, xbt_dynar_t source)
+{
+ xbt_dynar_reset(dest);
+
+ unsigned int cursor;
+ mc_comm_pattern_t comm;
+ xbt_dynar_foreach(source, cursor, comm) {
+ mc_comm_pattern_t copy_comm = MC_comm_pattern_dup(comm);
+ xbt_dynar_push(dest, ©_comm);
+ }
+}
+
+void MC_restore_communications_pattern(mc_state_t state)
+{
+ mc_list_comm_pattern_t list_process_comm;
+ unsigned int cursor;
+
+ xbt_dynar_foreach(initial_communications_pattern, cursor, list_process_comm){
+ list_process_comm->index_comm = (int)xbt_dynar_get_as(state->index_comm, cursor, int);
+ }
+
+ for (unsigned i = 0; i < MC_smx_get_maxpid(); i++) {
+ MC_patterns_copy(
+ xbt_dynar_get_as(incomplete_communications_pattern, i, xbt_dynar_t),
+ xbt_dynar_get_as(state->incomplete_comm_pattern, i, xbt_dynar_t)
+ );
+ }
+}
+
+void MC_state_copy_incomplete_communications_pattern(mc_state_t state)
+{
+ state->incomplete_comm_pattern = xbt_dynar_new(sizeof(xbt_dynar_t), xbt_dynar_free_voidp);
+
+ for (unsigned i=0; i < MC_smx_get_maxpid(); i++) {
+ xbt_dynar_t comms = xbt_dynar_get_as(incomplete_communications_pattern, i, xbt_dynar_t);
+ xbt_dynar_t copy = MC_comm_patterns_dup(comms);
+ xbt_dynar_insert_at(state->incomplete_comm_pattern, i, ©);
+ }
+}
+
+void MC_state_copy_index_communications_pattern(mc_state_t state)
+{
+ state->index_comm = xbt_dynar_new(sizeof(unsigned int), NULL);
+ mc_list_comm_pattern_t list_process_comm;
+ unsigned int cursor;
+ xbt_dynar_foreach(initial_communications_pattern, cursor, list_process_comm){
+ xbt_dynar_push_as(state->index_comm, unsigned int, list_process_comm->index_comm);
+ }
+}
+
+void MC_handle_comm_pattern(
+ e_mc_call_type_t call_type, smx_simcall_t req,
+ int value, xbt_dynar_t pattern, int backtracking)
+{
+
+ switch(call_type) {
+ case MC_CALL_TYPE_NONE:
+ break;
+ case MC_CALL_TYPE_SEND:
+ case MC_CALL_TYPE_RECV:
+ MC_get_comm_pattern(pattern, req, call_type, backtracking);
+ break;
+ case MC_CALL_TYPE_WAIT:
+ case MC_CALL_TYPE_WAITANY:
+ {
+ smx_synchro_t comm_addr = NULL;
+ if (call_type == MC_CALL_TYPE_WAIT)
+ comm_addr = simcall_comm_wait__get__comm(req);
+ else
+ // comm_addr = REMOTE(xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value, smx_synchro_t)):
+ MC_process_read_dynar_element(&mc_model_checker->process(), &comm_addr,
+ simcall_comm_waitany__get__comms(req), value, sizeof(comm_addr));
+ MC_complete_comm_pattern(pattern, comm_addr,
+ MC_smx_simcall_get_issuer(req)->pid, backtracking);
+ }
+ break;
+ default:
+ xbt_die("Unexpected call type %i", (int)call_type);
+ }
+
+}
+
+void MC_comm_pattern_free(mc_comm_pattern_t p)
+{
+ xbt_free(p->rdv);
+ xbt_free(p->data);
+ xbt_free(p);
+ p = NULL;
+}
+
+static void MC_list_comm_pattern_free(mc_list_comm_pattern_t l)
+{
+ xbt_dynar_free(&(l->list));
+ xbt_free(l);
+ l = NULL;
+}
+
+void MC_comm_pattern_free_voidp(void *p)
+{
+ MC_comm_pattern_free((mc_comm_pattern_t) * (void **) p);
+}
+
+void MC_list_comm_pattern_free_voidp(void *p)
+{
+ MC_list_comm_pattern_free((mc_list_comm_pattern_t) * (void **) p);
+}
+
+}
#include "../smpi/private.h"
#include <smpi/smpi.h>
+#include "mc_state.h"
+
#ifndef MC_COMM_PATTERN_H
#define MC_COMM_PATTERN_H
typedef struct s_mc_comm_pattern{
int num;
- smx_synchro_t comm;
+ smx_synchro_t comm_addr;
e_smx_comm_type_t type;
unsigned long src_proc;
unsigned long dst_proc;
xbt_dynar_t list;
}s_mc_list_comm_pattern_t, *mc_list_comm_pattern_t;
-extern xbt_dynar_t initial_communications_pattern;
-extern xbt_dynar_t incomplete_communications_pattern;
+/**
+ * Type: `xbt_dynar_t<mc_list_comm_pattenr_t>`
+ */
+extern XBT_INTERNAL xbt_dynar_t initial_communications_pattern;
+
+/**
+ * Type: `xbt_dynar_t<xbt_dynar_t<mc_comm_pattern_t>>`
+ */
+extern XBT_INTERNAL xbt_dynar_t incomplete_communications_pattern;
typedef enum {
MC_CALL_TYPE_NONE,
DATA_DIFF,
} e_mc_comm_pattern_difference_t;
-static inline e_mc_call_type_t mc_get_call_type(smx_simcall_t req)
+static inline e_mc_call_type_t MC_get_call_type(smx_simcall_t req)
{
switch(req->call) {
case SIMCALL_COMM_ISEND:
}
}
-void get_comm_pattern(xbt_dynar_t communications_pattern, smx_simcall_t request, e_mc_call_type_t call_type, int backtracking);
-void handle_comm_pattern(e_mc_call_type_t call_type, smx_simcall_t request, int value, xbt_dynar_t current_pattern, int backtracking);
-void comm_pattern_free_voidp(void *p);
-void list_comm_pattern_free_voidp(void *p);
-void complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm, unsigned int issuer, int backtracking);
-void MC_pre_modelcheck_comm_determinism(void);
+XBT_INTERNAL void MC_get_comm_pattern(xbt_dynar_t communications_pattern, smx_simcall_t request, e_mc_call_type_t call_type, int backtracking);
+XBT_INTERNAL void MC_handle_comm_pattern(e_mc_call_type_t call_type, smx_simcall_t request, int value, xbt_dynar_t current_pattern, int backtracking);
+XBT_INTERNAL void MC_comm_pattern_free_voidp(void *p);
+XBT_INTERNAL void MC_list_comm_pattern_free_voidp(void *p);
+XBT_INTERNAL void MC_complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm_addr, unsigned int issuer, int backtracking);
void MC_modelcheck_comm_determinism(void);
+XBT_INTERNAL void MC_restore_communications_pattern(mc_state_t state);
+
+XBT_INTERNAL mc_comm_pattern_t MC_comm_pattern_dup(mc_comm_pattern_t comm);
+XBT_INTERNAL xbt_dynar_t MC_comm_patterns_dup(xbt_dynar_t state);
+
+XBT_INTERNAL void MC_state_copy_incomplete_communications_pattern(mc_state_t state);
+XBT_INTERNAL void MC_state_copy_index_communications_pattern(mc_state_t state);
+
+XBT_INTERNAL void MC_comm_pattern_free(mc_comm_pattern_t p);
+
SG_END_DECL()
#endif
* under the terms of the license (GNU LGPL) which comes with this package. */
#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
+#include <cinttypes>
#include <boost/unordered_set.hpp>
+#include <xbt/sysdep.h>
+
#include "internal_config.h"
#include "mc_object_info.h"
#include "mc_safety.h"
#include "mc_liveness.h"
#include "mc_private.h"
+#include "mc_smx.h"
#ifdef HAVE_SMPI
#include "smpi/private.h"
#include <xbt/probes.h>
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_compare, mc,
- "Logging specific to mc_compare");
-
typedef struct s_pointers_pair {
void *p1;
void *p2;
extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_compare, xbt,
+ "Logging specific to mc_compare in mc");
+
/************************** Free functions ****************************/
/********************************************************************/
static void stack_region_free(stack_region_t s)
{
if (s) {
- xbt_free(s->process_name);
xbt_free(s);
}
}
void* real_area2, mc_snapshot_t snapshot2, mc_mem_region_t region2,
dw_type_t type, int pointer_level)
{
+ mc_process_t process = &mc_model_checker->process();
+
unsigned int cursor = 0;
dw_type_t member, subtype, subsubtype;
int elm_size, i, res;
case DW_TAG_enumeration_type:
case DW_TAG_union_type:
{
- return mc_snapshot_region_memcmp(
+ return MC_snapshot_region_memcmp(
real_area1, region1, real_area2, region2,
type->byte_size) != 0;
}
case DW_TAG_reference_type:
case DW_TAG_rvalue_reference_type:
{
- void* addr_pointed1 = mc_snapshot_read_pointer_region(real_area1, region1);
- void* addr_pointed2 = mc_snapshot_read_pointer_region(real_area2, region2);
+ void* addr_pointed1 = MC_region_read_pointer(region1, real_area1);
+ void* addr_pointed2 = MC_region_read_pointer(region2, real_area2);
if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
return (addr_pointed1 != addr_pointed2);
// * a pointer leads to the read-only segment of the current object;
// * a pointer lead to a different ELF object.
- if (addr_pointed1 > std_heap
+ if (addr_pointed1 > process->heap_address
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)) {
if (!
- (addr_pointed2 > std_heap
+ (addr_pointed2 > process->heap_address
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
return 1;
// The pointers are both in the heap:
case DW_TAG_class_type:
xbt_dynar_foreach(type->members, cursor, member) {
void *member1 =
- mc_member_resolve(real_area1, type, member, snapshot1, process_index);
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
void *member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, process_index, region1);
mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, process_index, region2);
res =
mc_snapshot_t snapshot2)
{
xbt_assert(r1 && r2, "Missing region.");
+
+#ifdef HAVE_SMPI
+ if (r1->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ xbt_assert(process_index >= 0);
+ if (r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ return 1;
+ }
+
+ size_t process_count = MC_smpi_process_count();
+ xbt_assert(process_count == r1->privatized.regions_count
+ && process_count == r2->privatized.regions_count);
+
+ // Compare the global variables separately for each simulates process:
+ for (size_t process_index = 0; process_index < process_count; process_index++) {
+ int is_diff = compare_global_variables(object_info, process_index,
+ r1->privatized.regions[process_index], r2->privatized.regions[process_index],
+ snapshot1, snapshot2);
+ if (is_diff) return 1;
+ }
+ return 0;
+ }
+#else
+ xbt_assert(r1->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+#endif
+ xbt_assert(r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+
struct mc_compare_state state;
xbt_dynar_t variables;
int snapshot_compare(void *state1, void *state2)
{
+ mc_process_t process = &mc_model_checker->process();
mc_snapshot_t s1, s2;
int num1, num2;
#endif
/* Init heap information used in heap comparison algorithm */
- xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(std_heap, s1, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
- xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(std_heap, s2, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
+ xbt_mheap_t heap1 = (xbt_mheap_t) MC_snapshot_read(
+ s1, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
+ xbt_mheap_t heap2 = (xbt_mheap_t) MC_snapshot_read(
+ s2, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
res_init = init_heap_information(heap1, heap2, s1->to_ignore, s2->to_ignore);
if (res_init == -1) {
#ifdef MC_DEBUG
cursor++;
}
+ size_t regions_count = s1->snapshot_regions_count;
+ // TODO, raise a difference instead?
+ xbt_assert(regions_count == s2->snapshot_regions_count);
+ mc_comp_times->global_variables_comparison_time = 0;
- const char *names[3] = { "?", "libsimgrid", "binary" };
-#ifdef MC_DEBUG
- double *times[3] = {
- NULL,
- &mc_comp_times->libsimgrid_global_variables_comparison_time,
- &mc_comp_times->binary_global_variables_comparison_time
- };
-#endif
+ for (size_t k = 0; k != regions_count; ++k) {
+ mc_mem_region_t region1 = s1->snapshot_regions[k];
+ mc_mem_region_t region2 = s2->snapshot_regions[k];
+
+ // 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);
- mc_object_info_t object_infos[] = { NULL, mc_libsimgrid_info, mc_binary_info };
+ const char* name = region1->object_info->file_name;
- int k = 0;
- for (k = 2; k != 0; --k) {
#ifdef MC_DEBUG
if (is_diff == 0)
xbt_os_walltimer_stop(timer);
#endif
/* Compare global variables */
-#ifdef HAVE_SMPI
- if (object_infos[k] == mc_binary_info && smpi_privatize_global_variables) {
- // Compare the global variables separately for each simulates process:
- for (int process_index = 0; process_index < smpi_process_count(); process_index++) {
- is_diff =
- compare_global_variables(object_infos[k], process_index,
- s1->privatization_regions[process_index], s2->privatization_regions[process_index], s1, s2);
- if (is_diff) break;
- }
- }
- else
-#endif
- is_diff =
- compare_global_variables(object_infos[k], MC_NO_PROCESS_INDEX, s1->regions[k], s2->regions[k], s1, s2);
+ is_diff =
+ compare_global_variables(region1->object_info, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ region1, region2,
+ s1, s2);
if (is_diff != 0) {
XBT_TRACE3(mc, state_diff, num1, num2, "Different global variables");
#ifdef MC_DEBUG
xbt_os_walltimer_stop(timer);
- *times[k] = xbt_os_timer_elapsed(timer);
+ mc_comp_times->global_variables_comparison_time
+ += xbt_os_timer_elapsed(timer);
XBT_DEBUG("(%d - %d) Different global variables in %s", num1, num2,
- names[k]);
+ name);
errors++;
#else
#ifdef MC_VERBOSE
XBT_VERB("(%d - %d) Different global variables in %s", num1, num2,
- names[k]);
+ name);
#endif
reset_heap_information();
XBT_DEBUG("- Nb processes : %f", mc_comp_times->nb_processes_comparison_time);
XBT_DEBUG("- Nb bytes used : %f", mc_comp_times->bytes_used_comparison_time);
XBT_DEBUG("- Stacks sizes : %f", mc_comp_times->stacks_sizes_comparison_time);
- XBT_DEBUG("- Binary global variables : %f",
- mc_comp_times->binary_global_variables_comparison_time);
- XBT_DEBUG("- Libsimgrid global variables : %f",
- mc_comp_times->libsimgrid_global_variables_comparison_time);
+ XBT_DEBUG("- GLobal variables : %f", mc_comp_times->global_variables_comparison_time);
XBT_DEBUG("- Heap : %f", mc_comp_times->heap_comparison_time);
XBT_DEBUG("- Stacks : %f", mc_comp_times->stacks_comparison_time);
}
-/**************************** MC snapshot compare simcall **************************/
-/***********************************************************************************/
-
-int simcall_HANDLER_mc_compare_snapshots(smx_simcall_t simcall,
- mc_snapshot_t s1, mc_snapshot_t s2)
-{
- return snapshot_compare(s1, s2);
-}
-
-int MC_compare_snapshots(void *s1, void *s2)
-{
-
- return simcall_mc_compare_snapshots(s1, s2);
-
-}
-
}
#include <xbt/config.h>
#include <mc/mc.h>
+#include "mc/mc_replay.h"
#include <simgrid/sg_config.h>
#include "mc_record.h"
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_config, mc,
"Configuration of MC");
int _sg_do_model_check_record = 0;
int _sg_mc_checkpoint = 0;
int _sg_mc_sparse_checkpoint = 0;
-int _sg_mc_soft_dirty = 0;
char *_sg_mc_property_file = NULL;
int _sg_mc_hash = 0;
int _sg_mc_max_depth = 1000;
int _sg_mc_send_determinism = 0;
int _sg_mc_safety = 0;
int _sg_mc_liveness = 0;
+int _sg_mc_snapshot_fds = 0;
int _sg_mc_termination = 0;
-
void _mc_cfg_cb_reduce(const char *name, int pos)
{
if (_sg_cfg_init_status && !_sg_do_model_check) {
_sg_mc_sparse_checkpoint = xbt_cfg_get_boolean(_sg_cfg_set, name);
}
-void _mc_cfg_cb_soft_dirty(const char *name, int pos) {
- if (_sg_cfg_init_status && !_sg_do_model_check) {
- xbt_die("You are specifying a soft dirty value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
- }
- _sg_mc_soft_dirty = xbt_cfg_get_boolean(_sg_cfg_set, name);
-}
-
void _mc_cfg_cb_property(const char *name, int pos)
{
if (_sg_cfg_init_status && !_sg_do_model_check) {
_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) {
}
#endif
+
+}
#include "mc/mc_private.h"
#include "mc/mc_snapshot.h"
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_diff, xbt,
"Logging specific to mc_diff in mc");
xbt_dynar_t mc_heap_comparison_ignore;
xbt_dynar_t stacks_areas;
-void *maestro_stack_start, *maestro_stack_end;
+
/********************************* Backtrace ***********************************/
/* size_t block, frag_nb; */
/* int type; */
- /* xbt_mheap_t heap = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit(); */
-
/* block = (((char*) (addr) - (char*) heap -> heapbase) / BLOCKSIZE + 1); */
/* type = heap->heapinfo[block].type; */
typedef char *type_name;
struct s_mc_diff {
- /** \brief Base address of the real heap */
- void *s_heap;
+ s_xbt_mheap_t std_heap_copy;
size_t heaplimit;
// Number of blocks in the heaps:
size_t heapsize1, heapsize2;
}
static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
- void *address)
+ const void *address)
{
unsigned int cursor = 0;
return -1;
}
-static int is_stack(void *address)
+static int is_stack(const void *address)
{
unsigned int cursor = 0;
stack_region_t stack;
return -1;
state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
-
- // Mamailloute in order to find the base address of the main heap:
- state->s_heap =
- (char *) mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
+
+ state->std_heap_copy = *MC_process_get_heap(&mc_model_checker->process());
state->heapsize1 = heap1->heapsize;
state->heapsize2 = heap2->heapsize;
state->to_ignore2 = i2;
if (state->heaplimit > state->available) {
- state->equals_to1 =
+ state->equals_to1 = (s_heap_area_t*)
realloc(state->equals_to1,
state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
sizeof(s_heap_area_t));
- state->types1 =
+ state->types1 = (s_dw_type**)
realloc(state->types1,
state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
sizeof(type_name *));
- state->equals_to2 =
+ state->equals_to2 = (s_heap_area_t*)
realloc(state->equals_to2,
state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
sizeof(s_heap_area_t));
- state->types2 =
+ state->types2 = (s_dw_type**)
realloc(state->types2,
state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
sizeof(type_name *));
}
-int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+// TODO, have a robust way to find it in O(1)
+static inline
+mc_mem_region_t MC_get_heap_region(mc_snapshot_t snapshot)
{
+ size_t n = snapshot->snapshot_regions_count;
+ for (size_t i=0; i!=n; ++i) {
+ mc_mem_region_t region = snapshot->snapshot_regions[i];
+ if (region->region_type == MC_REGION_TYPE_HEAP)
+ return region;
+ }
+ xbt_die("No heap region");
+}
+int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+{
+ mc_process_t process = &mc_model_checker->process();
struct s_mc_diff *state = mc_diff_info;
/* Start comparison */
malloc_info heapinfo_temp1, heapinfo_temp2;
malloc_info heapinfo_temp2b;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
+
+ // This is the address of std_heap->heapinfo in the application process:
+ void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
// This is in snapshot do not use them directly:
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, MC_NO_PROCESS_INDEX);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, MC_NO_PROCESS_INDEX);
+ const malloc_info* heapinfos1 = (const malloc_info*) MC_snapshot_read_pointer(snapshot1, heapinfo_address, MC_PROCESS_INDEX_MISSING);
+ const malloc_info* heapinfos2 = (const malloc_info*) 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 = (const malloc_info*) MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = (const malloc_info*) 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 ++;
addr_block1 =
((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ (char *) state->std_heap_copy.heapbase));
if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) { /* Large block */
if (state->equals_to2_(i1, 0).valid == 0) {
- addr_block2 =
- ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ addr_block2 = (ADDR2UINT(i1) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.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) {
while (i2 <= state->heaplimit && !equal) {
- addr_block2 =
- ((void *) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ addr_block2 = (ADDR2UINT(i2) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.heapbase;
if (i2 == i1) {
i2++;
continue;
}
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = (const malloc_info*) MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
if (heapinfo2b->type != MMALLOC_TYPE_UNFRAGMENTED) {
i2++;
}
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
if (state->equals_to2_(i1, j1).valid == 0) {
- addr_block2 =
- ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ addr_block2 = (ADDR2UINT(i1) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.heapbase;
addr_frag2 =
(void *) ((char *) addr_block2 +
(j1 << heapinfo2->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1)
while (i2 <= state->heaplimit && !equal) {
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = (const malloc_info*) MC_region_read(
+ heap_region2, &heapinfo_temp2b, &heapinfos2[i2],
+ sizeof(malloc_info));
if (heapinfo2b->type == MMALLOC_TYPE_FREE || heapinfo2b->type == MMALLOC_TYPE_HEAPINFO) {
i2 ++;
if (state->equals_to2_(i2, j2).valid)
continue;
- addr_block2 =
- ((void *) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ addr_block2 = (ADDR2UINT(i2) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.heapbase;
addr_frag2 =
(void *) ((char *) addr_block2 +
(j2 << heapinfo2b->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot2, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot2, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
size_t i = 1, j = 0;
for(i = 1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = (const malloc_info*) MC_region_read(
+ heap_region1, &heapinfo_temp1, &heapinfos1[i], sizeof(malloc_info));
if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo1->busy_block.busy_size > 0) {
XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
for (i=1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo2 = (const malloc_info*) MC_region_read(
+ heap_region2, &heapinfo_temp2, &heapinfos2[i], sizeof(malloc_info));
if (heapinfo2->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo2->busy_block.busy_size > 0) {
* @param check_ignore
*/
static int compare_heap_area_without_type(struct s_mc_diff *state, int process_index,
- void *real_area1, void *real_area2,
+ const void *real_area1, const void *real_area2,
mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2,
xbt_dynar_t previous, int size,
int check_ignore)
{
+ mc_process_t process = &mc_model_checker->process();
int i = 0;
- void *addr_pointed1, *addr_pointed2;
+ const void *addr_pointed1, *addr_pointed2;
int pointer_align, res_compare;
ssize_t ignore1, ignore2;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
while (i < size) {
}
}
- if (mc_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
+ if (MC_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
pointer_align = (i / sizeof(void *)) * sizeof(void *);
- addr_pointed1 = mc_snapshot_read_pointer((char *) real_area1 + pointer_align, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer((char *) real_area2 + pointer_align, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char *) real_area1 + pointer_align, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char *) real_area2 + pointer_align, process_index);
- if (addr_pointed1 > maestro_stack_start
- && addr_pointed1 < maestro_stack_end
- && addr_pointed2 > maestro_stack_start
- && addr_pointed2 < maestro_stack_end) {
+ if (addr_pointed1 > process->maestro_stack_start
+ && addr_pointed1 < process->maestro_stack_end
+ && addr_pointed2 > process->maestro_stack_start
+ && addr_pointed2 < process->maestro_stack_end) {
i = pointer_align + sizeof(void *);
continue;
- } else if (addr_pointed1 > state->s_heap
+ } else if (addr_pointed1 > state->std_heap_copy.heapbase
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
- && addr_pointed2 > state->s_heap
+ && addr_pointed2 > state->std_heap_copy.heapbase
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)) {
// Both addreses are in the heap:
res_compare =
* @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,
}
dw_type_t subtype, subsubtype;
- int res, elm_size, i;
+ int res, elm_size;
unsigned int cursor = 0;
dw_type_t member;
- void *addr_pointed1, *addr_pointed2;;
+ const void *addr_pointed1, *addr_pointed2;;
- mc_mem_region_t heap_region1 = snapshot1->regions[0];
- mc_mem_region_t heap_region2 = snapshot2->regions[0];
+ mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+ mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
switch (type->type) {
case DW_TAG_unspecified_type:
if (real_area1 == real_area2)
return -1;
else
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
} else {
if (area_size != -1 && type->byte_size != area_size)
return -1;
else {
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
}
}
break;
if (area_size != -1 && type->byte_size != area_size)
return -1;
else
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
break;
case DW_TAG_typedef:
case DW_TAG_const_type:
return 0;
break;
}
- for (i = 0; i < type->element_count; i++) {
+ for (int i = 0; i < type->element_count; i++) {
// TODO, add support for variable stride (DW_AT_byte_stride)
res =
compare_heap_area_with_type(state, process_index,
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);
- if (addr_pointed1 > state->s_heap
+ for (size_t i = 0; i < (area_size / sizeof(void *)); i++) {
+ 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->std_heap_copy.heapbase
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
- && addr_pointed2 > state->s_heap
+ && addr_pointed2 > state->std_heap_copy.heapbase
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
res =
compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
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);
- if (addr_pointed1 > state->s_heap
+ 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->std_heap_copy.heapbase
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
- && addr_pointed2 > state->s_heap
+ && addr_pointed2 > state->std_heap_copy.heapbase
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
return compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
snapshot2, previous, type->subtype,
type = type->full_type;
if (area_size != -1 && type->byte_size != area_size) {
if (area_size > type->byte_size && area_size % type->byte_size == 0) {
- for (i = 0; i < (area_size / type->byte_size); i++) {
+ for (size_t i = 0; i < (size_t)(area_size / type->byte_size); i++) {
res =
compare_heap_area_with_type(state, process_index,
(char *) real_area1 + i * type->byte_size,
cursor = 0;
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);
- char *real_member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ void *real_member1 =
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
+ void *real_member2 =
+ 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,
if (member->offset == offset)
return member->subtype;
} else {
- char *real_member =
- mc_member_resolve(real_base_address, type, member, snapshot, process_index);
- if (real_member - (char *) real_base_address == offset)
+ void *real_member =
+ mc_member_resolve(real_base_address, type, member,
+ (mc_address_space_t) snapshot, process_index);
+ if ((char*) real_member - (char *) real_base_address == offset)
return member->subtype;
}
* @param pointer_level
* @return 0 (same), 1 (different), -1
*/
-int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t snapshot1,
+int compare_heap_area(int process_index, const void *area1, const void *area2, mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2, xbt_dynar_t previous,
dw_type_t type, int pointer_level)
{
+ mc_process_t process = &mc_model_checker->process();
struct s_mc_diff *state = mc_diff_info;
int match_pairs = 0;
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, process_index);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, process_index);
+ // This is the address of std_heap->heapinfo in the application process:
+ void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
+
+ const malloc_info* heapinfos1 = (const malloc_info*) MC_snapshot_read_pointer(
+ snapshot1, heapinfo_address, process_index);
+ const malloc_info* heapinfos2 = (const malloc_info*) MC_snapshot_read_pointer(
+ snapshot2, heapinfo_address, process_index);
malloc_info heapinfo_temp1, heapinfo_temp2;
// Get block number:
block1 =
((char *) area1 -
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
+ (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
block2 =
((char *) area2 -
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
+ (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
// If either block is a stack block:
if (is_block_stack((int) block1) && is_block_stack((int) block2)) {
return 0;
}
// If either block is not in the expected area of memory:
- if (((char *) area1 < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
- || (block1 > state->heapsize1) || (block1 < 1)
- || ((char *) area2 < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
- || (block2 > state->heapsize2) || (block2 < 1)) {
+ if (((char *) area1 < (char *) state->std_heap_copy.heapbase)
+ || (block1 > (ssize_t) state->heapsize1) || (block1 < 1)
+ || ((char *) area2 < (char *) state->std_heap_copy.heapbase)
+ || (block2 > (ssize_t) state->heapsize2) || (block2 < 1)) {
if (match_pairs) {
xbt_dynar_free(&previous);
}
}
// Process address of the block:
- real_addr_block1 =
- ((void *) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
- real_addr_block2 =
- ((void *) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE +
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
+ real_addr_block1 = (ADDR2UINT(block1) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.heapbase;
+ real_addr_block2 = (ADDR2UINT(block2) - 1) * BLOCKSIZE +
+ (char *) state->std_heap_copy.heapbase;
if (type) {
}
- 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 = (const malloc_info*) MC_region_read(
+ heap_region1, &heapinfo_temp1, &heapinfos1[block1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = (const malloc_info*) 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)) {
}
if (type_size != -1) {
- if (type_size != heapinfo1->busy_block.busy_size
- && type_size != heapinfo2->busy_block.busy_size
+ if (type_size != (ssize_t) heapinfo1->busy_block.busy_size
+ && type_size != (ssize_t) heapinfo2->busy_block.busy_size
&& (type->name == NULL || !strcmp(type->name, "struct s_smx_context"))) {
if (match_pairs) {
match_equals(state, previous);
block =
((char *) area -
- (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
+ (char *) state->std_heap_copy.heapbase) / BLOCKSIZE + 1;
- if (((char *) area < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
+ if (((char *) area < (char *) state->std_heap_copy.heapbase)
|| (block > state->heapsize1) || (block < 1))
return -1;
/* Heap information */
state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
-
- // Mamailloute in order to find the base address of the main heap:
- state->s_heap =
- (char *) mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
+ state->std_heap_copy = *MC_process_get_heap(&mc_model_checker->process());
state->heapbase1 = (char *) heap1 + BLOCKSIZE;
state->heapbase2 = (char *) heap2 + BLOCKSIZE;
}
#endif
+
+}
/* 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 <cinttypes>
+
#include <stdlib.h>
#define DW_LANG_Objc DW_LANG_ObjC /* fix spelling error in older dwarf.h */
#include <dwarf.h>
#include <elfutils/libdw.h>
-#include <inttypes.h>
#include <simgrid_config.h>
#include <xbt/log.h>
#include "mc_object_info.h"
#include "mc_private.h"
+extern "C" {
+
static void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable);
static void MC_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
static void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
*/
static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace);
+ const char *ns);
/** \brief Process a type DIE
*/
static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace);
+ const char *ns);
/** \brief Calls MC_dwarf_handle_die on all childrend of the given die
*
*/
static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace);
+ const char *ns);
/** \brief Handle a variable (DW_TAG_variable or other)
*
*/
static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace);
+ const char *ns);
/** \brief Get the DW_TAG_type of the DIE
*
* \param tag tag code (see the DWARF specification)
* \return name of the tag
*/
+XBT_INTERNAL
const char *MC_dwarf_tagname(int tag)
{
switch (tag) {
*/
static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
dw_type_t type = xbt_new0(s_dw_type_t, 1);
const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
if (name != NULL) {
type->name =
- namespace ? bprintf("%s%s::%s", prefix, namespace,
+ ns ? bprintf("%s%s::%s", prefix, ns,
name) : bprintf("%s%s", prefix, name);
}
type->dw_type_id = MC_dwarf_at_type(die);
+ // Some compilers do not emit DW_AT_byte_size for pointer_type,
+ // so we fill this. We currently assume that the model-checked process is in
+ // the same architecture..
+ if (type->type == DW_TAG_pointer_type)
+ type->byte_size = sizeof(void*);
+
// Computation of the byte_size;
if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
type->byte_size = MC_dwarf_attr_integrate_uint(die, DW_AT_byte_size, 0);
case DW_TAG_union_type:
case DW_TAG_class_type:
MC_dwarf_add_members(info, die, unit, type);
- char *new_namespace = namespace == NULL ? xbt_strdup(type->name)
- : bprintf("%s::%s", namespace, name);
- MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
- free(new_namespace);
+ char *new_ns = ns == NULL ? xbt_strdup(type->name)
+ : bprintf("%s::%s", ns, name);
+ MC_dwarf_handle_children(info, die, unit, frame, new_ns);
+ free(new_ns);
break;
}
static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
- dw_type_t type = MC_dwarf_die_to_type(info, die, unit, frame, namespace);
+ dw_type_t type = MC_dwarf_die_to_type(info, die, unit, frame, ns);
char *key = bprintf("%" PRIx64, (uint64_t) type->id);
xbt_dict_set(info->types, key, type, NULL);
static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
// Skip declarations:
if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
}
}
- if (namespace && variable->global) {
+ if (ns && variable->global) {
char *old_name = variable->name;
- variable->name = bprintf("%s::%s", namespace, old_name);
+ variable->name = bprintf("%s::%s", ns, old_name);
free(old_name);
}
// The current code needs a variable name,
static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
dw_variable_t variable =
- MC_die_to_variable(info, die, unit, frame, namespace);
+ MC_die_to_variable(info, die, unit, frame, ns);
if (variable == NULL)
return;
MC_dwarf_register_variable(info, frame, variable);
static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t parent_frame,
- const char *namespace)
+ const char *ns)
{
// TODO, handle DW_TAG_type/DW_TAG_location for DW_TAG_with_stmt
int tag = dwarf_tag(die);
if (klass == mc_tag_subprogram) {
const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
frame->name =
- namespace ? bprintf("%s::%s", namespace, name) : xbt_strdup(name);
+ ns ? bprintf("%s::%s", ns, name) : xbt_strdup(name);
}
frame->abstract_origin_id =
xbt_dynar_push(parent_frame->scopes, &frame);
}
// Handle children:
- MC_dwarf_handle_children(info, die, unit, frame, namespace);
+ MC_dwarf_handle_children(info, die, unit, frame, ns);
}
static void mc_dwarf_handle_namespace_die(mc_object_info_t info,
Dwarf_Die * die, Dwarf_Die * unit,
dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
if (frame)
xbt_die("Unexpected namespace in a subprogram");
- char *new_namespace = namespace == NULL ? xbt_strdup(name)
- : bprintf("%s::%s", namespace, name);
- MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
- xbt_free(new_namespace);
+ char *new_ns = ns == NULL ? xbt_strdup(name)
+ : bprintf("%s::%s", ns, name);
+ MC_dwarf_handle_children(info, die, unit, frame, new_ns);
+ xbt_free(new_ns);
}
static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
// For each child DIE:
Dwarf_Die child;
int res;
for (res = dwarf_child(die, &child); res == 0;
res = dwarf_siblingof(&child, &child)) {
- MC_dwarf_handle_die(info, &child, unit, frame, namespace);
+ MC_dwarf_handle_die(info, &child, unit, frame, ns);
}
}
static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
Dwarf_Die * unit, dw_frame_t frame,
- const char *namespace)
+ const char *ns)
{
int tag = dwarf_tag(die);
mc_tag_class klass = MC_dwarf_tag_classify(tag);
// Type:
case mc_tag_type:
- MC_dwarf_handle_type_die(info, die, unit, frame, namespace);
+ MC_dwarf_handle_type_die(info, die, unit, frame, ns);
break;
// Subprogram or scope:
case mc_tag_subprogram:
case mc_tag_scope:
- MC_dwarf_handle_scope_die(info, die, unit, frame, namespace);
+ MC_dwarf_handle_scope_die(info, die, unit, frame, ns);
return;
// Variable:
case mc_tag_variable:
- MC_dwarf_handle_variable_die(info, die, unit, frame, namespace);
+ MC_dwarf_handle_variable_die(info, die, unit, frame, ns);
break;
case mc_tag_namespace:
- mc_dwarf_handle_namespace_die(info, die, unit, frame, namespace);
+ mc_dwarf_handle_namespace_die(info, die, unit, frame, ns);
break;
default:
}
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;
void MC_free_object_info(mc_object_info_t * info)
{
- xbt_free(&(*info)->file_name);
+ xbt_free((*info)->file_name);
xbt_dict_free(&(*info)->subprograms);
xbt_dynar_free(&(*info)->global_variables);
xbt_dict_free(&(*info)->types);
xbt_dict_free(&(*info)->full_types_by_name);
- xbt_free(info);
+ xbt_free(*info);
xbt_dynar_free(&(*info)->functions_index);
*info = NULL;
}
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;
dw_variable_t variable = NULL;
xbt_dynar_foreach(info->global_variables, cursor, variable) {
if (variable->type_origin) {
- variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ variable->type = (dw_type_t) xbt_dict_get_or_null(info->types, variable->type_origin);
}
}
}
// Attach correct namespaced name in inlined subroutine:
char *key = bprintf("%" PRIx64, (uint64_t) scope->abstract_origin_id);
- dw_frame_t abstract_origin = xbt_dict_get_or_null(info->subprograms, key);
+ dw_frame_t abstract_origin = (dw_frame_t) xbt_dict_get_or_null(info->subprograms, key);
xbt_assert(abstract_origin, "Could not lookup abstract origin %s", key);
xbt_free(key);
scope->name = xbt_strdup(abstract_origin->name);
dw_variable_t variable = NULL;
xbt_dynar_foreach(scope->variables, cursor, variable) {
if (variable->type_origin) {
- variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ variable->type = (dw_type_t) xbt_dict_get_or_null(info->types, variable->type_origin);
}
}
if (type->dw_type_id == NULL)
return;
- type->subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ type->subtype = (dw_type_t) xbt_dict_get_or_null(info->types, type->dw_type_id);
if (type->subtype == NULL)
return;
if (type->subtype->byte_size != 0)
// We need to fix in order to support C++.
dw_type_t subtype =
- xbt_dict_get_or_null(info->full_types_by_name, type->subtype->name);
+ (dw_type_t) xbt_dict_get_or_null(info->full_types_by_name, type->subtype->name);
if (subtype != NULL) {
type->subtype = subtype;
}
}
/** \brief Finds informations about a given shared object/executable */
-mc_object_info_t MC_find_object_info(memory_map_t maps, char *name,
+mc_object_info_t MC_find_object_info(memory_map_t maps, const char *name,
int executable)
{
mc_object_info_t result = MC_new_object_info();
MC_dwarf_register_non_global_variable(info, frame, variable);
}
-void MC_post_process_object_info(mc_object_info_t info)
+void MC_post_process_object_info(mc_process_t process, mc_object_info_t info)
{
xbt_dict_cursor_t cursor = NULL;
char *key = NULL;
dw_type_t type = NULL;
xbt_dict_foreach(info->types, cursor, key, type) {
+ dw_type_t subtype = type;
+ while (subtype->type == DW_TAG_typedef || subtype->type == DW_TAG_volatile_type
+ || subtype->type == DW_TAG_const_type) {
+ if (subtype->subtype)
+ subtype = subtype->subtype;
+ else
+ break;
+ }
+
// Resolve full_type:
- if (type->name && type->byte_size == 0) {
- for (size_t i = 0; i != mc_object_infos_size; ++i) {
- dw_type_t same_type =
- xbt_dict_get_or_null(mc_object_infos[i]->full_types_by_name,
- type->name);
+ if (subtype->name && subtype->byte_size == 0) {
+ for (size_t i = 0; i != process->object_infos_size; ++i) {
+ dw_type_t same_type = (dw_type_t)
+ xbt_dict_get_or_null(process->object_infos[i]->full_types_by_name,
+ subtype->name);
if (same_type && same_type->name && same_type->byte_size) {
type->full_type = same_type;
break;
}
}
- }
+ } else type->full_type = subtype;
}
}
+
+}
#include <elfutils/libdw.h>
#include "mc_object_info.h"
-#include "mc_snapshot.h"
#include "mc_private.h"
+extern "C" {
+
static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
{
if (state->stack_size >= MC_EXPRESSION_STACK_SIZE)
return 0;
}
+/** Convert a DWARF register into a libunwind register
+ *
+ * DWARF and libunwind does not use the same convention for numbering the
+ * registers on some architectures. The function makes the necessary
+ * convertion.
+ */
static int mc_dwarf_register_to_libunwind(int dwarf_register)
{
#if defined(UNW_TARGET_X86_64)
xbt_die("Bad/unknown register number.");
}
#else
-#error This architecture is not supported yet.
+#error This architecture is not supported yet for DWARF expression evaluation.
#endif
}
int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
mc_expression_state_t state)
{
- for (int i = 0; i != n; ++i) {
+ for (size_t i = 0; i != n; ++i) {
int error = 0;
const Dwarf_Op *op = ops + i;
uint8_t atom = op->atom;
{
if (!state->frame_base)
return MC_EXPRESSION_E_MISSING_FRAME_BASE;
- error =
- mc_dwarf_push_value(state,
- ((uintptr_t) state->frame_base) + op->number);
+ uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
+ error = mc_dwarf_push_value(state, fb);
break;
}
- // Constants:
+ // ***** Constants:
+ // Short constant literals:
+ // DW_OP_lit15 pushed the 15 on the stack.
case DW_OP_lit0:
case DW_OP_lit1:
case DW_OP_lit2:
error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
break;
- case DW_OP_addr:
+ // Address from the base address of this ELF object.
+ // Push the address on the stack (base_address + argument).
+ case DW_OP_addr: {
if (!state->object_info)
return MC_EXPRESSION_E_NO_BASE_ADDRESS;
if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
return MC_EXPRESSION_E_STACK_OVERFLOW;
- error = mc_dwarf_push_value(state,
- (Dwarf_Off) (uintptr_t)
- MC_object_base_address(state->object_info) +
- op->number);
+ Dwarf_Off addr = (Dwarf_Off) (uintptr_t)
+ MC_object_base_address(state->object_info) + op->number;
+ error = mc_dwarf_push_value(state, addr);
break;
+ }
+ // General constants:
+ // Push the constant argument on the stack.
case DW_OP_const1u:
case DW_OP_const2u:
case DW_OP_const4u:
error = mc_dwarf_push_value(state, op->number);
break;
- // Stack manipulation:
+ // ***** Stack manipulation:
- // Push the value at the top of the stack:
+ // Push another copy/duplicate the value at the top of the stack:
case DW_OP_dup:
if (state->stack_size == 0)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
break;
+ // Pop/drop the top of the stack:
case DW_OP_drop:
if (state->stack_size == 0)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
state->stack_size--;
break;
+ // Swap the two top-most value of the stack:
case DW_OP_swap:
if (state->stack_size < 2)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
}
break;
+ // Duplicate the value under the top of the stack:
case DW_OP_over:
if (state->stack_size < 2)
return MC_EXPRESSION_E_STACK_UNDERFLOW;
error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
break;
- // Operations:
+ // ***** Operations:
+ // Those usually take the top of the stack and the next value as argument
+ // and replace the top of the stack with the computed value
+ // (stack.top() += stack.before_top()).
case DW_OP_plus:
if (state->stack_size < 2)
case DW_OP_nop:
break;
- // Dereference:
+ // ***** Deference (memory fetch)
+
case DW_OP_deref_size:
return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
{
// Computed address:
uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
- uintptr_t temp;
- uintptr_t* res = (uintptr_t*) mc_snapshot_read((void*) address, state->snapshot, state->process_index, &temp, sizeof(uintptr_t));
- state->stack[state->stack_size - 1] = *res;
+ if (!state->address_space)
+ xbt_die("Missing address space");
+ MC_address_space_read(
+ state->address_space, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &state->stack[state->stack_size - 1], (const void*) address,
+ sizeof(uintptr_t), state->process_index);
}
break;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
s_mc_expression_state_t state;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = frame_pointer_address;
state.cursor = c;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.object_info = object_info;
state.process_index = process_index;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
unw_word_t ip = 0;
if (expression) {
mc_dwarf_resolve_location(location,
expression, object_info, c,
- frame_pointer_address, snapshot, process_index);
+ frame_pointer_address, address_space, process_index);
} else {
xbt_die("Could not resolve location");
}
expression->lowpc = NULL;
expression->highpc = NULL;
expression->size = len;
- expression->ops = xbt_malloc(len * sizeof(Dwarf_Op));
+ expression->ops = (Dwarf_Op*) xbt_malloc(len * sizeof(Dwarf_Op));
memcpy(expression->ops, ops, len * sizeof(Dwarf_Op));
}
}
}
+
+}
#ifndef MC_FORWARD_H
#define MC_FORWARD_H
+#include <xbt/misc.h>
#include <mc/datatypes.h>
-#include "mc_interface.h"
+
+#ifdef __cplusplus
+
+namespace simgrid {
+namespace mc {
+ class PageStore;
+ class ModelChecker;
+}
+}
+
+typedef ::simgrid::mc::ModelChecker s_mc_model_checker_t;
+typedef ::simgrid::mc::PageStore s_mc_pages_store_t;
+
+#else
+
+typedef struct _s_mc_model_checker s_mc_model_checker_t;
+typedef struct _s_mc_pages_store s_mc_pages_store_t;
+
+#endif
typedef struct s_mc_object_info s_mc_object_info_t, *mc_object_info_t;
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_model_checker s_mc_model_checker_t, *mc_model_checker_t;
+typedef 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 s_mc_model_checker_t *mc_model_checker_t;
+
+SG_BEGIN_DECL()
extern mc_model_checker_t mc_model_checker;
+SG_END_DECL()
#endif
/* 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 <cinttypes>
+
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+
#include "mc_base.h"
#ifndef _XBT_WIN32
#include <unistd.h>
-#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
-#include <sys/mman.h>
-#include <libgen.h>
#endif
#include "simgrid/sg_config.h"
#include "xbt/fifo.h"
#include "xbt/automaton.h"
#include "xbt/dict.h"
+#include "mc_record.h"
#ifdef HAVE_MC
-#define UNW_LOCAL_ONLY
+#include "mc_server.h"
#include <libunwind.h>
-
+#include <xbt/mmalloc.h>
#include "../xbt/mmalloc/mmprivate.h"
#include "mc_object_info.h"
#include "mc_comm_pattern.h"
#include "mc_snapshot.h"
#include "mc_liveness.h"
#include "mc_private.h"
+#include "mc_unw.h"
+#include "mc_smx.h"
+#include "mcer_ignore.h"
#endif
#include "mc_record.h"
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
"Logging specific to MC (global)");
+e_mc_mode_t mc_mode;
+
double *mc_time = NULL;
#ifdef HAVE_MC
/* Liveness */
xbt_automaton_t _mc_property_automaton = NULL;
-/* Variables */
-mc_object_info_t mc_libsimgrid_info = NULL;
-mc_object_info_t mc_binary_info = NULL;
-
-mc_object_info_t mc_object_infos[2] = { NULL, NULL };
-
-size_t mc_object_infos_size = 2;
-
/* Dot output */
FILE *dot_output = NULL;
const char *colors[13];
}
-static void MC_init_debug_info(void)
+#ifdef HAVE_MC
+void MC_init()
{
- 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_time = xbt_new0(double, simix_process_maxpid);
-mc_model_checker_t mc_model_checker = NULL;
+ if (_sg_mc_visited > 0 || _sg_mc_liveness || _sg_mc_termination || mc_mode == MC_MODE_SERVER) {
+ /* Those requests are handled on the client side and propagated by message
+ * to the server: */
-mc_model_checker_t MC_model_checker_new()
-{
- 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_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
-void MC_model_checker_delete(mc_model_checker_t mc) {
- mc_pages_store_delete(mc->pages);
- if(mc->record)
- xbt_dynar_free(&mc->record);
+ smx_process_t process;
+ xbt_swag_foreach(process, simix_global->process_list) {
+ MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
+ }
+ }
}
-void MC_init()
+void MC_init_model_checker(pid_t pid, int socket)
{
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- 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;
-
- mc_model_checker = MC_model_checker_new();
+ mc_model_checker = new simgrid::mc::ModelChecker(pid, socket);
mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
mc_stats = xbt_new0(s_mc_stats_t, 1);
mc_stats->state_size = 1;
- MC_init_memory_map_info();
- MC_init_debug_info(); /* FIXME : get debug information only if liveness verification or visited state reduction */
-
if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0'))
MC_init_dot_output();
/* Init parmap */
//parmap = xbt_parmap_mc_new(xbt_os_get_numcores(), XBT_PARMAP_DEFAULT);
- MC_SET_STD_HEAP;
-
- if (_sg_mc_visited > 0 || _sg_mc_liveness || _sg_mc_termination) {
- /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
- MC_ignore_local_variable("e", "*");
- MC_ignore_local_variable("__ex_cleanup", "*");
- MC_ignore_local_variable("__ex_mctx_en", "*");
- MC_ignore_local_variable("__ex_mctx_me", "*");
- MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
- MC_ignore_local_variable("_log_ev", "*");
- MC_ignore_local_variable("_throw_ctx", "*");
- MC_ignore_local_variable("ctx", "*");
-
- MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
- MC_ignore_local_variable("next_cont"
- "ext", "smx_ctx_sysv_suspend_serial");
- MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
-
- /* Ignore local variable about time used for tracing */
- MC_ignore_local_variable("start_time", "*");
-
- /* Main MC state: */
- MC_ignore_global_variable("mc_model_checker");
- MC_ignore_global_variable("initial_communications_pattern");
- MC_ignore_global_variable("incomplete_communications_pattern");
- MC_ignore_global_variable("nb_comm_pattern");
-
- /* MC __thread variables: */
- MC_ignore_global_variable("mc_diff_info");
- MC_ignore_global_variable("mc_comp_times");
- MC_ignore_global_variable("mc_snapshot_comparison_time");
-
- /* This MC state is used in MC replay as well: */
- MC_ignore_global_variable("mc_time");
-
- /* Static variable used for tracing */
- MC_ignore_global_variable("counter");
-
- /* SIMIX */
- MC_ignore_global_variable("smx_total_comms");
-
- 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));
- }
- }
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
-
+ /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
+ MC_ignore_local_variable("e", "*");
+ MC_ignore_local_variable("__ex_cleanup", "*");
+ MC_ignore_local_variable("__ex_mctx_en", "*");
+ MC_ignore_local_variable("__ex_mctx_me", "*");
+ MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
+ MC_ignore_local_variable("_log_ev", "*");
+ MC_ignore_local_variable("_throw_ctx", "*");
+ MC_ignore_local_variable("ctx", "*");
+
+ MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
+ MC_ignore_local_variable("next_cont"
+ "ext", "smx_ctx_sysv_suspend_serial");
+ MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
+
+ /* Ignore local variable about time used for tracing */
+ MC_ignore_local_variable("start_time", "*");
+
+ /* Static variable used for tracing */
+ MCer_ignore_global_variable("counter");
+
+ /* SIMIX */
+ MCer_ignore_global_variable("smx_total_comms");
}
+#endif
/******************************* Core of MC *******************************/
/**************************************************************************/
-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;
-
- /* Create exploration stack */
- mc_stack = xbt_fifo_new();
-
- MC_SET_STD_HEAP;
-
- MC_pre_modelcheck_comm_determinism();
-
- MC_SET_MC_HEAP;
- initial_global_state = xbt_new0(s_mc_global_t, 1);
- initial_global_state->snapshot = MC_take_snapshot(0);
- initial_global_state->initial_communications_pattern_done = 0;
- initial_global_state->recv_deterministic = 1;
- initial_global_state->send_deterministic = 1;
- initial_global_state->recv_diff = NULL;
- initial_global_state->send_diff = NULL;
-
- MC_SET_STD_HEAP;
-
- MC_modelcheck_comm_determinism();
-
- if(mc_mem_set)
- MC_SET_MC_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;
-
- /* Create exploration stack */
- mc_stack = xbt_fifo_new();
-
- MC_SET_STD_HEAP;
-
- MC_pre_modelcheck_safety();
-
- MC_SET_MC_HEAP;
- /* Save the initial state */
- initial_global_state = xbt_new0(s_mc_global_t, 1);
- initial_global_state->snapshot = MC_take_snapshot(0);
- MC_SET_STD_HEAP;
-
- MC_modelcheck_safety();
-
- if (mc_mem_set)
- MC_SET_MC_HEAP;
-
- xbt_abort();
- //MC_exit();
-}
-
-static void MC_modelcheck_liveness_init()
+void MC_run()
{
-
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- _sg_mc_liveness = 1;
-
+ mc_mode = MC_MODE_CLIENT;
MC_init();
-
- if (!mc_mem_set)
- MC_SET_MC_HEAP;
-
- /* Create exploration stack */
- mc_stack = xbt_fifo_new();
-
- /* Create the initial state */
- initial_global_state = xbt_new0(s_mc_global_t, 1);
-
- MC_SET_STD_HEAP;
-
- MC_pre_modelcheck_liveness();
-
- /* We're done */
- MC_print_statistics(mc_stats);
- xbt_free(mc_time);
-
- if (mc_mem_set)
- MC_SET_MC_HEAP;
-
-}
-
-void MC_do_the_modelcheck_for_real()
-{
-
- if (_sg_mc_comms_determinism || _sg_mc_send_determinism) {
- XBT_INFO("Check communication determinism");
- mc_reduce_kind = e_mc_reduce_none;
- MC_modelcheck_comm_determinism_init();
- } else if (!_sg_mc_property_file || _sg_mc_property_file[0] == '\0') {
- if(_sg_mc_termination){
- XBT_INFO("Check non progressive cycles");
- mc_reduce_kind = e_mc_reduce_none;
- }else{
- XBT_INFO("Check a safety property");
- }
- MC_modelcheck_safety_init();
- } else {
- if (mc_reduce_kind == e_mc_reduce_unset)
- mc_reduce_kind = e_mc_reduce_none;
- XBT_INFO("Check the liveness property %s", _sg_mc_property_file);
- MC_automaton_load(_sg_mc_property_file);
- MC_modelcheck_liveness_init();
- }
+ MC_client_main_loop();
}
-
void MC_exit(void)
{
xbt_free(mc_time);
//xbt_abort();
}
+#ifdef HAVE_MC
int MC_deadlock_check()
{
+ if (mc_mode == MC_MODE_SERVER) {
+ int res;
+ if ((res = MC_protocol_send_simple_message(mc_model_checker->process().socket,
+ MC_MESSAGE_DEADLOCK_CHECK)))
+ xbt_die("Could not check deadlock state");
+ s_mc_int_message_t message;
+ ssize_t s = MC_receive_message(mc_model_checker->process().socket, &message, sizeof(message), 0);
+ if (s == -1)
+ xbt_die("Could not receive message");
+ else if (s != sizeof(message) || message.type != MC_MESSAGE_DEADLOCK_CHECK_REPLY) {
+ xbt_die("%s received unexpected message %s (%i, size=%i) "
+ "expected MC_MESSAGE_DEADLOCK_CHECK_REPLY (%i, size=%i)",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(message.type), (int) message.type, (int) s,
+ (int) MC_MESSAGE_DEADLOCK_CHECK_REPLY, (int) sizeof(message)
+ );
+ }
+ else
+ return message.value;
+ }
+
int deadlock = FALSE;
smx_process_t process;
if (xbt_swag_size(simix_global->process_list)) {
deadlock = TRUE;
xbt_swag_foreach(process, simix_global->process_list) {
- if (MC_request_is_enabled(&process->simcall)) {
+ if (MC_process_is_enabled(process)) {
deadlock = FALSE;
break;
}
}
return deadlock;
}
-
-void handle_comm_pattern(e_mc_call_type_t call_type, smx_simcall_t req, int value, xbt_dynar_t pattern, int backtracking) {
-
- switch(call_type) {
- case MC_CALL_TYPE_NONE:
- break;
- case MC_CALL_TYPE_SEND:
- case MC_CALL_TYPE_RECV:
- get_comm_pattern(pattern, req, call_type, backtracking);
- break;
- case MC_CALL_TYPE_WAIT:
- case MC_CALL_TYPE_WAITANY:
- {
- smx_synchro_t current_comm = NULL;
- if (call_type == MC_CALL_TYPE_WAIT)
- current_comm = simcall_comm_wait__get__comm(req);
- else
- current_comm = xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value, smx_synchro_t);
- complete_comm_pattern(pattern, current_comm, req->issuer->pid, backtracking);
- }
- break;
- default:
- xbt_die("Unexpected call type %i", (int)call_type);
- }
-
-}
-
-static void MC_restore_communications_pattern(mc_state_t state) {
- mc_list_comm_pattern_t list_process_comm;
- unsigned int cursor, cursor2;
- xbt_dynar_foreach(initial_communications_pattern, cursor, list_process_comm){
- list_process_comm->index_comm = (int)xbt_dynar_get_as(state->index_comm, cursor, int);
- }
- mc_comm_pattern_t comm;
- cursor = 0;
- xbt_dynar_t initial_incomplete_process_comms, incomplete_process_comms;
- for(int i=0; i<simix_process_maxpid; i++){
- initial_incomplete_process_comms = xbt_dynar_get_as(incomplete_communications_pattern, i, xbt_dynar_t);
- xbt_dynar_reset(initial_incomplete_process_comms);
- incomplete_process_comms = xbt_dynar_get_as(state->incomplete_comm_pattern, i, xbt_dynar_t);
- xbt_dynar_foreach(incomplete_process_comms, cursor2, comm) {
- mc_comm_pattern_t copy_comm = xbt_new0(s_mc_comm_pattern_t, 1);
- copy_comm->index = comm->index;
- copy_comm->type = comm->type;
- copy_comm->comm = comm->comm;
- copy_comm->rdv = strdup(comm->rdv);
- copy_comm->data_size = -1;
- copy_comm->data = NULL;
- if(comm->type == SIMIX_COMM_SEND){
- copy_comm->src_proc = comm->src_proc;
- copy_comm->src_host = comm->src_host;
- if(comm->data != NULL){
- copy_comm->data_size = comm->data_size;
- copy_comm->data = xbt_malloc0(comm->data_size);
- memcpy(copy_comm->data, comm->data, comm->data_size);
- }
- }else{
- copy_comm->dst_proc = comm->dst_proc;
- copy_comm->dst_host = comm->dst_host;
- }
- xbt_dynar_push(initial_incomplete_process_comms, ©_comm);
- }
- }
-}
+#endif
/**
* \brief Re-executes from the state at position start all the transitions indicated by
*/
void MC_replay(xbt_fifo_t stack)
{
- int raw_mem = (mmalloc_get_current_heap() == mc_heap);
-
- int value, count = 1, j;
+ int value, count = 1;
char *req_str;
smx_simcall_t req = NULL, saved_req = NULL;
xbt_fifo_item_t item, start_item;
MC_restore_snapshot(state->system_state);
if(_sg_mc_comms_determinism || _sg_mc_send_determinism)
MC_restore_communications_pattern(state);
- MC_SET_STD_HEAP;
return;
}
}
MC_restore_snapshot(initial_global_state->snapshot);
/* At the moment of taking the snapshot the raw heap was set, so restoring
* it will set it back again, we have to unset it to continue */
- MC_SET_STD_HEAP;
start_item = xbt_fifo_get_last_item(stack);
-
- MC_SET_MC_HEAP;
if (_sg_mc_comms_determinism || _sg_mc_send_determinism) {
- for (j=0; j<simix_process_maxpid; j++) {
+ // int n = xbt_dynar_length(incomplete_communications_pattern);
+ unsigned n = MC_smx_get_maxpid();
+ assert(n == xbt_dynar_length(incomplete_communications_pattern));
+ assert(n == xbt_dynar_length(initial_communications_pattern));
+ for (unsigned j=0; j < n ; j++) {
xbt_dynar_reset((xbt_dynar_t)xbt_dynar_get_as(incomplete_communications_pattern, j, xbt_dynar_t));
- ((mc_list_comm_pattern_t)xbt_dynar_get_as(initial_communications_pattern, j, mc_list_comm_pattern_t))->index_comm = 0;
+ xbt_dynar_get_as(initial_communications_pattern, j, mc_list_comm_pattern_t)->index_comm = 0;
}
}
- MC_SET_STD_HEAP;
-
/* Traverse the stack from the state at position start and re-execute the transitions */
for (item = start_item;
item != xbt_fifo_get_first_item(stack);
if (saved_req) {
/* because we got a copy of the executed request, we have to fetch the
real one, pointed by the request field of the issuer process */
- req = &saved_req->issuer->simcall;
+
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(saved_req);
+ req = &issuer->simcall;
/* Debug information */
if (XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)) {
- req_str = MC_request_to_string(req, value);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_SIMIX);
XBT_DEBUG("Replay: %s (%p)", req_str, state);
xbt_free(req_str);
}
/* TODO : handle test and testany simcalls */
e_mc_call_type_t call = MC_CALL_TYPE_NONE;
if (_sg_mc_comms_determinism || _sg_mc_send_determinism)
- call = mc_get_call_type(req);
+ call = MC_get_call_type(req);
- SIMIX_simcall_handle(req, value);
+ MC_simcall_handle(req, value);
- MC_SET_MC_HEAP;
if (_sg_mc_comms_determinism || _sg_mc_send_determinism)
- handle_comm_pattern(call, req, value, NULL, 1);
- MC_SET_STD_HEAP;
-
+ MC_handle_comm_pattern(call, req, value, NULL, 1);
+
MC_wait_for_requests();
count++;
}
XBT_DEBUG("**** End Replay ****");
-
- if (raw_mem)
- MC_SET_MC_HEAP;
- else
- MC_SET_STD_HEAP;
-
-
}
void MC_replay_liveness(xbt_fifo_t stack)
{
-
- initial_global_state->raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
xbt_fifo_item_t item;
mc_pair_t pair = NULL;
mc_state_t state = NULL;
pair = (mc_pair_t) xbt_fifo_get_item_content(item);
if(pair->graph_state->system_state){
MC_restore_snapshot(pair->graph_state->system_state);
- MC_SET_STD_HEAP;
return;
}
}
/* Restore the initial state */
MC_restore_snapshot(initial_global_state->snapshot);
- /* At the moment of taking the snapshot the raw heap was set, so restoring
- * it will set it back again, we have to unset it to continue */
- if (!initial_global_state->raw_mem_set)
- MC_SET_STD_HEAP;
-
/* Traverse the stack from the initial state and re-execute the transitions */
for (item = xbt_fifo_get_last_item(stack);
item != xbt_fifo_get_first_item(stack);
if (saved_req != NULL) {
/* because we got a copy of the executed request, we have to fetch the
real one, pointed by the request field of the issuer process */
- req = &saved_req->issuer->simcall;
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(saved_req);
+ req = &issuer->simcall;
/* Debug information */
if (XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)) {
- req_str = MC_request_to_string(req, value);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_SIMIX);
XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
xbt_free(req_str);
}
}
- SIMIX_simcall_handle(req, value);
+ MC_simcall_handle(req, value);
MC_wait_for_requests();
}
}
XBT_DEBUG("**** End Replay ****");
-
- if (initial_global_state->raw_mem_set)
- MC_SET_MC_HEAP;
- else
- MC_SET_STD_HEAP;
-
}
/**
*/
void MC_dump_stack_safety(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
MC_show_stack_safety(stack);
mc_state_t state;
-
- 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;
-
}
void MC_show_stack_safety(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
int value;
mc_state_t state;
xbt_fifo_item_t item;
char *req_str = NULL;
for (item = xbt_fifo_get_last_item(stack);
- (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
- : (NULL)); item = xbt_fifo_get_prev_item(item)) {
+ item; item = xbt_fifo_get_prev_item(item)) {
+ state = (mc_state_t)xbt_fifo_get_item_content(item);
req = MC_state_get_executed_request(state, &value);
if (req) {
- req_str = MC_request_to_string(req, value);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_EXECUTED);
XBT_INFO("%s", req_str);
xbt_free(req_str);
}
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
}
void MC_show_deadlock(smx_simcall_t req)
char *req_str = NULL;
for (item = xbt_fifo_get_last_item(stack);
- (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item))) : (NULL));
- item = xbt_fifo_get_prev_item(item)) {
+ item; item = xbt_fifo_get_prev_item(item)) {
+ pair = (mc_pair_t) xbt_fifo_get_item_content(item);
req = MC_state_get_executed_request(pair->graph_state, &value);
if (req && req->call != SIMCALL_NONE) {
- req_str = MC_request_to_string(req, value);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_EXECUTED);
XBT_INFO("%s", req_str);
xbt_free(req_str);
}
void MC_dump_stack_liveness(xbt_fifo_t stack)
{
-
- int raw_mem_set = (mmalloc_get_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;
-
}
void MC_print_statistics(mc_stats_t stats)
{
- xbt_mheap_t previous_heap = mmalloc_get_current_heap();
-
if(_sg_mc_comms_determinism) {
if (!initial_global_state->recv_deterministic && initial_global_state->send_deterministic){
XBT_INFO("******************************************************");
XBT_INFO("%s", initial_global_state->send_diff);
}
}
+
if (stats->expanded_pairs == 0) {
XBT_INFO("Expanded states = %lu", stats->expanded_states);
XBT_INFO("Visited states = %lu", stats->visited_states);
XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
}
XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
- MC_SET_MC_HEAP;
if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0')) {
fprintf(dot_output, "}\n");
fclose(dot_output);
if (_sg_mc_comms_determinism)
XBT_INFO("Recv-deterministic : %s", !initial_global_state->recv_deterministic ? "No" : "Yes");
}
- mmalloc_set_current_heap(previous_heap);
}
-void MC_assert(int prop)
+void MC_automaton_load(const char *file)
{
- 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();
- }
+ if (_mc_property_automaton == NULL)
+ _mc_property_automaton = xbt_automaton_new();
+
+ xbt_automaton_load(_mc_property_automaton, file);
}
-void MC_cut(void)
+static void register_symbol(xbt_automaton_propositional_symbol_t symbol)
{
- user_max_depth_reached = 1;
+ 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));
}
-void MC_automaton_load(const char *file)
+void MC_automaton_new_propositional_symbol(const char *id, int(*fct)(void))
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_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;
-
+ xbt_automaton_propositional_symbol_t symbol = xbt_automaton_propositional_symbol_new(_mc_property_automaton, id, fct);
+ register_symbol(symbol);
}
-void MC_automaton_new_propositional_symbol(const char *id, void *fct)
+void MC_automaton_new_propositional_symbol_pointer(const char *id, int* value)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_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);
+}
- xbt_automaton_propositional_symbol_new(_mc_property_automaton, id, fct);
-
- MC_SET_STD_HEAP;
-
- if (raw_mem_set)
- MC_SET_MC_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)
+{
+ 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);
}
+// TODO, fix cross-process access (this function is not used)
void MC_dump_stacks(FILE* file)
{
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
- MC_SET_MC_HEAP;
-
int nstack = 0;
stack_region_t current_stack;
unsigned cursor;
unw_word_t off;
do {
const char * name = !unw_get_proc_name(&c, buffer, 100, &off) ? buffer : "?";
+#if defined(__x86_64__)
+ unw_word_t rip = 0;
+ unw_word_t rsp = 0;
+ unw_get_reg(&c, UNW_X86_64_RIP, &rip);
+ unw_get_reg(&c, UNW_X86_64_RSP, &rsp);
+ fprintf(file, " %i: %s (RIP=0x%" PRIx64 " RSP=0x%" PRIx64 ")\n",
+ nframe, name, rip, rsp);
+#else
fprintf(file, " %i: %s\n", nframe, name);
+#endif
++nframe;
} while(unw_step(&c));
++nstack;
}
-
- if (raw_mem_set)
- MC_SET_MC_HEAP;
}
#endif
{
mc_time[process->pid] += amount;
}
+
+#ifdef HAVE_MC
+void MC_report_assertion_error(void)
+{
+ 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);
+}
+
+void MC_invalidate_cache(void)
+{
+ if (mc_model_checker)
+ mc_model_checker->process().cache_flags = 0;
+}
+#endif
+
+}
/* 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 <cinttypes>
+
#include <stdint.h>
#include <stdbool.h>
#include "mc/datatypes.h"
#include <mc/mc.h>
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_hash, mc, "Logging specific to mc_hash");
// This is djb2:
// #define MC_HASH(hash, value) hash = (((hash << 5) + hash) + (uint64_t) value)
#define MC_HASH(hash, value) \
{ hash = (((hash << 5) + hash) + (uint64_t) value);\
- XBT_DEBUG("%s:%i: %"PRIx64" -> %"PRIx64, __FILE__, __LINE__, (uint64_t) value, hash); }
+ XBT_DEBUG("%s:%i: %" PRIx64 " -> %" PRIx64, __FILE__, __LINE__, (uint64_t) value, hash); }
// ***** Hash state
+#if 0
typedef struct s_mc_hashing_state {
// Set of pointers/addresses already processed (avoid loops):
mc_address_set_t handled_addresses;
static void mc_hash_binary(mc_hash_t * hash, const void *s, size_t len)
{
- const char *p = (const void *) s;
- int i;
- for (i = 0; i != len; ++i) {
+ const char *p = (const char*) s;
+ for (size_t i = 0; i != len; ++i) {
MC_HASH(*hash, p[i]);
}
}
-#if 0
/** \brief Compute a hash for a given value of a given type
*
* We try to be very conservative (do not hash too ambiguous things).
mc_object_info_t info, const void *address,
dw_type_t type)
{
+ mc_process_t process = &mc_model_checker->process();
top:
switch (type->type) {
mc_address_add(state->handled_addresses, pointed);
// Anything outside the R/W segments and the heap is not hashed:
- bool valid_pointer = (pointed >= (void *) mc_binary_info->start_rw
- && pointed <= (void *) mc_binary_info->end_rw)
- || (pointed >= (void *) mc_libsimgrid_info->start_rw
- && pointed <= (void *) mc_libsimgrid_info->end_rw)
- || (pointed >= std_heap
- && pointed < (void *) ((const char *) std_heap + STD_HEAP_SIZE));
+ bool valid_pointer = (pointed >= (void *) binary_info->start_rw
+ && pointed <= (void *) binary_info->end_rw)
+ || (pointed >= (void *) libsimgrid_info->start_rw
+ && pointed <= (void *) libsimgrid_info->end_rw)
+ || (pointed >= process->heap_address
+ && pointed < (void *) ((const char *) process->heap_address + STD_HEAP_SIZE));
if (!valid_pointer) {
XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed);
return;
}
const char *address = variable->address;
- bool valid_pointer = (address >= mc_binary_info->start_rw
- && address <= mc_binary_info->end_rw)
- || (address >= mc_libsimgrid_info->start_rw
- && address <= mc_libsimgrid_info->end_rw)
- || (address >= (const char *) std_heap
- && address < (const char *) std_heap + STD_HEAP_SIZE);
+ bool valid_pointer = (address >= binary_info->start_rw
+ && address <= binary_info->end_rw)
+ || (address >= libsimgrid_info->start_rw
+ && address <= libsimgrid_info->end_rw)
+ || (address >= (const char *) process->heap_address
+ && address < (const char *) process->heap_address + STD_HEAP_SIZE);
if (!valid_pointer)
continue;
MC_HASH(*hash, stack_frame->ip);
mc_object_info_t info;
- if (stack_frame->ip >= (unw_word_t) mc_libsimgrid_info->start_exec
- && stack_frame->ip < (unw_word_t) mc_libsimgrid_info->end_exec)
- info = mc_libsimgrid_info;
- else if (stack_frame->ip >= (unw_word_t) mc_binary_info->start_exec
- && stack_frame->ip < (unw_word_t) mc_binary_info->end_exec)
- info = mc_binary_info;
+ if (stack_frame->ip >= (unw_word_t) libsimgrid_info->start_exec
+ && stack_frame->ip < (unw_word_t) libsimgrid_info->end_exec)
+ info = libsimgrid_info;
+ else if (stack_frame->ip >= (unw_word_t) binary_info->start_exec
+ && stack_frame->ip < (unw_word_t) binary_info->end_exec)
+ info = binary_info;
else
continue;
{
XBT_DEBUG("START hash %i", num_state);
+#if 0
mc_hashing_state state;
mc_hash_state_init(&state);
+#endif
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);
+#if 0
+ // 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);
+#endif
XBT_DEBUG("END hash %i", num_state);
return hash;
}
+
+}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "internal_config.h"
+#include "mc_object_info.h"
+#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"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_ignore, mc,
+ "Logging specific to MC ignore mechanism");
+
+// ***** Model-checked
+
+void MC_ignore_heap(void *address, size_t size)
+{
+ if (mc_mode != MC_MODE_CLIENT)
+ return;
+
+ xbt_mheap_t heap = mmalloc_get_current_heap();
+
+ s_mc_heap_ignore_region_t region;
+ memset(®ion, 0, sizeof(region));
+ region.address = address;
+ region.size = size;
+ region.block =
+ ((char *) address -
+ (char *) heap->heapbase) / BLOCKSIZE + 1;
+ if (heap->heapinfo[region.block].type == 0) {
+ region.fragment = -1;
+ heap->heapinfo[region.block].busy_block.ignore++;
+ } else {
+ region.fragment =
+ ((uintptr_t) (ADDR2UINT(address) % (BLOCKSIZE))) >>
+ heap->heapinfo[region.block].type;
+ heap->heapinfo[region.block].busy_frag.ignore[region.fragment]++;
+ }
+
+ 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");
+}
+
+void MC_remove_ignore_heap(void *address, size_t size)
+{
+ if (mc_mode != MC_MODE_CLIENT)
+ return;
+
+ 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));
+}
+
+void MC_ignore_global_variable(const char *name)
+{
+ // TODO, send a message to the model_checker
+ xbt_die("Unimplemented");
+}
+
+/** @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 the heap so it must be told where
+ * they are with this function.
+ *
+ * @param stack
+ * @param process Process owning the stack
+ * @param context
+ * @param size Size of the stack
+ */
+void MC_register_stack_area(void *stack, smx_process_t process, void *context, size_t size)
+{
+ if (mc_mode != MC_MODE_CLIENT)
+ return;
+
+ xbt_mheap_t heap = mmalloc_get_current_heap();
+
+ s_stack_region_t region;
+ memset(®ion, 0, sizeof(region));
+ region.address = stack;
+ region.context = context;
+ region.size = size;
+ region.block =
+ ((char *) stack -
+ (char *) heap->heapbase) / BLOCKSIZE + 1;
+#ifdef HAVE_SMPI
+ if (smpi_privatize_global_variables && process) {
+ region.process_index = smpi_process_index_of_smx_process(process);
+ } else
+#endif
+ region.process_index = -1;
+
+ s_mc_stack_region_message_t message;
+ message.type = MC_MESSAGE_STACK_REGION;
+ message.stack_region = region;
+ MC_client_send_message(&message, sizeof(message));
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/dynar.h>
+
+#include "mc/datatypes.h"
+#include "mc_process.h"
+
+#include "xbt/misc.h" /* SG_BEGIN_DECL */
+
+SG_BEGIN_DECL();
+
+XBT_INTERNAL void MC_stack_area_add(stack_region_t stack_area);
+
+XBT_INTERNAL xbt_dynar_t MC_checkpoint_ignore_new(void);
+
+SG_END_DECL();
+++ /dev/null
-/* MC interface: definitions that non-MC modules must see, but not the user */
-
-/* Copyright (c) 2007-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_INTERFACE_H
-#define MC_INTERFACE_H
-#include "mc/mc.h"
-
-SG_BEGIN_DECL()
-
-typedef struct s_mc_snapshot s_mc_snapshot_t, *mc_snapshot_t;
-
-SG_END_DECL()
-
-#endif
#include "mc_liveness.h"
#include "mc_private.h"
#include "mc_record.h"
+#include "mc_smx.h"
+#include "mc_client.h"
+#include "mc_replay.h"
+#include "mc_safety.h"
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc,
"Logging specific to algorithms for liveness properties verification");
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)
+{
mc_visited_pair_t new_pair = NULL;
new_pair = MC_visited_pair_new(pair->num, pair->automaton_state, pair->atomic_propositions, pair->graph_state);
new_pair->acceptance_pair = 1;
// Parallell implementation
/*res = xbt_parmap_mc_apply(parmap, snapshot_compare, xbt_dynar_get_ptr(acceptance_pairs, min), (max-min)+1, pair);
if(res != -1){
- if(!raw_mem_set)
- MC_SET_STD_HEAP;
return ((mc_pair_t)xbt_dynar_get_as(acceptance_pairs, (min+res)-1, mc_pair_t))->num;
} */
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;
-
return NULL;
}
}
xbt_dynar_insert_at(acceptance_pairs, index, &new_pair);
}
}
-
}
-
- if (!raw_mem_set)
- MC_SET_STD_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)
+{
unsigned int cursor = 0;
mc_visited_pair_t pair_test = NULL;
int pair_found = 0;
MC_visited_pair_delete(pair_test);
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
}
unsigned int cursor = 0;
xbt_automaton_propositional_symbol_t p = NULL;
xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, p) {
- if (strcmp(p->pred, l->u.predicat) == 0)
+ if (strcmp(xbt_automaton_propositional_symbol_get_name(p), l->u.predicat) == 0)
return (int) xbt_dynar_get_as(atomic_propositions_values, cursor, int);
}
return -1;
}
}
-void MC_pre_modelcheck_liveness(void) {
-
- initial_global_state->raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+static void MC_modelcheck_liveness_main(void);
+static void MC_pre_modelcheck_liveness(void)
+{
mc_pair_t initial_pair = NULL;
smx_process_t process;
MC_wait_for_requests();
- MC_SET_MC_HEAP;
-
acceptance_pairs = xbt_dynar_new(sizeof(mc_visited_pair_t), NULL);
if(_sg_mc_visited > 0)
visited_pairs = xbt_dynar_new(sizeof(mc_visited_pair_t), NULL);
initial_pair->depth = 1;
/* Get enabled processes and insert them in the interleave set of the graph_state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(initial_pair->graph_state, process);
}
- }
+ );
initial_pair->requests = MC_state_interleave_size(initial_pair->graph_state);
initial_pair->search_cycle = 0;
}
}
- MC_SET_STD_HEAP;
-
- MC_modelcheck_liveness();
-
- if (initial_global_state->raw_mem_set)
- MC_SET_MC_HEAP;
-
-
+ MC_modelcheck_liveness_main();
}
-void MC_modelcheck_liveness() {
-
+static void MC_modelcheck_liveness_main(void)
+{
smx_process_t process = NULL;
mc_pair_t current_pair = NULL;
int value, res, visited_num = -1;
/* Update current state in buchi automaton */
_mc_property_automaton->current_state = current_pair->automaton_state;
- XBT_DEBUG("********************* ( Depth = %d, search_cycle = %d, interleave size %d, pair_num %d)",
+ XBT_DEBUG("********************* ( Depth = %d, search_cycle = %d, interleave size = %d, pair_num = %d, requests = %d)",
current_pair->depth, current_pair->search_cycle,
- MC_state_interleave_size(current_pair->graph_state), current_pair->num);
+ MC_state_interleave_size(current_pair->graph_state), current_pair->num,
+ current_pair->requests);
if (current_pair->requests > 0) {
if ((current_pair->exploration_started == 0) && (visited_num = is_visited_pair(reached_pair, current_pair)) != -1) {
if (dot_output != NULL){
- MC_SET_MC_HEAP;
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_global_state->prev_pair, visited_num, initial_global_state->prev_req);
fflush(dot_output);
- MC_SET_STD_HEAP;
}
XBT_DEBUG("Pair already visited (equal to pair %d), exploration on the current path stopped.", visited_num);
- MC_SET_MC_HEAP;
current_pair->requests = 0;
- MC_SET_STD_HEAP;
goto backtracking;
}else{
req = MC_state_get_request(current_pair->graph_state, &value);
if (dot_output != NULL) {
- MC_SET_MC_HEAP;
if (initial_global_state->prev_pair != 0 && initial_global_state->prev_pair != current_pair->num) {
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_global_state->prev_pair, current_pair->num, initial_global_state->prev_req);
xbt_free(initial_global_state->prev_req);
if (current_pair->search_cycle)
fprintf(dot_output, "%d [shape=doublecircle];\n", current_pair->num);
fflush(dot_output);
- MC_SET_STD_HEAP;
}
- char* req_str = MC_request_to_string(req, value);
- XBT_DEBUG("Execute: %s", req_str);
+ char* req_str = MC_request_to_string(req, value, MC_REQUEST_SIMIX);
+ XBT_DEBUG("Execute: %s", req_str);
xbt_free(req_str);
/* Set request as executed */
mc_stats->visited_pairs++;
/* Answer the request */
- SIMIX_simcall_handle(req, value);
+ MC_simcall_handle(req, value);
/* Wait for requests (schedules processes) */
MC_wait_for_requests();
- MC_SET_MC_HEAP;
-
current_pair->requests--;
current_pair->exploration_started = 1;
next_pair->atomic_propositions = get_atomic_propositions_values();
next_pair->depth = current_pair->depth + 1;
/* Get enabled processes and insert them in the interleave set of the next graph_state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(next_pair->graph_state, process);
}
- }
+ );
next_pair->requests = MC_state_interleave_size(next_pair->graph_state);
}
cursor--;
}
-
- MC_SET_STD_HEAP;
-
+
} /* End of visited_pair test */
} else {
if(visited_num == -1)
XBT_DEBUG("No more request to execute. Looking for backtracking point.");
- MC_SET_MC_HEAP;
-
xbt_dynar_free(&prop_values);
/* Traverse the stack backwards until a pair with a non empty interleave
set is found, deleting all the pairs that have it empty in the way. */
- while ((current_pair = xbt_fifo_shift(mc_stack)) != NULL) {
+ while ((current_pair = (mc_pair_t) xbt_fifo_shift(mc_stack)) != NULL) {
if (current_pair->requests > 0) {
/* We found a backtracking point */
XBT_DEBUG("Backtracking to depth %d", current_pair->depth);
xbt_fifo_unshift(mc_stack, current_pair);
- MC_SET_STD_HEAP;
MC_replay_liveness(mc_stack);
XBT_DEBUG("Backtracking done");
break;
MC_pair_delete(current_pair);
}
}
-
- MC_SET_STD_HEAP;
+
} /* End of if (current_pair->requests > 0) else ... */
} /* End of while(xbt_fifo_size(mc_stack) > 0) */
}
+
+void MC_modelcheck_liveness(void)
+{
+ if (mc_reduce_kind == e_mc_reduce_unset)
+ mc_reduce_kind = e_mc_reduce_none;
+ XBT_INFO("Check the liveness property %s", _sg_mc_property_file);
+ MC_automaton_load(_sg_mc_property_file);
+ MC_wait_for_requests();
+
+ XBT_DEBUG("Starting the liveness algorithm");
+ _sg_mc_liveness = 1;
+
+ /* Create exploration stack */
+ mc_stack = xbt_fifo_new();
+
+ /* Create the initial state */
+ initial_global_state = xbt_new0(s_mc_global_t, 1);
+
+ MC_pre_modelcheck_liveness();
+
+ /* We're done */
+ MC_print_statistics(mc_stats);
+ xbt_free(mc_time);
+}
+
+}
SG_BEGIN_DECL()
-extern xbt_automaton_t _mc_property_automaton;
+extern XBT_INTERNAL xbt_automaton_t _mc_property_automaton;
typedef struct s_mc_pair{
int num;
int visited_removed;
} s_mc_visited_pair_t, *mc_visited_pair_t;
-mc_pair_t MC_pair_new(void);
-void MC_pair_delete(mc_pair_t);
-void mc_pair_free_voidp(void *p);
-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);
-void MC_visited_pair_delete(mc_visited_pair_t p);
+XBT_INTERNAL mc_pair_t MC_pair_new(void);
+XBT_INTERNAL void MC_pair_delete(mc_pair_t);
+XBT_INTERNAL void mc_pair_free_voidp(void *p);
+XBT_INTERNAL 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);
+XBT_INTERNAL void MC_visited_pair_delete(mc_visited_pair_t p);
-void MC_pre_modelcheck_liveness(void);
void MC_modelcheck_liveness(void);
-void MC_show_stack_liveness(xbt_fifo_t stack);
-void MC_dump_stack_liveness(xbt_fifo_t stack);
+XBT_INTERNAL void MC_show_stack_liveness(xbt_fifo_t stack);
+XBT_INTERNAL void MC_dump_stack_liveness(xbt_fifo_t stack);
-extern xbt_dynar_t visited_pairs;
-int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair);
+XBT_INTERNAL extern xbt_dynar_t visited_pairs;
+XBT_INTERNAL int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair);
SG_END_DECL()
#include <stdint.h>
-#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <dwarf.h>
#include <elfutils/libdw.h>
#include <simgrid_config.h>
-#include "mc_interface.h"
+#include "mc_base.h"
+#include "mc_forward.h"
#include "mc_object_info.h"
#include "mc_forward.h"
+#include "mc_address_space.h"
SG_BEGIN_DECL()
}
}
-void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
-void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
+XBT_INTERNAL 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);
+MC_SHOULD_BE_INTERNAL 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);
+XBT_INTERNAL void mc_dwarf_expression_clear(mc_expression_t expression);
+XBT_INTERNAL void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops);
-void mc_dwarf_location_list_clear(mc_location_list_t list);
+XBT_INTERNAL void mc_dwarf_location_list_clear(mc_location_list_t list);
-void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops);
-void mc_dwarf_location_list_init(mc_location_list_t target, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr);
+XBT_INTERNAL void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops);
+XBT_INTERNAL void mc_dwarf_location_list_init(mc_location_list_t target, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr);
#define MC_EXPRESSION_STACK_SIZE 64
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;
-int mc_dwarf_execute_expression(size_t n, const Dwarf_Op* ops, mc_expression_state_t state);
+MC_SHOULD_BE_INTERNAL int mc_dwarf_execute_expression(
+ size_t n, const Dwarf_Op* ops, mc_expression_state_t state);
-void* mc_find_frame_base(dw_frame_t frame, mc_object_info_t object_info, unw_cursor_t* unw_cursor);
+MC_SHOULD_BE_INTERNAL void* mc_find_frame_base(
+ dw_frame_t frame, mc_object_info_t object_info, unw_cursor_t* unw_cursor);
SG_END_DECL()
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <xbt/misc.h>
+
#include "mc_object_info.h"
#include "mc_private.h"
+extern "C" {
+
/** Resolve snapshot in the process address space
*
* @param object Process address of the struct/class
* @return Process address of the given member of the 'object' struct/class
*/
void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
if (!member->location.size) {
return ((char *) base) + member->offset;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = NULL;
state.cursor = NULL;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.stack_size = 1;
state.stack[0] = (uintptr_t) base;
state.process_index = process_index;
else
return (void *) state.stack[state.stack_size - 1];
}
+
+}
+++ /dev/null
-/* Copyright (c) 2008-2014. The SimGrid Team.
- * All rights reserved. */
-
-/* This program is free software; you can redistribute it and/or modify it
- * under the terms of the license (GNU LGPL) which comes with this package. */
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "xbt/log.h"
-
-#include "mc/mc.h"
-#include "mc_object_info.h"
-#include "mc_private.h"
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory, mc,
- "Logging specific to MC (memory)");
-
-/* Pointers to each of the heap regions to use */
-xbt_mheap_t std_heap = NULL; /* memory erased each time the MC stuff rollbacks to the beginning. Almost everything goes here */
-xbt_mheap_t mc_heap = NULL; /* memory persistent over the MC rollbacks. Only MC stuff should go there */
-
-/* Initialize the model-checker memory subsystem */
-/* It creates the two heap regions: std_heap and mc_heap */
-void MC_memory_init()
-{
- /* 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)
- xbt_mheap_destroy(mc_heap);
-}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "xbt/log.h"
+#include "xbt/dynar.h"
+#include "xbt/virtu.h"
+
+#include "mc/mc.h"
+#include "mc_object_info.h"
+#include "mc_private.h"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory, mc,
+ "Logging specific to MC (memory)");
+
+/* Initialize the model-checker memory subsystem */
+/* 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.");
+ }
+}
+
+/* Finalize the memory subsystem */
+#include "xbt_modinter.h"
+void MC_memory_exit(void)
+{
+}
+
+}
#ifndef MC_MEMORY_MAP_H
#define MC_MEMORY_MAP_H
+#include <sys/types.h>
+
#include <simgrid_config.h>
#include "mc_forward.h"
};
-void MC_init_memory_map_info(void);
-memory_map_t MC_get_memory_map(void);
-void MC_free_memory_map(memory_map_t map);
+XBT_INTERNAL memory_map_t MC_get_memory_map(pid_t pid);
+XBT_INTERNAL void MC_free_memory_map(memory_map_t map);
SG_END_DECL()
#ifndef MC_MMALLOC_H
#define MC_MMALLOC_H
+#include <xbt/misc.h>
#include <xbt/mmalloc.h>
/** file
* Normally the system should operate in std, for switching to raw mode
* you must wrap the code between MC_SET_RAW_MODE and MC_UNSET_RAW_MODE.
*/
-
-extern xbt_mheap_t std_heap;
-extern xbt_mheap_t mc_heap;
+
+SG_BEGIN_DECL()
/* FIXME: Horrible hack! because the mmalloc library doesn't provide yet of */
/* an API to query about the status of a heap, we simply call mmstats and */
/* size_t bytes_free; /\* Byte total of chunks in the free list. *\/ */
/* }; */
-#define MC_SET_MC_HEAP mmalloc_set_current_heap(mc_heap)
-#define MC_SET_STD_HEAP mmalloc_set_current_heap(std_heap)
+SG_END_DECL()
#endif
#include <stdint.h>
#include <stdbool.h>
+#include <xbt/misc.h>
+
#include <simgrid_config.h>
SG_BEGIN_DECL()
-extern int xbt_pagesize;
-extern int xbt_pagebits;
-
/** @brief How many memory pages are necessary to store size bytes?
*
* @param size Byte 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;
* @return Offset within the memory page
*/
static inline __attribute__ ((always_inline))
-size_t mc_page_offset(void* address)
+size_t mc_page_offset(const void* address)
{
return ((uintptr_t) address) & (xbt_pagesize-1);
}
* @param page Index of the page
*/
static inline __attribute__ ((always_inline))
-void* mc_page_from_number(void* base, size_t page)
+void* mc_page_from_number(const void* base, size_t page)
{
return (void*) ((char*)base + (page << xbt_pagebits));
}
static inline __attribute__ ((always_inline))
-bool mc_same_page(void* a, void* b)
+bool mc_same_page(const void* a, const void* b)
{
return ((uintptr_t) a >> xbt_pagebits) == ((uintptr_t) b >> xbt_pagebits);
}
+++ /dev/null
-/* Copyright (c) 2007-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_MODEL_CHECKER_H
-#define MC_MODEL_CHECKER_H
-
-#include <simgrid_config.h>
-
-#include "mc_forward.h"
-
-SG_BEGIN_DECL()
-
-/** @brief State of the model-checker (global variables for the model checker)
- *
- * Each part of the state of the model chercker represented as a global
- * variable prevents some sharing between snapshots and must be ignored.
- * By moving as much state as possible in this structure allocated
- * on the model-chercker heap, we avoid those issues.
- */
-struct s_mc_model_checker {
- // This is the parent snapshot of the current state:
- mc_snapshot_t parent_snapshot;
- mc_pages_store_t pages;
- int fd_clear_refs;
- int fd_pagemap;
- xbt_dynar_t record;
-};
-
-mc_model_checker_t MC_model_checker_new(void);
-void MC_model_checker_delete(mc_model_checker_t mc);
-
-SG_END_DECL()
-
-#endif
--- /dev/null
+/* Copyright (c) 2014-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 <stddef.h>
+
+#include <xbt/dynar.h>
+
+#include "mc_object_info.h"
+#include "mc_private.h"
+
+extern "C" {
+
+dw_frame_t MC_file_object_info_find_function(mc_object_info_t info, const void *ip)
+{
+ xbt_dynar_t dynar = info->functions_index;
+ mc_function_index_item_t base =
+ (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
+ int i = 0;
+ int j = xbt_dynar_length(dynar) - 1;
+ while (j >= i) {
+ int k = i + ((j - i) / 2);
+ if (ip < base[k].low_pc) {
+ j = k - 1;
+ } else if (ip >= base[k].high_pc) {
+ i = k + 1;
+ } else {
+ return base[k].function;
+ }
+ }
+ return NULL;
+}
+
+dw_variable_t MC_file_object_info_find_variable_by_name(mc_object_info_t info, const char* name)
+{
+ unsigned int cursor = 0;
+ dw_variable_t variable;
+ xbt_dynar_foreach(info->global_variables, cursor, variable){
+ if(!strcmp(name, variable->name))
+ return variable;
+ }
+
+ return NULL;
+}
+
+}
#define MC_OBJECT_INFO_H
#include <stdint.h>
+#include <stdbool.h>
#include <simgrid_config.h>
#include <xbt/dict.h>
#include "mc_forward.h"
#include "mc_location.h"
+#include "mc_process.h"
+#include "../smpi/private.h"
SG_BEGIN_DECL();
dw_type_t full_type; // The same (but more complete) type
};
-void dw_type_free(dw_type_t t);
-void dw_variable_free(dw_variable_t v);
-void dw_variable_free_voidp(void *t);
+XBT_INTERNAL void dw_type_free(dw_type_t t);
+XBT_INTERNAL void dw_variable_free(dw_variable_t v);
+XBT_INTERNAL void dw_variable_free_voidp(void *t);
// ***** Object info
-enum mc_object_info_flags {
- MC_OBJECT_INFO_NONE = 0,
- MC_OBJECT_INFO_EXECUTABLE = 1
-};
+/** Bit field of options */
+typedef int mc_object_info_flags;
+#define MC_OBJECT_INFO_NONE 0
+#define MC_OBJECT_INFO_EXECUTABLE 1
struct s_mc_object_info {
- enum mc_object_info_flags flags;
+ mc_object_info_flags flags;
char* file_name;
+ const void* start, *end;
char *start_exec, *end_exec; // Executable segment
char *start_rw, *end_rw; // Read-write segment
char *start_ro, *end_ro; // read-only segment
xbt_dynar_t functions_index;
};
+static inline __attribute__ ((always_inline))
+bool MC_object_info_executable(mc_object_info_t info)
+{
+ return info->flags & MC_OBJECT_INFO_EXECUTABLE;
+}
+
+static inline __attribute__ ((always_inline))
+bool MC_object_info_is_privatized(mc_object_info_t info)
+{
+ return info && MC_object_info_executable(info) && smpi_privatize_global_variables;
+}
+
/** Find the DWARF offset for this ELF object
*
* An offset is applied to address found in DWARF:
* + \text{dwarf address}\f$.</li>
*
*/
-void* MC_object_base_address(mc_object_info_t info);
+XBT_INTERNAL 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);
-void MC_free_object_info(mc_object_info_t* p);
+XBT_INTERNAL mc_object_info_t MC_new_object_info(void);
+XBT_INTERNAL mc_object_info_t MC_find_object_info(memory_map_t maps, const char* name, int executable);
+XBT_INTERNAL void MC_free_object_info(mc_object_info_t* p);
-void MC_post_process_object_info(mc_object_info_t info);
+XBT_INTERNAL dw_frame_t MC_file_object_info_find_function(mc_object_info_t info, const void *ip);
+MC_SHOULD_BE_INTERNAL dw_variable_t MC_file_object_info_find_variable_by_name(mc_object_info_t info, const char* name);
-void MC_dwarf_get_variables(mc_object_info_t info);
-void MC_dwarf_get_variables_libdw(mc_object_info_t info);
-const char* MC_dwarf_attrname(int attr);
-const char* MC_dwarf_tagname(int tag);
+XBT_INTERNAL void MC_post_process_object_info(mc_process_t process, mc_object_info_t info);
-// Not used:
-char* get_type_description(mc_object_info_t info, char *type_name);
+XBT_INTERNAL void MC_dwarf_get_variables(mc_object_info_t info);
+XBT_INTERNAL void MC_dwarf_get_variables_libdw(mc_object_info_t info);
+XBT_INTERNAL const char* MC_dwarf_attrname(int attr);
+XBT_INTERNAL const char* MC_dwarf_tagname(int tag);
-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;
+// Not used:
+XBT_INTERNAL char* get_type_description(mc_object_info_t info, char *type_name);
-void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot, int process_index);
+XBT_INTERNAL 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. */
dw_frame_t function;
};
-void mc_frame_free(dw_frame_t freme);
+XBT_INTERNAL void mc_frame_free(dw_frame_t freme);
SG_END_DECL()
/* 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_page_store.h"
+#include <unistd.h> // pread, pwrite
+
+#include "PageStore.hpp"
#include "mc_mmu.h"
#include "mc_private.h"
#include "mc_snapshot.h"
#include <xbt/mmalloc.h>
-#define SOFT_DIRTY_BIT_NUMBER 55
-#define SOFT_DIRTY (((uint64_t)1) << SOFT_DIRTY_BIT_NUMBER)
-
extern "C" {
// ***** Region management:
*
* @param data The start of the region (must be at the beginning of a page)
* @param pag_count Number of pages of the region
- * @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)
* @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)
{
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) {
- // The page is softclean, it is the same page as the reference page:
- pagenos[i] = reference_pages[i];
- mc_model_checker->pages->ref_page(reference_pages[i]);
- } else {
+
// 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->page_store().store_page(page_data);
+
}
+ free(temp);
return pagenos;
}
void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count)
{
for (size_t i=0; i!=page_count; ++i) {
- mc_model_checker->pages->unref_page(pagenos[i]);
+ mc_model_checker->page_store().unref_page(pagenos[i]);
}
}
* @param start_addr
* @param page_count Number of pages of the region
* @param pagenos
- * @param pagemap Linux kernel pagemap values fot this region (or NULL)
- * @param reference_pages Snapshot page numbers of the previous soft_dirty_reset (or NULL)
*/
-void mc_restore_page_snapshot_region(void* start_addr, size_t page_count, size_t* pagenos, uint64_t* pagemap, size_t* reference_pagenos)
+void mc_restore_page_snapshot_region(mc_process_t process,
+ void* start_addr, size_t page_count, size_t* pagenos)
{
for (size_t i=0; i!=page_count; ++i) {
-
- bool softclean = pagemap && !(pagemap[i] & SOFT_DIRTY);
- if (softclean && reference_pagenos && pagenos[i] == reference_pagenos[i]) {
- // The page is softclean and is the same as the reference one:
- // the page is already in the target state.
- continue;
- }
-
// 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);
- }
-}
-
-// ***** Soft dirty tracking
-
-/** @brief Like pread() but without partial reads */
-static size_t pread_whole(int fd, void* buf, size_t count, off_t offset) {
- size_t res = 0;
-
- char* data = (char*) buf;
- while(count) {
- ssize_t n = pread(fd, buf, count, offset);
- // EOF
- if (n==0)
- return res;
-
- // Error (or EINTR):
- if (n==-1) {
- if (errno == EINTR)
- continue;
- else
- return -1;
- }
-
- // It might be a partial read:
- count -= n;
- data += n;
- offset += n;
- res += n;
- }
-
- return res;
-}
-
-static inline __attribute__ ((always_inline))
-void mc_ensure_fd(int* fd, const char* path, int flags) {
- if (*fd != -1)
- return;
- *fd = open(path, flags);
- if (*fd == -1) {
- xbt_die("Could not open file %s", path);
- }
-}
-
-/** @brief Reset the soft-dirty bits
- *
- * This is done after checkpointing and after checkpoint restoration
- * (if per page checkpoiting is used) in order to know which pages were
- * modified.
- *
- * See https://www.kernel.org/doc/Documentation/vm/soft-dirty.txt
- * */
-void mc_softdirty_reset() {
- mc_ensure_fd(&mc_model_checker->fd_clear_refs, "/proc/self/clear_refs", O_WRONLY|O_CLOEXEC);
- if( ::write(mc_model_checker->fd_clear_refs, "4\n", 2) != 2) {
- xbt_die("Could not reset softdirty bits");
- }
-}
-
-/** @brief Read memory page informations
- *
- * For each virtual memory page of the process,
- * /proc/self/pagemap provides a 64 bit field of information.
- * We are interested in the soft-dirty bit: with this we can track which
- * pages were modified between snapshots/restorations and avoid
- * copying data which was not modified.
- *
- * See https://www.kernel.org/doc/Documentation/vm/pagemap.txt
- *
- * @param pagemap Output buffer for pagemap informations
- * @param start_addr Address of the first page
- * @param page_count Number of pages
- */
-static void mc_read_pagemap(uint64_t* pagemap, size_t page_start, size_t page_count)
-{
- mc_ensure_fd(&mc_model_checker->fd_pagemap, "/proc/self/pagemap", O_RDONLY|O_CLOEXEC);
- size_t bytesize = sizeof(uint64_t) * page_count;
- off_t offset = sizeof(uint64_t) * page_start;
- if (pread_whole(mc_model_checker->fd_pagemap, pagemap, bytesize, offset) != bytesize) {
- xbt_die("Could not read pagemap");
+ const void* source_page = mc_model_checker->page_store().get_page(pagenos[i]);
+ MC_process_write(process, source_page, target_page, xbt_pagesize);
}
}
// ***** High level API
-mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type,
+ void *start_addr, void* permanent_addr, size_t size)
{
- mc_mem_region_t 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");
"Not at the beginning of a page");
size_t page_count = mc_page_count(size);
- uint64_t* pagemap = NULL;
- if (_sg_mc_soft_dirty && mc_model_checker->parent_snapshot) {
- pagemap = (uint64_t*) mmalloc_no_memset(mc_heap, sizeof(uint64_t) * page_count);
- mc_read_pagemap(pagemap, mc_page_number(NULL, permanent_addr), page_count);
- }
-
// 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);
- 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)
{
xbt_assert((((uintptr_t)reg->permanent_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
size_t page_count = mc_page_count(reg->size);
- 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);
- 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);
-
- if(pagemap) {
- free(pagemap);
- }
+ mc_restore_page_snapshot_region(process,
+ reg->permanent_addr, page_count, reg->chunked.page_numbers);
}
}
#include "mc_liveness.h"
#include "mc_private.h"
+extern "C" {
+
mc_pair_t MC_pair_new()
{
mc_pair_t p = NULL;
{
MC_pair_delete((mc_pair_t) * (void **) p);
}
+
+}
#ifndef MC_PRIVATE_H
#define MC_PRIVATE_H
+#include <sys/types.h>
+
#include "simgrid_config.h"
#include <stdio.h>
#include <stdint.h>
#include "mc/datatypes.h"
#include "xbt/fifo.h"
#include "xbt/config.h"
+
#include "xbt/function_types.h"
#include "xbt/mmalloc.h"
#include "../simix/smx_private.h"
#include "../xbt/mmalloc/mmprivate.h"
#include "xbt/automaton.h"
#include "xbt/hash.h"
-#include "simgrid/msg.h"
-#include "msg/datatypes.h"
+#include <simgrid/msg.h>
#include "xbt/strbuff.h"
#include "xbt/parmap.h"
#include "mc_forward.h"
+#include "mc_protocol.h"
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 **********************************/
-extern FILE *dot_output;
-extern const char* colors[13];
-extern xbt_parmap_t parmap;
+/** 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_model_checker(pid_t pid, int socket);
+
+XBT_INTERNAL extern FILE *dot_output;
+XBT_INTERNAL extern const char* colors[13];
+XBT_INTERNAL extern xbt_parmap_t parmap;
-extern int user_max_depth_reached;
+XBT_INTERNAL extern int user_max_depth_reached;
-int MC_deadlock_check(void);
-void MC_replay(xbt_fifo_t stack);
-void MC_replay_liveness(xbt_fifo_t stack);
-void MC_show_deadlock(smx_simcall_t req);
-void MC_show_stack_safety(xbt_fifo_t stack);
-void MC_dump_stack_safety(xbt_fifo_t stack);
-void MC_show_non_termination(void);
+XBT_INTERNAL int MC_deadlock_check(void);
+XBT_INTERNAL void MC_replay(xbt_fifo_t stack);
+XBT_INTERNAL void MC_replay_liveness(xbt_fifo_t stack);
+XBT_INTERNAL void MC_show_deadlock(smx_simcall_t req);
+XBT_INTERNAL void MC_show_stack_safety(xbt_fifo_t stack);
+XBT_INTERNAL void MC_dump_stack_safety(xbt_fifo_t stack);
+XBT_INTERNAL void MC_show_non_termination(void);
/** Stack (of `mc_state_t`) representing the current position of the
* the MC in the exploration graph
*
* It is managed by its head (`xbt_fifo_shift` and `xbt_fifo_unshift`).
*/
-extern xbt_fifo_t mc_stack;
+XBT_INTERNAL extern xbt_fifo_t mc_stack;
-int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max);
+XBT_INTERNAL int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max);
/****************************** Statistics ************************************/
unsigned long executed_transitions;
} s_mc_stats_t, *mc_stats_t;
-extern mc_stats_t mc_stats;
+XBT_INTERNAL extern mc_stats_t mc_stats;
-void MC_print_statistics(mc_stats_t stats);
-
-extern char *libsimgrid_path;
+XBT_INTERNAL void MC_print_statistics(mc_stats_t stats);
/********************************** Snapshot comparison **********************************/
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;
-extern __thread mc_comparison_times_t mc_comp_times;
-extern __thread double mc_snapshot_comparison_time;
+extern XBT_INTERNAL __thread mc_comparison_times_t mc_comp_times;
+extern XBT_INTERNAL __thread double mc_snapshot_comparison_time;
-int snapshot_compare(void *state1, void *state2);
-void print_comparison_times(void);
+XBT_INTERNAL int snapshot_compare(void *state1, void *state2);
+XBT_INTERNAL void print_comparison_times(void);
//#define MC_DEBUG 1
#define MC_VERBOSE 1
/********************************** 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);
+XBT_INTERNAL void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
/********************************** Miscellaneous **********************************/
dw_type_t type;
void *address;
int region;
-}s_local_variable_t, *local_variable_t;
-
-/* *********** Sets *********** */
-
-typedef struct s_mc_address_set *mc_address_set_t;
-
-mc_address_set_t mc_address_set_new(void);
-void mc_address_set_free(mc_address_set_t* p);
-void mc_address_add(mc_address_set_t p, const void* value);
-bool mc_address_test(mc_address_set_t p, const void* value);
+} s_local_variable_t, *local_variable_t;
/* *********** Hash *********** */
* \param stacks stacks (mc_snapshot_stak_t) used fot the stack unwinding informations
* \result resulting hash
* */
-uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks);
+XBT_INTERNAL uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks);
/** @brief Dump the stacks of the application processes
*
*
* Does not work when an application thread is running.
*/
-void MC_dump_stacks(FILE* file);
+XBT_INTERNAL void MC_dump_stacks(FILE* file);
+
+XBT_INTERNAL void MC_report_assertion_error(void);
+
+XBT_INTERNAL void MC_invalidate_cache(void);
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2014-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 <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <regex.h>
+#include <sys/mman.h> // PROT_*
+
+#include <pthread.h>
+
+#include <libgen.h>
+
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include <xbt/mmalloc.h>
+
+#include "mc_process.h"
+#include "mc_object_info.h"
+#include "mc_address_space.h"
+#include "mc_unw.h"
+#include "mc_snapshot.h"
+#include "mc_ignore.h"
+#include "mc_smx.h"
+#include "mc_server.h"
+
+extern "C" {
+
+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 = {
+ (mc_address_space_class_read_callback_t) &MC_process_read,
+ (mc_address_space_class_get_process_callback_t) 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 = MC_PROCESS_CACHE_FLAG_NONE;
+ 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,
+ "__mmalloc_default_mdp");
+ 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->smx_process_infos = MC_smx_process_info_list_new();
+ process->smx_old_process_infos = MC_smx_process_info_list_new();
+
+ 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);
+
+ xbt_dynar_free(&process->smx_process_infos);
+ xbt_dynar_free(&process->smx_old_process_infos);
+
+ 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 = MC_PROCESS_CACHE_FLAG_NONE;
+
+ free(process->heap);
+ process->heap = NULL;
+
+ free(process->heap_info);
+ process->heap_info = NULL;
+}
+
+void MC_process_refresh_heap(mc_process_t process)
+{
+ xbt_assert(mc_mode == MC_MODE_SERVER);
+ xbt_assert(!MC_process_is_self(process));
+ // Read/dereference/refresh the std_heap pointer:
+ if (!process->heap) {
+ process->heap = (struct mdesc*) malloc(sizeof(struct mdesc));
+ }
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap, process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_DISABLED
+ );
+ process->cache_flags |= MC_PROCESS_CACHE_FLAG_HEAP;
+}
+
+void MC_process_refresh_malloc_info(mc_process_t process)
+{
+ xbt_assert(mc_mode == MC_MODE_SERVER);
+ xbt_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 + 1) * sizeof(malloc_info);
+ process->heap_info = (malloc_info*) realloc(process->heap_info, malloc_info_bytesize);
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap_info,
+ process->heap->heapinfo, malloc_info_bytesize,
+ MC_PROCESS_INDEX_DISABLED);
+ process->cache_flags |= MC_PROCESS_CACHE_FLAG_MALLOC_INFO;
+}
+
+#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;
+
+ for (ssize_t 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 (size_t 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;
+
+ // First lookup the variable in the executable shared object.
+ // A global variable used directly by the executable code from a library
+ // is reinstanciated in the executable memory .data/.bss.
+ // We need to look up the variable in the execvutable first.
+ if (process->binary_info) {
+ mc_object_info_t info = process->binary_info;
+ dw_variable_t var = MC_file_object_info_find_variable_by_name(info, name);
+ if (var)
+ return var;
+ }
+
+ 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;
+}
+
+void MC_process_read_variable(mc_process_t process, const char* name, void* target, size_t size)
+{
+ dw_variable_t var = MC_process_find_variable_by_name(process, name);
+ if (!var->address)
+ xbt_die("No simple location for this variable");
+ if (!var->type->full_type)
+ xbt_die("Partial type for %s, cannot check size", name);
+ if ((size_t) var->type->full_type->byte_size != size)
+ xbt_die("Unexpected size for %s (expected %zi, was %zi)",
+ name, size, (size_t) var->type->full_type->byte_size);
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE, target, var->address, size,
+ MC_PROCESS_INDEX_ANY);
+}
+
+char* MC_process_read_string(mc_process_t process, void* address)
+{
+ if (!address)
+ return NULL;
+ if (MC_process_is_self(process))
+ return strdup((char*) address);
+
+ off_t len = 128;
+ char* res = (char*) malloc(len);
+ off_t off = 0;
+
+ while (1) {
+ ssize_t c = pread(process->memory_file, res + off, len - off, (off_t) address + off);
+ if (c == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ xbt_die("Could not read from from remote process");
+ }
+ if (c==0)
+ xbt_die("Could not read string from remote process");
+
+ void* p = memchr(res + off, '\0', c);
+ if (p)
+ return res;
+
+ off += c;
+ if (off == len) {
+ len *= 2;
+ res = (char*) realloc(res, len);
+ }
+ }
+}
+
+// ***** 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 || (size_t) 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, 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;
+ }
+}
+
+const void* MC_process_read_simple(mc_process_t process,
+ void* local, const void* remote, size_t len)
+{
+ adress_space_read_flags_t flags = MC_ADDRESS_SPACE_READ_FLAGS_NONE;
+ int index = MC_PROCESS_INDEX_ANY;
+ MC_process_read(process, flags, local, remote, len, index);
+ return local;
+}
+
+const void* MC_process_read_dynar_element(mc_process_t process,
+ void* local, const void* remote_dynar, size_t i, size_t len)
+{
+ s_xbt_dynar_t d;
+ MC_process_read_simple(process, &d, remote_dynar, sizeof(d));
+ if (i >= d.used)
+ xbt_die("Out of bound index %zi/%lu", i, d.used);
+ if (len != d.elmsize)
+ xbt_die("Bad size in MC_process_read_dynar_element");
+ MC_process_read_simple(process, local, xbt_dynar_get_ptr(&d, i), len);
+ 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);
+ }
+}
+
+unsigned long MC_process_read_dynar_length(mc_process_t process, const void* remote_dynar)
+{
+ if (!remote_dynar)
+ return 0;
+ unsigned long res;
+ MC_process_read_simple(process, &res,
+ &((xbt_dynar_t)remote_dynar)->used, sizeof(res));
+ return res;
+}
+
+static pthread_once_t zero_buffer_flag = PTHREAD_ONCE_INIT;
+static const void* zero_buffer;
+static const size_t zero_buffer_size = 10 * 4096;
+
+static void MC_zero_buffer_init(void)
+{
+ int fd = open("/dev/zero", O_RDONLY);
+ if (fd<0)
+ xbt_die("Could not open /dev/zero");
+ zero_buffer = mmap(NULL, zero_buffer_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (zero_buffer == MAP_FAILED)
+ xbt_die("Could not map the zero buffer");
+ close(fd);
+}
+
+void MC_process_clear_memory(mc_process_t process, void* remote, size_t len)
+{
+ if (MC_process_is_self(process)) {
+ memset(remote, 0, len);
+ } else {
+ pthread_once(&zero_buffer_flag, MC_zero_buffer_init);
+ while (len) {
+ size_t s = len > zero_buffer_size ? zero_buffer_size : len;
+ MC_process_write(process, zero_buffer, remote, s);
+ remote = (char*) remote + s;
+ len -= s;
+ }
+ }
+}
+
+}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_PROCESS_H
+#define MC_PROCESS_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "simgrid_config.h"
+#include <sys/types.h>
+
+#include <xbt/mmalloc.h>
+
+#ifdef HAVE_MC
+#include "xbt/mmalloc/mmprivate.h"
+#endif
+
+#include <simgrid/simix.h>
+#include "simix/popping_private.h"
+#include "simix/smx_private.h"
+
+#include "mc_forward.h"
+#include "mc_base.h"
+#include "mc_mmalloc.h" // std_heap
+#include "mc_memory_map.h"
+#include "mc_address_space.h"
+#include "mc_protocol.h"
+
+SG_BEGIN_DECL()
+
+int MC_process_vm_open(pid_t pid, int flags);
+
+typedef int mc_process_flags_t;
+#define MC_PROCESS_NO_FLAG 0
+#define MC_PROCESS_SELF_FLAG 1
+
+// Those flags are used to track down which cached information
+// is still up to date and which information needs to be updated.
+typedef int mc_process_cache_flags_t;
+#define MC_PROCESS_CACHE_FLAG_NONE 0
+#define MC_PROCESS_CACHE_FLAG_HEAP 1
+#define MC_PROCESS_CACHE_FLAG_MALLOC_INFO 2
+#define MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES 4
+
+typedef struct s_mc_smx_process_info s_mc_smx_process_info_t, *mc_smx_process_info_t;
+
+/** Representation of a process
+ */
+struct s_mc_process {
+ s_mc_address_space_t address_space;
+ 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;
+
+ /** Copy of `simix_global->process_list`
+ *
+ * See mc_smx.c.
+ */
+ xbt_dynar_t smx_process_infos;
+
+ /** Copy of `simix_global->process_to_destroy`
+ *
+ * See mc_smx.c.
+ */
+ xbt_dynar_t smx_old_process_infos;
+
+ /** State of the cache (which variables are up to date) */
+ mc_process_cache_flags_t cache_flags;
+
+ /** Address of the heap structure in the MCed 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;
+};
+
+XBT_INTERNAL bool MC_is_process(mc_address_space_t p);
+
+MC_SHOULD_BE_INTERNAL void MC_process_init(mc_process_t process, pid_t pid, int sockfd);
+XBT_INTERNAL 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.
+ */
+XBT_INTERNAL 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.
+ * */
+XBT_INTERNAL 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
+ */
+XBT_INTERNAL const void* MC_process_read(mc_process_t process,
+ adress_space_read_flags_t flags,
+ void* local, const void* remote, size_t len,
+ int process_index);
+
+// Simplified versions/wrappers (whould be moved in mc_address_space):
+XBT_INTERNAL const void* MC_process_read_simple(mc_process_t process,
+ void* local, const void* remote, size_t len);
+XBT_INTERNAL const void* MC_process_read_dynar_element(mc_process_t process,
+ void* local, const void* remote_dynar, size_t i, size_t len);
+XBT_INTERNAL unsigned long MC_process_read_dynar_length(mc_process_t process,
+ const void* remote_dynar);
+
+/** 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
+ */
+XBT_INTERNAL void MC_process_write(mc_process_t process,
+ const void* local, void* remote, size_t len);
+
+XBT_INTERNAL void MC_process_clear_memory(mc_process_t process,
+ void* remote, size_t len);
+
+/* Functions, variables of the process: */
+
+XBT_INTERNAL mc_object_info_t MC_process_find_object_info(mc_process_t process, const void* addr);
+XBT_INTERNAL mc_object_info_t MC_process_find_object_info_exec(mc_process_t process, const void* addr);
+XBT_INTERNAL mc_object_info_t MC_process_find_object_info_rw(mc_process_t process, const void* addr);
+
+XBT_INTERNAL dw_frame_t MC_process_find_function(mc_process_t process, const void* ip);
+
+XBT_INTERNAL void MC_process_read_variable(mc_process_t process, const char* name, void* target, size_t size);
+XBT_INTERNAL char* MC_process_read_string(mc_process_t, void* address);
+
+static inline xbt_mheap_t MC_process_get_heap(mc_process_t process)
+{
+ 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 (!(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
+ */
+XBT_INTERNAL dw_variable_t MC_process_find_variable_by_name(mc_process_t process, const char* name);
+
+XBT_INTERNAL void MC_invalidate_cache(void);
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <xbt/log.h>
+
+#include "mc_protocol.h"
+#include "mc_client.h"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_protocol, mc, "Generic MC protocol logic");
+
+int MC_protocol_send(int socket, void* message, size_t size)
+{
+ XBT_DEBUG("Protocol [%s] send %s",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(*(e_mc_message_type*) message));
+
+ while (send(socket, message, size, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ return errno;
+ }
+ return 0;
+}
+
+int MC_protocol_send_simple_message(int socket, e_mc_message_type 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");
+ return 1;
+ }
+
+ s_mc_message_t message;
+ message.type = MC_MESSAGE_NONE;
+
+ ssize_t s;
+ while ((s = MC_receive_message(socket, &message, sizeof(message), 0)) == -1) {
+ if (errno == EINTR)
+ continue;
+ else {
+ XBT_ERROR("Could not receive HELLO message");
+ return 2;
+ }
+ }
+ if ((size_t) s < sizeof(message) || message.type != MC_MESSAGE_HELLO) {
+ XBT_ERROR("Did not receive suitable HELLO message. Who are you?");
+ return 3;
+ }
+
+ return 0;
+}
+
+ssize_t MC_receive_message(int socket, void* message, size_t size, int options)
+{
+ int res = recv(socket, message, size, options);
+ if (res != -1) {
+ XBT_DEBUG("Protocol [%s] received %s",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(*(e_mc_message_type*) message));
+ }
+ return res;
+}
+
+const char* MC_message_type_name(e_mc_message_type type)
+{
+ switch(type) {
+ case MC_MESSAGE_NONE:
+ return "NONE";
+ case MC_MESSAGE_HELLO:
+ return "HELLO";
+ case MC_MESSAGE_CONTINUE:
+ return "CONTINUE";
+ case MC_MESSAGE_IGNORE_HEAP:
+ return "IGNORE_HEAP";
+ case MC_MESSAGE_UNIGNORE_HEAP:
+ return "UNIGNORE_HEAP";
+ case MC_MESSAGE_IGNORE_MEMORY:
+ return "IGNORE_MEMORY";
+ case MC_MESSAGE_STACK_REGION:
+ return "STACK_REGION";
+ case MC_MESSAGE_REGISTER_SYMBOL:
+ return "REGISTER_SYMBOL";
+ case MC_MESSAGE_DEADLOCK_CHECK:
+ return "DEADLOCK_CHECK";
+ case MC_MESSAGE_DEADLOCK_CHECK_REPLY:
+ return "DEADLOCK_CHECK_REPLY";
+ case MC_MESSAGE_WAITING:
+ return "WAITING";
+ case MC_MESSAGE_SIMCALL_HANDLE:
+ return "SIMCALL_HANDLE";
+ case MC_MESSAGE_ASSERTION_FAILED:
+ return "ASSERTION_FAILED";
+ default:
+ return "?";
+ }
+}
+
+const char* MC_mode_name(e_mc_mode_t mode)
+{
+ switch(mode) {
+ case MC_MODE_NONE:
+ return "NONE";
+ case MC_MODE_CLIENT:
+ return "CLIENT";
+ case MC_MODE_SERVER:
+ return "SERVER";
+ default:
+ return "?";
+ }
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_PROTOCOL_H
+#define MC_PROTOCOL_H
+
+#include <xbt/misc.h>
+
+#include "mc/datatypes.h"
+
+SG_BEGIN_DECL()
+
+// ***** Environment variables for passing context to the model-checked process
+
+/** Environment variable name set by `simgrid-mc` to enable MC support in the
+ * children MC processes
+ */
+#define MC_ENV_VARIABLE "SIMGRIC_MC"
+
+/** Environment variable name used to pass the communication socket */
+#define MC_ENV_SOCKET_FD "SIMGRID_MC_SOCKET_FD"
+
+// ***** MC mode
+
+typedef enum {
+ MC_MODE_NONE = 0,
+ MC_MODE_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,
+ MC_MESSAGE_DEADLOCK_CHECK,
+ MC_MESSAGE_DEADLOCK_CHECK_REPLY,
+ MC_MESSAGE_WAITING,
+ MC_MESSAGE_SIMCALL_HANDLE,
+ MC_MESSAGE_ASSERTION_FAILED,
+} 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_int_message {
+ e_mc_message_type type;
+ uint64_t value;
+} s_mc_int_message_t, *mc_int_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_simcall_handle_message {
+ e_mc_message_type type;
+ unsigned long pid;
+ int value;
+} s_mc_simcall_handle_message_t, *mc_simcall_handle_message;
+
+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;
+
+XBT_INTERNAL int MC_protocol_send(int socket, void* message, size_t size);
+XBT_INTERNAL int MC_protocol_send_simple_message(int socket, e_mc_message_type type);
+XBT_INTERNAL int MC_protocol_hello(int socket);
+XBT_INTERNAL ssize_t MC_receive_message(int socket, void* message, size_t size, int options);
+
+XBT_INTERNAL const char* MC_message_type_name(e_mc_message_type type);
+XBT_INTERNAL const char* MC_mode_name(e_mc_mode_t mode);
+
+SG_END_DECL()
+
+#endif
#ifdef HAVE_MC
#include "mc_private.h"
-#include "mc_model_checker.h"
#include "mc_state.h"
+#include "mc_smx.h"
#endif
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_record, mc,
" Logging specific to MC record/replay facility");
xbt_dynar_push(dynar, &item);
// Find next chunk:
- char* end = strchr(current, ';');
+ const char* end = strchr(current, ';');
if(end==NULL)
break;
else
mc_state_t state = (mc_state_t) xbt_fifo_get_item_content(item);
int value = 0;
smx_simcall_t saved_req = MC_state_get_executed_request(state, &value);
- int pid = saved_req->issuer->pid;
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(saved_req);
+ const int pid = issuer->pid;
// Serialization the (pid, value) pair:
const char* sep = (item!=start) ? ";" : "";
{
mc_time = xbt_new0(double, simix_process_maxpid);
}
+
+}
/** Convert a string representation of the path into a array of `s_mc_record_item_t`
*/
-xbt_dynar_t MC_record_from_string(const char* data);
+XBT_INTERNAL xbt_dynar_t MC_record_from_string(const char* data);
/** Generate a string representation
*
* "pid0,value0;pid2,value2;pid3,value3". The value can be
* omitted is it is null.
*/
-char* MC_record_stack_to_string(xbt_fifo_t stack);
+XBT_INTERNAL char* MC_record_stack_to_string(xbt_fifo_t stack);
/** Dump the path represented by a given stack in the log
*/
-void MC_record_dump_path(xbt_fifo_t stack);
+XBT_INTERNAL void MC_record_dump_path(xbt_fifo_t stack);
// ***** Replay
* \param start Array of record item
* \item count Number of record items
*/
-void MC_record_replay(mc_record_item_t start, size_t count);
+XBT_INTERNAL void MC_record_replay(mc_record_item_t start, size_t count);
/** Replay a path represented by a string
*
* \param data String representation of the path
*/
-void MC_record_replay_from_string(const char* data);
+XBT_INTERNAL void MC_record_replay_from_string(const char* data);
-void MC_record_replay_init(void);
+XBT_INTERNAL void MC_record_replay_init(void);
SG_END_DECL()
--- /dev/null
+/* simgrid/modelchecker.h - Formal Verification made possible in SimGrid */
+
+/* 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 <xbt/misc.h>
+
+#ifndef SIMGRID_MC_REPLAY_H
+#define SIMGRID_MC_REPLAY_H
+
+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 int MC_record_replay_is_active(void) {
+ return MC_record_path != 0;
+}
+
+SG_END_DECL()
+
+#endif
+++ /dev/null
-/* Copyright (c) 2008-2014. The SimGrid Team.
- * All rights reserved. */
-
-/* This program is free software; you can redistribute it and/or modify it
- * under the terms of the license (GNU LGPL) which comes with this package. */
-
-#include "mc_request.h"
-#include "mc_safety.h"
-#include "mc_private.h"
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
- "Logging specific to MC (request)");
-
-static char *pointer_to_string(void *pointer);
-static char *buff_size_to_string(size_t size);
-
-int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
-{
- if (mc_reduce_kind == e_mc_reduce_none)
- return TRUE;
-
- if (r1->issuer == r2->issuer)
- return FALSE;
-
- /* Wait with timeout transitions are not considered by the independance theorem, thus we consider them as dependant with all other transitions */
- if ((r1->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r1) > 0)
- || (r2->call == SIMCALL_COMM_WAIT
- && simcall_comm_wait__get__timeout(r2) > 0))
- return TRUE;
-
- if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
- return FALSE;
-
- if ((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
- && r2->call == SIMCALL_COMM_WAIT) {
-
- smx_rdv_t rdv =
- r1->call ==
- SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) :
- simcall_comm_irecv__get__rdv(r1);
-
- if (rdv != simcall_comm_wait__get__comm(r2)->comm.rdv_cpy
- && simcall_comm_wait__get__timeout(r2) <= 0)
- return FALSE;
-
- if ((r1->issuer != simcall_comm_wait__get__comm(r2)->comm.src_proc)
- && (r1->issuer != simcall_comm_wait__get__comm(r2)->comm.dst_proc)
- && simcall_comm_wait__get__timeout(r2) <= 0)
- return FALSE;
-
- if ((r1->call == SIMCALL_COMM_ISEND)
- && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND)
- && (simcall_comm_wait__get__comm(r2)->comm.src_buff !=
- simcall_comm_isend__get__src_buff(r1))
- && simcall_comm_wait__get__timeout(r2) <= 0)
- return FALSE;
-
- if ((r1->call == SIMCALL_COMM_IRECV)
- && (simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE)
- && (simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
- simcall_comm_irecv__get__dst_buff(r1))
- && simcall_comm_wait__get__timeout(r2) <= 0)
- return FALSE;
- }
-
- if ((r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
- && r1->call == SIMCALL_COMM_WAIT) {
-
- smx_rdv_t rdv =
- r2->call ==
- SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) :
- simcall_comm_irecv__get__rdv(r2);
-
- if (rdv != simcall_comm_wait__get__comm(r1)->comm.rdv_cpy
- && simcall_comm_wait__get__timeout(r1) <= 0)
- return FALSE;
-
- if ((r2->issuer != simcall_comm_wait__get__comm(r1)->comm.src_proc)
- && (r2->issuer != simcall_comm_wait__get__comm(r1)->comm.dst_proc)
- && simcall_comm_wait__get__timeout(r1) <= 0)
- return FALSE;
-
- if ((r2->call == SIMCALL_COMM_ISEND)
- && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND)
- && (simcall_comm_wait__get__comm(r1)->comm.src_buff !=
- simcall_comm_isend__get__src_buff(r2))
- && simcall_comm_wait__get__timeout(r1) <= 0)
- return FALSE;
-
- if ((r2->call == SIMCALL_COMM_IRECV)
- && (simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE)
- && (simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
- simcall_comm_irecv__get__dst_buff(r2))
- && simcall_comm_wait__get__timeout(r1) <= 0)
- return FALSE;
- }
-
- /* FIXME: the following rule assumes that the result of the
- * isend/irecv call is not stored in a buffer used in the
- * test call. */
- /*if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
- && r2->call == SIMCALL_COMM_TEST)
- return FALSE; */
-
- /* FIXME: the following rule assumes that the result of the
- * isend/irecv call is not stored in a buffer used in the
- * test call.*/
- /*if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
- && r1->call == SIMCALL_COMM_TEST)
- return FALSE; */
-
- if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
- && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
- && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_WAIT
- && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
- && (simcall_comm_wait__get__comm(r1)->comm.src_proc == NULL
- || simcall_comm_wait__get__comm(r1)->comm.dst_proc == NULL))
- return FALSE;
-
- if (r2->call == SIMCALL_COMM_WAIT
- && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
- && (simcall_comm_wait__get__comm(r2)->comm.src_proc == NULL
- || simcall_comm_wait__get__comm(r2)->comm.dst_proc == NULL))
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
- && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
- simcall_comm_wait__get__comm(r2)->comm.src_buff
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
- simcall_comm_wait__get__comm(r2)->comm.dst_buff)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
- && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
- && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
- && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r2)->comm.src_buff
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r2)->comm.dst_buff
- && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r1)->comm.src_buff)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_TEST &&
- (simcall_comm_test__get__comm(r1) == NULL
- || simcall_comm_test__get__comm(r1)->comm.src_buff == NULL
- || simcall_comm_test__get__comm(r1)->comm.dst_buff == NULL))
- return FALSE;
-
- if (r2->call == SIMCALL_COMM_TEST &&
- (simcall_comm_test__get__comm(r2) == NULL
- || simcall_comm_test__get__comm(r2)->comm.src_buff == NULL
- || simcall_comm_test__get__comm(r2)->comm.dst_buff == NULL))
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
- && simcall_comm_test__get__comm(r1)->comm.src_buff ==
- simcall_comm_wait__get__comm(r2)->comm.src_buff
- && simcall_comm_test__get__comm(r1)->comm.dst_buff ==
- simcall_comm_wait__get__comm(r2)->comm.dst_buff)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
- && simcall_comm_wait__get__comm(r1)->comm.src_buff ==
- simcall_comm_test__get__comm(r2)->comm.src_buff
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff ==
- simcall_comm_test__get__comm(r2)->comm.dst_buff)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
- && simcall_comm_wait__get__comm(r1)->comm.src_buff != NULL
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff != NULL
- && simcall_comm_test__get__comm(r2)->comm.src_buff != NULL
- && simcall_comm_test__get__comm(r2)->comm.dst_buff != NULL
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
- simcall_comm_test__get__comm(r2)->comm.src_buff
- && simcall_comm_wait__get__comm(r1)->comm.dst_buff !=
- simcall_comm_test__get__comm(r2)->comm.dst_buff
- && simcall_comm_test__get__comm(r2)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r1)->comm.src_buff)
- return FALSE;
-
- if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
- && simcall_comm_test__get__comm(r1)->comm.src_buff != NULL
- && simcall_comm_test__get__comm(r1)->comm.dst_buff != NULL
- && simcall_comm_wait__get__comm(r2)->comm.src_buff != NULL
- && simcall_comm_wait__get__comm(r2)->comm.dst_buff != NULL
- && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r2)->comm.src_buff
- && simcall_comm_test__get__comm(r1)->comm.dst_buff !=
- simcall_comm_wait__get__comm(r2)->comm.dst_buff
- && simcall_comm_wait__get__comm(r2)->comm.dst_buff !=
- simcall_comm_test__get__comm(r1)->comm.src_buff)
- return FALSE;
-
-
- return TRUE;
-}
-
-static char *pointer_to_string(void *pointer)
-{
-
- if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
- return bprintf("%p", pointer);
-
- return xbt_strdup("(verbose only)");
-}
-
-static char *buff_size_to_string(size_t buff_size)
-{
-
- if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
- return bprintf("%zu", buff_size);
-
- return xbt_strdup("(verbose only)");
-}
-
-
-char *MC_request_to_string(smx_simcall_t req, int value)
-{
- char *type = NULL, *args = NULL, *str = NULL, *p = NULL, *bs = NULL;
- smx_synchro_t act = NULL;
- smx_mutex_t mutex = NULL;
- size_t size = 0;
-
- switch (req->call) {
- case SIMCALL_COMM_ISEND:
- type = xbt_strdup("iSend");
- p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
- bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
- if (req->issuer->smx_host)
- args =
- bprintf("src=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
- p, bs);
- else
- args =
- bprintf("src=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
- req->issuer->name, p, bs);
- break;
- case SIMCALL_COMM_IRECV:
- size =
- simcall_comm_irecv__get__dst_buff_size(req) ?
- *simcall_comm_irecv__get__dst_buff_size(req) : 0;
- type = xbt_strdup("iRecv");
- p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
- bs = buff_size_to_string(size);
- if (req->issuer->smx_host)
- args =
- bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
- p, bs);
- else
- args =
- bprintf("dst=(%lu)%s, buff=%s, size=%s", req->issuer->pid,
- req->issuer->name, p, bs);
- break;
- case SIMCALL_COMM_WAIT:
- act = simcall_comm_wait__get__comm(req);
- if (value == -1) {
- type = xbt_strdup("WaitTimeout");
- p = pointer_to_string(act);
- args = bprintf("comm=%s", p);
- } else {
- type = xbt_strdup("Wait");
- p = pointer_to_string(act);
- args = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
- act->comm.src_proc ? act->comm.src_proc->pid : 0,
- act->comm.src_proc ? MSG_host_get_name(act->comm.src_proc->
- smx_host) : "",
- act->comm.src_proc ? act->comm.src_proc->name : "",
- act->comm.dst_proc ? act->comm.dst_proc->pid : 0,
- act->comm.dst_proc ? MSG_host_get_name(act->comm.dst_proc->
- smx_host) : "",
- act->comm.dst_proc ? act->comm.dst_proc->name : "");
- }
- break;
- case SIMCALL_COMM_TEST:
- act = simcall_comm_test__get__comm(req);
- if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
- type = xbt_strdup("Test FALSE");
- p = pointer_to_string(act);
- args = bprintf("comm=%s", p);
- } else {
- type = xbt_strdup("Test TRUE");
- p = pointer_to_string(act);
- args = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
- act->comm.src_proc->pid, act->comm.src_proc->name,
- MSG_host_get_name(act->comm.src_proc->smx_host),
- act->comm.dst_proc->pid, act->comm.dst_proc->name,
- MSG_host_get_name(act->comm.dst_proc->smx_host));
- }
- break;
-
- case SIMCALL_COMM_WAITANY:
- type = xbt_strdup("WaitAny");
- if (!xbt_dynar_is_empty(simcall_comm_waitany__get__comms(req))) {
- p = pointer_to_string(xbt_dynar_get_as
- (simcall_comm_waitany__get__comms(req), value,
- smx_synchro_t));
- args =
- bprintf("comm=%s (%d of %lu)", p, value + 1,
- xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
- } else {
- args = bprintf("comm at idx %d", value);
- }
- break;
-
- case SIMCALL_COMM_TESTANY:
- if (value == -1) {
- type = xbt_strdup("TestAny FALSE");
- args = xbt_strdup("-");
- } else {
- type = xbt_strdup("TestAny");
- args =
- bprintf("(%d of %lu)", value + 1,
- xbt_dynar_length(simcall_comm_testany__get__comms(req)));
- }
- break;
-
- case SIMCALL_MUTEX_LOCK:
- mutex = simcall_mutex_lock__get__mutex(req);
- type = xbt_strdup("Mutex LOCK");
- args = bprintf("locked = %d, owner = %d, sleeping = %d", mutex->locked, mutex->owner != NULL ? (int)mutex->owner->pid : -1, xbt_swag_size(mutex->sleeping));
- break;
-
- case SIMCALL_MC_SNAPSHOT:
- type = xbt_strdup("MC_SNAPSHOT");
- args = NULL;
- break;
-
- case SIMCALL_MC_COMPARE_SNAPSHOTS:
- type = xbt_strdup("MC_COMPARE_SNAPSHOTS");
- args = NULL;
- break;
-
- case SIMCALL_MC_RANDOM:
- type = xbt_strdup("MC_RANDOM");
- args = bprintf("%d", value);
- break;
-
- default:
- THROW_UNIMPLEMENTED;
- }
-
- if (args != NULL) {
- str =
- bprintf("[(%lu)%s (%s)] %s(%s)", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
- type, args);
- } else {
- str =
- bprintf("[(%lu)%s (%s)] %s ", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), req->issuer->name,
- type);
- }
-
- xbt_free(args);
- xbt_free(type);
- xbt_free(p);
- xbt_free(bs);
- return str;
-}
-
-unsigned int MC_request_testany_fail(smx_simcall_t req)
-{
- unsigned int cursor;
- smx_synchro_t action;
-
- xbt_dynar_foreach(simcall_comm_testany__get__comms(req), cursor, action) {
- if (action->comm.src_proc && action->comm.dst_proc)
- return FALSE;
- }
-
- return TRUE;
-}
-
-int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
-{
- smx_synchro_t act;
-
- switch (req->call) {
-
- case SIMCALL_COMM_WAIT:
- /* FIXME: check also that src and dst processes are not suspended */
- act = simcall_comm_wait__get__comm(req);
- return (act->comm.src_proc && act->comm.dst_proc);
- break;
-
- case SIMCALL_COMM_WAITANY:
- act =
- xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), idx,
- smx_synchro_t);
- return (act->comm.src_proc && act->comm.dst_proc);
- break;
-
- case SIMCALL_COMM_TESTANY:
- act =
- xbt_dynar_get_as(simcall_comm_testany__get__comms(req), idx,
- smx_synchro_t);
- return (act->comm.src_proc && act->comm.dst_proc);
- break;
-
- default:
- return TRUE;
- }
-}
-
-int MC_process_is_enabled(smx_process_t process)
-{
- return MC_request_is_enabled(&process->simcall);
-}
-
-char *MC_request_get_dot_output(smx_simcall_t req, int value)
-{
-
- char *str = NULL, *label = NULL;
- smx_synchro_t act = NULL;
-
- switch (req->call) {
- case SIMCALL_COMM_ISEND:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] iSend", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] iSend", req->issuer->pid);
- break;
-
- case SIMCALL_COMM_IRECV:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] iRecv", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] iRecv", req->issuer->pid);
- break;
-
- case SIMCALL_COMM_WAIT:
- act = simcall_comm_wait__get__comm(req);
- if (value == -1) {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] WaitTimeout", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] WaitTimeout", req->issuer->pid);
- } else {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host),
- act->comm.src_proc ? act->comm.src_proc->pid : 0,
- act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
- else
- label =
- bprintf("[(%lu)] Wait [(%lu)->(%lu)]", req->issuer->pid,
- act->comm.src_proc ? act->comm.src_proc->pid : 0,
- act->comm.dst_proc ? act->comm.dst_proc->pid : 0);
- }
- break;
-
- case SIMCALL_COMM_TEST:
- act = simcall_comm_test__get__comm(req);
- if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] Test FALSE", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] Test FALSE", req->issuer->pid);
- } else {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] Test TRUE", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] Test TRUE", req->issuer->pid);
- }
- break;
-
- case SIMCALL_COMM_WAITANY:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] WaitAny [%d of %lu]", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), value + 1,
- xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
- else
- label =
- bprintf("[(%lu)] WaitAny [%d of %lu]", req->issuer->pid, value + 1,
- xbt_dynar_length(simcall_comm_waitany__get__comms(req)));
- break;
-
- case SIMCALL_COMM_TESTANY:
- if (value == -1) {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] TestAny FALSE", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] TestAny FALSE", req->issuer->pid);
- } else {
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] TestAny TRUE [%d of %lu]", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), value + 1,
- xbt_dynar_length(simcall_comm_testany__get__comms(req)));
- else
- label =
- bprintf("[(%lu)] TestAny TRUE [%d of %lu]", req->issuer->pid,
- value + 1,
- xbt_dynar_length(simcall_comm_testany__get__comms(req)));
- }
- break;
-
- case SIMCALL_MUTEX_LOCK:
- label = bprintf("[(%lu)] Mutex LOCK", req->issuer->pid);
- break;
-
- case SIMCALL_MC_RANDOM:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] MC_RANDOM (%d)", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host), value);
- else
- label = bprintf("[(%lu)] MC_RANDOM (%d)", req->issuer->pid, value);
- break;
-
- case SIMCALL_MC_SNAPSHOT:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] MC_SNAPSHOT", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] MC_SNAPSHOT", req->issuer->pid);
- break;
-
- case SIMCALL_MC_COMPARE_SNAPSHOTS:
- if (req->issuer->smx_host)
- label =
- bprintf("[(%lu)%s] MC_COMPARE_SNAPSHOTS", req->issuer->pid,
- MSG_host_get_name(req->issuer->smx_host));
- else
- label = bprintf("[(%lu)] MC_COMPARE_SNAPSHOTS", req->issuer->pid);
- break;
-
- default:
- THROW_UNIMPLEMENTED;
- }
-
- str =
- bprintf("label = \"%s\", color = %s, fontcolor = %s", label,
- colors[req->issuer->pid - 1], colors[req->issuer->pid - 1]);
- xbt_free(label);
- return str;
-
-}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <assert.h>
+
+#include "mc_request.h"
+#include "mc_safety.h"
+#include "mc_private.h"
+#include "mc_smx.h"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_request, mc,
+ "Logging specific to MC (request)");
+
+static char *pointer_to_string(void *pointer);
+static char *buff_size_to_string(size_t size);
+
+// Those are MC_state_get_internal_request(state)
+int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2)
+{
+ if (mc_reduce_kind == e_mc_reduce_none)
+ return TRUE;
+
+ if (r1->issuer == r2->issuer)
+ return FALSE;
+
+ /* Wait with timeout transitions are not considered by the independance theorem, thus we consider them as dependant with all other transitions */
+ if ((r1->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r1) > 0)
+ || (r2->call == SIMCALL_COMM_WAIT
+ && simcall_comm_wait__get__timeout(r2) > 0))
+ return TRUE;
+
+ if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
+ return FALSE;
+
+ // Those are internal requests, we do not need indirection
+ // because those objects are copies:
+ smx_synchro_t synchro1 = NULL, synchro2 = NULL;
+ if (r1->call == SIMCALL_COMM_WAIT) {
+ synchro1 = simcall_comm_wait__get__comm(r1);
+ }
+ if (r2->call == SIMCALL_COMM_WAIT) {
+ synchro2 = simcall_comm_wait__get__comm(r2);
+ }
+ if (r1->call == SIMCALL_COMM_TEST) {
+ synchro1 = simcall_comm_test__get__comm(r1);
+ }
+ if (r2->call == SIMCALL_COMM_TEST) {
+ synchro2 = simcall_comm_test__get__comm(r2);
+ }
+
+ if ((r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
+ && r2->call == SIMCALL_COMM_WAIT) {
+
+ smx_rdv_t rdv =
+ r1->call ==
+ SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) :
+ simcall_comm_irecv__get__rdv(r1);
+
+ if (rdv != synchro2->comm.rdv_cpy
+ && simcall_comm_wait__get__timeout(r2) <= 0)
+ return FALSE;
+
+ if ((r1->issuer != synchro2->comm.src_proc)
+ && (r1->issuer != synchro2->comm.dst_proc)
+ && simcall_comm_wait__get__timeout(r2) <= 0)
+ return FALSE;
+
+ if ((r1->call == SIMCALL_COMM_ISEND)
+ && (synchro2->comm.type == SIMIX_COMM_SEND)
+ && (synchro2->comm.src_buff !=
+ simcall_comm_isend__get__src_buff(r1))
+ && simcall_comm_wait__get__timeout(r2) <= 0)
+ return FALSE;
+
+ if ((r1->call == SIMCALL_COMM_IRECV)
+ && (synchro2->comm.type == SIMIX_COMM_RECEIVE)
+ && (synchro2->comm.dst_buff != simcall_comm_irecv__get__dst_buff(r1))
+ && simcall_comm_wait__get__timeout(r2) <= 0)
+ return FALSE;
+ }
+
+ if ((r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
+ && r1->call == SIMCALL_COMM_WAIT) {
+
+ smx_rdv_t rdv =
+ r2->call ==
+ SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) :
+ simcall_comm_irecv__get__rdv(r2);
+
+ if (rdv != synchro1->comm.rdv_cpy
+ && simcall_comm_wait__get__timeout(r1) <= 0)
+ return FALSE;
+
+ if ((r2->issuer != synchro1->comm.src_proc)
+ && (r2->issuer != synchro1->comm.dst_proc)
+ && simcall_comm_wait__get__timeout(r1) <= 0)
+ return FALSE;
+
+ if ((r2->call == SIMCALL_COMM_ISEND)
+ && (synchro1->comm.type == SIMIX_COMM_SEND)
+ && (synchro1->comm.src_buff !=
+ simcall_comm_isend__get__src_buff(r2))
+ && simcall_comm_wait__get__timeout(r1) <= 0)
+ return FALSE;
+
+ if ((r2->call == SIMCALL_COMM_IRECV)
+ && (synchro1->comm.type == SIMIX_COMM_RECEIVE)
+ && (synchro1->comm.dst_buff !=
+ simcall_comm_irecv__get__dst_buff(r2))
+ && simcall_comm_wait__get__timeout(r1) <= 0)
+ return FALSE;
+ }
+
+ /* FIXME: the following rule assumes that the result of the
+ * isend/irecv call is not stored in a buffer used in the
+ * test call. */
+ /*if( (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
+ && r2->call == SIMCALL_COMM_TEST)
+ return FALSE; */
+
+ /* FIXME: the following rule assumes that the result of the
+ * isend/irecv call is not stored in a buffer used in the
+ * test call.*/
+ /*if( (r2->call == SIMCALL_COMM_ISEND || r2->call == SIMCALL_COMM_IRECV)
+ && r1->call == SIMCALL_COMM_TEST)
+ return FALSE; */
+
+ if (r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_ISEND
+ && simcall_comm_isend__get__rdv(r1) != simcall_comm_isend__get__rdv(r2))
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_IRECV
+ && simcall_comm_irecv__get__rdv(r1) != simcall_comm_irecv__get__rdv(r2))
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_WAIT
+ && (r2->call == SIMCALL_COMM_WAIT || r2->call == SIMCALL_COMM_TEST)
+ && (synchro1->comm.src_proc == NULL || synchro1->comm.dst_proc == NULL))
+ return FALSE;
+
+ if (r2->call == SIMCALL_COMM_WAIT
+ && (r1->call == SIMCALL_COMM_WAIT || r1->call == SIMCALL_COMM_TEST)
+ && (synchro2->comm.src_proc == NULL || synchro2->comm.dst_proc == NULL))
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
+ && synchro1->comm.src_buff == synchro2->comm.src_buff
+ && synchro2->comm.dst_buff == synchro2->comm.dst_buff)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_WAIT
+ && synchro1->comm.src_buff != NULL
+ && synchro1->comm.dst_buff != NULL
+ && synchro2->comm.src_buff != NULL
+ && synchro2->comm.dst_buff != NULL
+ && synchro1->comm.dst_buff != synchro2->comm.src_buff
+ && synchro1->comm.dst_buff != synchro2->comm.dst_buff
+ && synchro2->comm.dst_buff != synchro1->comm.src_buff)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_TEST &&
+ (simcall_comm_test__get__comm(r1) == NULL
+ || synchro1->comm.src_buff == NULL
+ || synchro1->comm.dst_buff == NULL))
+ return FALSE;
+
+ if (r2->call == SIMCALL_COMM_TEST &&
+ (simcall_comm_test__get__comm(r2) == NULL
+ || synchro2->comm.src_buff == NULL
+ || synchro2->comm.dst_buff == NULL))
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
+ && synchro1->comm.src_buff == synchro2->comm.src_buff
+ && synchro1->comm.dst_buff == synchro2->comm.dst_buff)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
+ && synchro1->comm.src_buff == synchro2->comm.src_buff
+ && synchro1->comm.dst_buff == synchro2->comm.dst_buff)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_WAIT && r2->call == SIMCALL_COMM_TEST
+ && synchro1->comm.src_buff != NULL
+ && synchro1->comm.dst_buff != NULL
+ && synchro2->comm.src_buff != NULL
+ && synchro2->comm.dst_buff != NULL
+ && synchro1->comm.dst_buff != synchro2->comm.src_buff
+ && synchro1->comm.dst_buff != synchro2->comm.dst_buff
+ && synchro2->comm.dst_buff != synchro1->comm.src_buff)
+ return FALSE;
+
+ if (r1->call == SIMCALL_COMM_TEST && r2->call == SIMCALL_COMM_WAIT
+ && synchro1->comm.src_buff != NULL
+ && synchro1->comm.dst_buff != NULL
+ && synchro2->comm.src_buff != NULL
+ && synchro2->comm.dst_buff != NULL
+ && synchro1->comm.dst_buff != synchro2->comm.src_buff
+ && synchro1->comm.dst_buff != synchro2->comm.dst_buff
+ && synchro2->comm.dst_buff != synchro1->comm.src_buff)
+ return FALSE;
+
+ return TRUE;
+}
+
+static char *pointer_to_string(void *pointer)
+{
+
+ if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
+ return bprintf("%p", pointer);
+
+ return xbt_strdup("(verbose only)");
+}
+
+static char *buff_size_to_string(size_t buff_size)
+{
+
+ if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose))
+ return bprintf("%zu", buff_size);
+
+ return xbt_strdup("(verbose only)");
+}
+
+
+char *MC_request_to_string(smx_simcall_t req, int value, e_mc_request_type_t request_type)
+{
+ bool use_remote_comm = true;
+ switch(request_type) {
+ case MC_REQUEST_SIMIX:
+ use_remote_comm = true;
+ break;
+ case MC_REQUEST_EXECUTED:
+ case MC_REQUEST_INTERNAL:
+ use_remote_comm = false;
+ break;
+ }
+
+ const char* type = NULL;
+ char *args = NULL;
+
+ smx_process_t issuer = MC_smx_simcall_get_issuer(req);
+
+ switch (req->call) {
+
+ case SIMCALL_COMM_ISEND: {
+ type = "iSend";
+ char* p = pointer_to_string(simcall_comm_isend__get__src_buff(req));
+ char* bs = buff_size_to_string(simcall_comm_isend__get__src_buff_size(req));
+ if (issuer->smx_host)
+ args =
+ bprintf("src=(%lu)%s (%s), buff=%s, size=%s", issuer->pid,
+ MC_smx_process_get_host_name(issuer),
+ MC_smx_process_get_name(issuer),
+ p, bs);
+ else
+ args =
+ bprintf("src=(%lu)%s, buff=%s, size=%s", issuer->pid,
+ MC_smx_process_get_name(issuer), p, bs);
+ xbt_free(bs);
+ xbt_free(p);
+ break;
+ }
+
+ case SIMCALL_COMM_IRECV: {
+ size_t* remote_size = simcall_comm_irecv__get__dst_buff_size(req);
+
+ // size_t size = size_pointer ? *size_pointer : 0;
+ size_t size = 0;
+ if (remote_size)
+ MC_process_read_simple(&mc_model_checker->process(), &size,
+ remote_size, sizeof(size));
+
+ type = "iRecv";
+ char* p = pointer_to_string(simcall_comm_irecv__get__dst_buff(req));
+ char* bs = buff_size_to_string(size);
+ if (issuer->smx_host)
+ args =
+ bprintf("dst=(%lu)%s (%s), buff=%s, size=%s", issuer->pid,
+ MC_smx_process_get_host_name(issuer),
+ MC_smx_process_get_name(issuer),
+ p, bs);
+ else
+ args =
+ bprintf("dst=(%lu)%s, buff=%s, size=%s", issuer->pid,
+ MC_smx_process_get_name(issuer),
+ p, bs);
+ xbt_free(bs);
+ xbt_free(p);
+ break;
+ }
+
+ case SIMCALL_COMM_WAIT: {
+ smx_synchro_t remote_act = simcall_comm_wait__get__comm(req);
+ char* p;
+ if (value == -1) {
+ type = "WaitTimeout";
+ p = pointer_to_string(remote_act);
+ args = bprintf("comm=%s", p);
+ } else {
+ type = "Wait";
+ p = pointer_to_string(remote_act);
+
+ s_smx_synchro_t synchro;
+ smx_synchro_t act;
+ if (use_remote_comm) {
+ MC_process_read_simple(&mc_model_checker->process(), &synchro,
+ remote_act, sizeof(synchro));
+ act = &synchro;
+ } else
+ act = remote_act;
+
+ smx_process_t src_proc = MC_smx_resolve_process(act->comm.src_proc);
+ smx_process_t dst_proc = MC_smx_resolve_process(act->comm.dst_proc);
+ args = bprintf("comm=%s [(%lu)%s (%s)-> (%lu)%s (%s)]", p,
+ src_proc ? src_proc->pid : 0,
+ src_proc ? MC_smx_process_get_host_name(src_proc) : "",
+ src_proc ? MC_smx_process_get_name(src_proc) : "",
+ dst_proc ? dst_proc->pid : 0,
+ dst_proc ? MC_smx_process_get_host_name(dst_proc) : "",
+ dst_proc ? MC_smx_process_get_name(dst_proc) : "");
+ }
+ xbt_free(p);
+ break;
+ }
+
+ case SIMCALL_COMM_TEST: {
+ smx_synchro_t remote_act = simcall_comm_test__get__comm(req);
+ s_smx_synchro_t synchro;
+ smx_synchro_t act;
+ if (use_remote_comm) {
+ MC_process_read_simple(&mc_model_checker->process(), &synchro,
+ remote_act, sizeof(synchro));
+ act = &synchro;
+ } else
+ act = remote_act;
+
+ char* p;
+ if (act->comm.src_proc == NULL || act->comm.dst_proc == NULL) {
+ type = "Test FALSE";
+ p = pointer_to_string(remote_act);
+ args = bprintf("comm=%s", p);
+ } else {
+ type = "Test TRUE";
+ p = pointer_to_string(remote_act);
+
+ smx_process_t src_proc = MC_smx_resolve_process(act->comm.src_proc);
+ smx_process_t dst_proc = MC_smx_resolve_process(act->comm.dst_proc);
+ args = bprintf("comm=%s [(%lu)%s (%s) -> (%lu)%s (%s)]", p,
+ src_proc->pid,
+ MC_smx_process_get_name(src_proc),
+ MC_smx_process_get_host_name(src_proc),
+ dst_proc->pid,
+ MC_smx_process_get_name(dst_proc),
+ MC_smx_process_get_host_name(dst_proc));
+ }
+ xbt_free(p);
+ break;
+ }
+
+ case SIMCALL_COMM_WAITANY: {
+ type = "WaitAny";
+ s_xbt_dynar_t comms;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &comms, simcall_comm_waitany__get__comms(req), sizeof(comms));
+ if (!xbt_dynar_is_empty(&comms)) {
+ smx_synchro_t remote_sync;
+ MC_process_read_dynar_element(&mc_model_checker->process(),
+ &remote_sync, simcall_comm_waitany__get__comms(req), value,
+ sizeof(remote_sync));
+ char* p = pointer_to_string(remote_sync);
+ args = bprintf("comm=%s (%d of %lu)",
+ p, value + 1, xbt_dynar_length(&comms));
+ xbt_free(p);
+ } else {
+ args = bprintf("comm at idx %d", value);
+ }
+ break;
+ }
+
+ case SIMCALL_COMM_TESTANY:
+ if (value == -1) {
+ type = "TestAny FALSE";
+ args = xbt_strdup("-");
+ } else {
+ type = "TestAny";
+ args =
+ bprintf("(%d of %lu)", value + 1,
+ MC_process_read_dynar_length(&mc_model_checker->process(),
+ simcall_comm_testany__get__comms(req)));
+ }
+ break;
+
+ case SIMCALL_MUTEX_LOCK: {
+ type = "Mutex LOCK";
+
+ s_smx_mutex_t mutex;
+ MC_process_read_simple(&mc_model_checker->process(), &mutex,
+ simcall_mutex_lock__get__mutex(req), sizeof(mutex));
+ s_xbt_swag_t mutex_sleeping;
+ MC_process_read_simple(&mc_model_checker->process(), &mutex_sleeping,
+ mutex.sleeping, sizeof(mutex_sleeping));
+
+ args = bprintf("locked = %d, owner = %d, sleeping = %d",
+ mutex.locked,
+ mutex.owner != NULL ? (int) MC_smx_resolve_process(mutex.owner)->pid : -1,
+ mutex_sleeping.count);
+ break;
+ }
+
+ case SIMCALL_MC_SNAPSHOT:
+ type = "MC_SNAPSHOT";
+ args = NULL;
+ break;
+
+ case SIMCALL_MC_COMPARE_SNAPSHOTS:
+ type = "MC_COMPARE_SNAPSHOTS";
+ args = NULL;
+ break;
+
+ case SIMCALL_MC_RANDOM:
+ type = "MC_RANDOM";
+ args = bprintf("%d", value);
+ break;
+
+ default:
+ THROW_UNIMPLEMENTED;
+ }
+
+ char* str;
+ if (args != NULL) {
+ str =
+ bprintf("[(%lu)%s (%s)] %s(%s)", issuer->pid,
+ MC_smx_process_get_host_name(issuer),
+ MC_smx_process_get_name(issuer),
+ type, args);
+ } else {
+ str =
+ bprintf("[(%lu)%s (%s)] %s ", issuer->pid,
+ MC_smx_process_get_host_name(issuer),
+ MC_smx_process_get_name(issuer),
+ type);
+ }
+ xbt_free(args);
+ return str;
+}
+
+unsigned int MC_request_testany_fail(smx_simcall_t req)
+{
+ // Remote xbt_dynar_foreach on simcall_comm_testany__get__comms(req).
+
+ // Read the dynar:
+ s_xbt_dynar_t comms;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &comms, simcall_comm_testany__get__comms(req), sizeof(comms));
+
+ // Read ther dynar buffer:
+ size_t buffer_size = comms.elmsize * comms.used;
+ char buffer[buffer_size];
+ MC_process_read_simple(&mc_model_checker->process(),
+ buffer, comms.data, buffer_size);
+
+ // Iterate over the elements:
+ assert(comms.elmsize == sizeof(smx_synchro_t));
+ unsigned cursor;
+ for (cursor=0; cursor != comms.used; ++cursor) {
+
+ // Get the element:
+ smx_synchro_t remote_action = NULL;
+ memcpy(&remote_action, buffer + comms.elmsize * cursor, sizeof(remote_action));
+
+ // Dereference the pointer:
+ s_smx_synchro_t action;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &action, remote_action, sizeof(action));
+
+ // Finally so something useful about it:
+ if (action.comm.src_proc && action.comm.dst_proc)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
+{
+ smx_synchro_t remote_act = NULL;
+ switch (req->call) {
+
+ case SIMCALL_COMM_WAIT:
+ /* FIXME: check also that src and dst processes are not suspended */
+ remote_act = simcall_comm_wait__get__comm(req);
+ break;
+
+ case SIMCALL_COMM_WAITANY: {
+ MC_process_read_dynar_element(
+ &mc_model_checker->process(), &remote_act, simcall_comm_waitany__get__comms(req),
+ idx, sizeof(remote_act));
+ }
+ break;
+
+ case SIMCALL_COMM_TESTANY: {
+ MC_process_read_dynar_element(
+ &mc_model_checker->process(), &remote_act, simcall_comm_testany__get__comms(req),
+ idx, sizeof(remote_act));
+ }
+ break;
+
+ default:
+ return TRUE;
+ }
+
+ s_smx_synchro_t synchro;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &synchro, remote_act, sizeof(synchro));
+ return synchro.comm.src_proc && synchro.comm.dst_proc;
+}
+
+int MC_process_is_enabled(smx_process_t process)
+{
+ return MC_request_is_enabled(&process->simcall);
+}
+
+char *MC_request_get_dot_output(smx_simcall_t req, int value)
+{
+ char *label = NULL;
+
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(req);
+
+ switch (req->call) {
+ case SIMCALL_COMM_ISEND:
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] iSend", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] iSend", issuer->pid);
+ break;
+
+ case SIMCALL_COMM_IRECV:
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] iRecv", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] iRecv", issuer->pid);
+ break;
+
+ case SIMCALL_COMM_WAIT: {
+ if (value == -1) {
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] WaitTimeout", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] WaitTimeout", issuer->pid);
+ } else {
+ smx_synchro_t remote_act = simcall_comm_wait__get__comm(req);
+ s_smx_synchro_t synchro;
+ MC_process_read_simple(&mc_model_checker->process(), &synchro,
+ remote_act, sizeof(synchro));
+
+ smx_process_t src_proc = MC_smx_resolve_process(synchro.comm.src_proc);
+ smx_process_t dst_proc = MC_smx_resolve_process(synchro.comm.dst_proc);
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] Wait [(%lu)->(%lu)]", issuer->pid,
+ MC_smx_process_get_host_name(issuer),
+ src_proc ? src_proc->pid : 0,
+ dst_proc ? dst_proc->pid : 0);
+ else
+ label =
+ bprintf("[(%lu)] Wait [(%lu)->(%lu)]", issuer->pid,
+ src_proc ? src_proc->pid : 0,
+ dst_proc ? dst_proc->pid : 0);
+ }
+ break;
+ }
+
+ case SIMCALL_COMM_TEST: {
+ smx_synchro_t remote_act = simcall_comm_test__get__comm(req);
+ s_smx_synchro_t synchro;
+ MC_process_read_simple(&mc_model_checker->process(), &synchro,
+ remote_act, sizeof(synchro));
+ if (synchro.comm.src_proc == NULL || synchro.comm.dst_proc == NULL) {
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] Test FALSE", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] Test FALSE", issuer->pid);
+ } else {
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] Test TRUE", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] Test TRUE", issuer->pid);
+ }
+ break;
+ }
+
+ case SIMCALL_COMM_WAITANY: {
+ unsigned long comms_size = MC_process_read_dynar_length(
+ &mc_model_checker->process(), simcall_comm_waitany__get__comms(req));
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] WaitAny [%d of %lu]", issuer->pid,
+ MC_smx_process_get_host_name(issuer), value + 1,
+ comms_size);
+ else
+ label =
+ bprintf("[(%lu)] WaitAny [%d of %lu]", issuer->pid, value + 1,
+ comms_size);
+ break;
+ }
+
+ case SIMCALL_COMM_TESTANY:
+ if (value == -1) {
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] TestAny FALSE", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] TestAny FALSE", issuer->pid);
+ } else {
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] TestAny TRUE [%d of %lu]", issuer->pid,
+ MC_smx_process_get_host_name(issuer), value + 1,
+ xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+ else
+ label =
+ bprintf("[(%lu)] TestAny TRUE [%d of %lu]", issuer->pid,
+ value + 1,
+ xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+ }
+ break;
+
+ case SIMCALL_MUTEX_LOCK:
+ label = bprintf("[(%lu)] Mutex LOCK", req->issuer->pid);
+ break;
+
+ case SIMCALL_MC_RANDOM:
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] MC_RANDOM (%d)", issuer->pid,
+ MC_smx_process_get_host_name(issuer), value);
+ else
+ label = bprintf("[(%lu)] MC_RANDOM (%d)", issuer->pid, value);
+ break;
+
+ case SIMCALL_MC_SNAPSHOT:
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] MC_SNAPSHOT", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] MC_SNAPSHOT", issuer->pid);
+ break;
+
+ case SIMCALL_MC_COMPARE_SNAPSHOTS:
+ if (issuer->smx_host)
+ label =
+ bprintf("[(%lu)%s] MC_COMPARE_SNAPSHOTS", issuer->pid,
+ MC_smx_process_get_host_name(issuer));
+ else
+ label = bprintf("[(%lu)] MC_COMPARE_SNAPSHOTS", issuer->pid);
+ break;
+
+ default:
+ THROW_UNIMPLEMENTED;
+ }
+
+ char* str =
+ bprintf("label = \"%s\", color = %s, fontcolor = %s", label,
+ colors[issuer->pid - 1], colors[issuer->pid - 1]);
+ xbt_free(label);
+ return str;
+
+}
+
+}
SG_BEGIN_DECL()
-int MC_request_depend(smx_simcall_t req1, smx_simcall_t req2);
-char* MC_request_to_string(smx_simcall_t req, int value);
-unsigned int MC_request_testany_fail(smx_simcall_t req);
+typedef enum e_mc_request_type {
+ MC_REQUEST_SIMIX,
+ MC_REQUEST_EXECUTED,
+ MC_REQUEST_INTERNAL,
+} e_mc_request_type_t;
+
+XBT_INTERNAL int MC_request_depend(smx_simcall_t req1, smx_simcall_t req2);
+XBT_INTERNAL char* MC_request_to_string(smx_simcall_t req, int value, e_mc_request_type_t type);
+XBT_INTERNAL unsigned int MC_request_testany_fail(smx_simcall_t req);
/*int MC_waitany_is_enabled_by_comm(smx_req_t req, unsigned int comm);*/
-int MC_request_is_visible(smx_simcall_t req);
+XBT_INTERNAL int MC_request_is_visible(smx_simcall_t req);
/** Can this requests can be executed.
*
* have both a source and a destination yet is not enabled
* (unless timeout is enabled in the wait and enabeld in SimGridMC).
*/
-int MC_request_is_enabled(smx_simcall_t req);
-int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx);
+XBT_INTERNAL int MC_request_is_enabled(smx_simcall_t req);
+XBT_INTERNAL int MC_request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx);
/** Is the process ready to execute its simcall?
*
* This is true if the request associated with the process is ready.
*/
-int MC_process_is_enabled(smx_process_t process);
+XBT_INTERNAL int MC_process_is_enabled(smx_process_t process);
-char *MC_request_get_dot_output(smx_simcall_t req, int value);
+XBT_INTERNAL char *MC_request_get_dot_output(smx_simcall_t req, int value);
SG_END_DECL()
/* 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 <assert.h>
+
#include "mc_state.h"
#include "mc_request.h"
#include "mc_safety.h"
#include "mc_private.h"
#include "mc_record.h"
+#include "mc_smx.h"
+#include "mc_client.h"
#include "xbt/mmalloc/mmprivate.h"
+extern "C" {
+
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_safety, mc,
"Logging specific to MC safety verification ");
/**
* \brief Initialize the DPOR exploration algorithm
*/
-void MC_pre_modelcheck_safety()
+static 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;
-
if (_sg_mc_visited > 0)
visited_states = xbt_dynar_new(sizeof(mc_visited_state_t), visited_state_free_voidp);
- initial_state = MC_state_new();
-
- MC_SET_STD_HEAP;
+ mc_state_t initial_state = MC_state_new();
XBT_DEBUG("**************************************************");
XBT_DEBUG("Initial state");
/* Wait for requests (schedules processes) */
MC_wait_for_requests();
- MC_SET_MC_HEAP;
-
/* Get an enabled process and insert it in the interleave set of the initial state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ smx_process_t process;
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(initial_state, process);
if (mc_reduce_kind != e_mc_reduce_none)
break;
}
- }
+ );
xbt_fifo_unshift(mc_stack, initial_state);
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
}
/** \brief Model-check the application using a DFS exploration
* with DPOR (Dynamic Partial Order Reductions)
*/
-void MC_modelcheck_safety(void)
+static void MC_modelcheck_safety_main(void)
{
-
char *req_str = NULL;
int value;
- smx_simcall_t req = NULL, prev_req = NULL;
+ smx_simcall_t req = NULL;
mc_state_t state = NULL, prev_state = NULL, next_state = NULL;
- smx_process_t process = NULL;
xbt_fifo_item_t item = NULL;
mc_visited_state_t visited_state = NULL;
if (xbt_fifo_size(mc_stack) <= _sg_mc_max_depth && !user_max_depth_reached
&& (req = MC_state_get_request(state, &value)) && visited_state == NULL) {
- char* req_str = MC_request_to_string(req, value);
- XBT_DEBUG("Execute: %s", req_str);
+ req_str = MC_request_to_string(req, value, MC_REQUEST_SIMIX);
+ XBT_DEBUG("Execute: %s", req_str);
xbt_free(req_str);
if (dot_output != NULL) {
- MC_SET_MC_HEAP;
req_str = MC_request_get_dot_output(req, value);
- MC_SET_STD_HEAP;
}
MC_state_set_executed_request(state, req, value);
mc_stats->executed_transitions++;
- /* Answer the request */
- SIMIX_simcall_handle(req, value);
+ // TODO, bundle both operations in a single message
+ // MC_execute_transition(req, value)
- /* Wait for requests (schedules processes) */
+ /* Answer the request */
+ MC_simcall_handle(req, value);
MC_wait_for_requests();
/* Create the new expanded state */
- MC_SET_MC_HEAP;
-
next_state = MC_state_new();
if(_sg_mc_termination && is_exploration_stack_state(next_state)){
if ((visited_state = is_visited_state(next_state)) == NULL) {
/* Get an enabled process and insert it in the interleave set of the next state */
- xbt_swag_foreach(process, simix_global->process_list) {
+ smx_process_t process = NULL;
+ MC_EACH_SIMIX_PROCESS(process,
if (MC_process_is_enabled(process)) {
MC_state_interleave_process(next_state, process);
if (mc_reduce_kind != e_mc_reduce_none)
break;
}
- }
+ );
if (dot_output != NULL)
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, next_state->num, req_str);
if (dot_output != NULL)
xbt_free(req_str);
- MC_SET_STD_HEAP;
-
/* Let's loop again */
/* The interleave set is empty or the maximum depth is reached, let's back-track */
}
- MC_SET_MC_HEAP;
-
/* Trash the current state, no longer needed */
xbt_fifo_shift(mc_stack);
- MC_state_delete(state, !state->in_visited_states ? 1 : 0);
XBT_DEBUG("Delete state %d at depth %d", state->num, xbt_fifo_size(mc_stack) + 1);
-
- MC_SET_STD_HEAP;
+ MC_state_delete(state, !state->in_visited_states ? 1 : 0);
visited_state = NULL;
return;
}
- MC_SET_MC_HEAP;
/* Traverse the stack backwards until a state with a non empty interleave
set is found, deleting all the states that have it empty in the way.
For each deleted state, check if the request that has generated it
executed before it. If it does then add it to the interleave set of the
state that executed that previous request. */
- while ((state = xbt_fifo_shift(mc_stack)) != NULL) {
+ while ((state = (mc_state_t) xbt_fifo_shift(mc_stack))) {
if (mc_reduce_kind == e_mc_reduce_dpor) {
req = MC_state_get_internal_request(state);
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(req);
xbt_fifo_foreach(mc_stack, item, prev_state, mc_state_t) {
if (MC_request_depend(req, MC_state_get_internal_request(prev_state))) {
if (XBT_LOG_ISENABLED(mc_safety, xbt_log_priority_debug)) {
XBT_DEBUG("Dependent Transitions:");
- prev_req = MC_state_get_executed_request(prev_state, &value);
- req_str = MC_request_to_string(prev_req, value);
+ smx_simcall_t prev_req = MC_state_get_executed_request(prev_state, &value);
+ req_str = MC_request_to_string(prev_req, value, MC_REQUEST_INTERNAL);
XBT_DEBUG("%s (state=%d)", req_str, prev_state->num);
xbt_free(req_str);
prev_req = MC_state_get_executed_request(state, &value);
- req_str = MC_request_to_string(prev_req, value);
+ req_str = MC_request_to_string(prev_req, value, MC_REQUEST_EXECUTED);
XBT_DEBUG("%s (state=%d)", req_str, state->num);
xbt_free(req_str);
}
- if (!MC_state_process_is_done(prev_state, req->issuer))
- MC_state_interleave_process(prev_state, req->issuer);
+ if (!MC_state_process_is_done(prev_state, issuer))
+ MC_state_interleave_process(prev_state, issuer);
else
XBT_DEBUG("Process %p is in done set", req->issuer);
} else {
+ const smx_process_t previous_issuer = MC_smx_simcall_get_issuer(MC_state_get_internal_request(prev_state));
XBT_DEBUG("Simcall %d, process %lu (state %d) and simcall %d, process %lu (state %d) are independant",
- req->call, req->issuer->pid, state->num,
+ req->call, issuer->pid, state->num,
MC_state_get_internal_request(prev_state)->call,
- MC_state_get_internal_request(prev_state)->issuer->pid,
+ previous_issuer->pid,
prev_state->num);
}
MC_state_delete(state, !state->in_visited_states ? 1 : 0);
}
}
- MC_SET_STD_HEAP;
}
}
MC_print_statistics(mc_stats);
- MC_SET_STD_HEAP;
-
return;
}
+
+void MC_modelcheck_safety(void)
+{
+ if(_sg_mc_termination)
+ mc_reduce_kind = e_mc_reduce_none;
+ else if (mc_reduce_kind == e_mc_reduce_unset)
+ mc_reduce_kind = e_mc_reduce_dpor;
+ _sg_mc_safety = 1;
+ if (_sg_mc_termination)
+ XBT_INFO("Check non progressive cycles");
+ else
+ XBT_INFO("Check a safety property");
+ MC_wait_for_requests();
+
+ XBT_DEBUG("Starting the safety algorithm");
+
+ _sg_mc_safety = 1;
+
+ /* Create exploration stack */
+ mc_stack = xbt_fifo_new();
+
+ MC_pre_modelcheck_safety();
+
+ /* Save the initial state */
+ initial_global_state = xbt_new0(s_mc_global_t, 1);
+ initial_global_state->snapshot = MC_take_snapshot(0);
+
+ MC_modelcheck_safety_main();
+
+ xbt_abort();
+ //MC_exit();
+}
+
+}
#include <simgrid_config.h>
#include <xbt/dict.h>
-#include "mc_interface.h"
+#include "mc_forward.h"
#include "mc_state.h"
SG_BEGIN_DECL()
e_mc_reduce_dpor
} e_mc_reduce_t;
-extern e_mc_reduce_t mc_reduce_kind;
+extern XBT_INTERNAL e_mc_reduce_t mc_reduce_kind;
-void MC_pre_modelcheck_safety(void);
void MC_modelcheck_safety(void);
typedef struct s_mc_visited_state{
int other_num; // dot_output for
}s_mc_visited_state_t, *mc_visited_state_t;
-extern xbt_dynar_t visited_states;
-mc_visited_state_t is_visited_state(mc_state_t graph_state);
-void visited_state_free(mc_visited_state_t state);
-void visited_state_free_voidp(void *s);
+extern XBT_INTERNAL xbt_dynar_t visited_states;
+XBT_INTERNAL mc_visited_state_t is_visited_state(mc_state_t graph_state);
+XBT_INTERNAL void visited_state_free(mc_visited_state_t state);
+XBT_INTERNAL void visited_state_free_voidp(void *s);
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <memory>
+#include <system_error>
+
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/signalfd.h>
+
+#include <xbt/log.h>
+
+#include "ModelChecker.hpp"
+#include "mc_protocol.h"
+#include "mc_server.h"
+#include "mc_private.h"
+#include "mc_ignore.h"
+#include "mcer_ignore.h"
+
+extern "C" {
+
+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.
+ */
+ int res = MC_protocol_hello(socket);
+ if (res != 0)
+ throw std::system_error(res, std::system_category());
+
+ // 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());
+ process->cache_flags = (mc_process_cache_flags_t) 0;
+}
+
+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());
+}
+
+bool 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 = MC_receive_message(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:
+ {
+ 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:
+ {
+ s_mc_ignore_memory_message_t message;
+ if (size != sizeof(message))
+ xbt_die("Broken messsage");
+ memcpy(&message, buffer, sizeof(message));
+ MC_heap_region_ignore_remove(message.addr, message.size);
+ break;
+ }
+
+ case MC_MESSAGE_IGNORE_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:
+ {
+ 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;
+ }
+
+ case MC_MESSAGE_WAITING:
+ return false;
+
+ case MC_MESSAGE_ASSERTION_FAILED:
+ MC_report_assertion_error();
+ xbt_abort();
+ break;
+
+ default:
+ xbt_die("Unexpected message from model-checked application");
+
+ }
+ return true;
+ }
+ 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 true;
+ }
+ if (signalfd_pollfd->revents & POLLERR) {
+ throw_socket_error(signalfd_pollfd->fd);
+ }
+ if (signalfd_pollfd->revents & POLLHUP)
+ xbt_die("Signalfd hang up?");
+ }
+
+ return true;
+}
+
+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");
+ 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;
+ }
+}
+
+void MC_server_wait_client(mc_process_t process)
+{
+ mc_server->resume(process);
+ while (mc_model_checker->process().running) {
+ if (!mc_server->handle_events())
+ return;
+ }
+}
+
+void MC_server_simcall_handle(mc_process_t process, unsigned long pid, int value)
+{
+ s_mc_simcall_handle_message m;
+ memset(&m, 0, sizeof(m));
+ m.type = MC_MESSAGE_SIMCALL_HANDLE;
+ m.pid = pid;
+ m.value = value;
+ MC_protocol_send(mc_model_checker->process().socket, &m, sizeof(m));
+ process->cache_flags = (mc_process_cache_flags_t) 0;
+ while (mc_model_checker->process().running) {
+ if (!mc_server->handle_events())
+ return;
+ }
+}
+
+void MC_server_loop(mc_server_t server)
+{
+ server->loop();
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_SERVER_H
+#define MC_SERVER_H
+
+#include <poll.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <sys/signalfd.h>
+#include <sys/types.h>
+
+#include <xbt/misc.h>
+
+#include "mc_process.h"
+
+SG_BEGIN_DECL()
+
+#define MC_SERVER_ERROR 127
+
+typedef struct s_mc_server s_mc_server_t, *mc_server_t;
+
+extern mc_server_t mc_server;
+
+XBT_INTERNAL void MC_server_wait_client(mc_process_t process);
+XBT_INTERNAL void MC_server_simcall_handle(mc_process_t process, unsigned long pid, int value);
+
+XBT_INTERNAL void MC_server_loop(mc_server_t 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();
+ bool handle_events();
+protected:
+ void handle_signals();
+ void handle_waitpid();
+ void on_signal(const struct signalfd_siginfo* info);
+};
+
+#endif
+
+#endif
+++ /dev/null
-/* Copyright (c) 2007-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 <stddef.h>
-#include <set>
-
-typedef std::set<const void*>* mc_address_set_t;
-
-extern "C" {
-
-mc_address_set_t mc_address_set_new();
-void mc_address_set_free(mc_address_set_t* p);
-void mc_address_add(mc_address_set_t p, const void* value);
-bool mc_address_test(mc_address_set_t p, const void* value);
-
-mc_address_set_t mc_address_set_new() {
- return new std::set<const void*>();
-}
-
-void mc_address_set_free(mc_address_set_t* p) {
- delete *p;
- *p = NULL;
-}
-
-void mc_address_add(mc_address_set_t p, const void* value) {
- p->insert(value);
-}
-
-bool mc_address_test(mc_address_set_t p, const void* value) {
- return p->find(value) != p->end();
-}
-
-};
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <assert.h>
+
+#include <xbt/log.h>
+
+#include "simix/smx_private.h"
+
+#include "mc_smx.h"
+#include "ModelChecker.hpp"
+
+extern "C" {
+
+static
+void MC_smx_process_info_clear(mc_smx_process_info_t p)
+{
+ p->hostname = NULL;
+ free(p->name);
+ p->name = NULL;
+}
+
+xbt_dynar_t MC_smx_process_info_list_new(void)
+{
+ return xbt_dynar_new(
+ sizeof(s_mc_smx_process_info_t),
+ ( void_f_pvoid_t) &MC_smx_process_info_clear);
+}
+
+static inline
+bool is_in_dynar(smx_process_t p, xbt_dynar_t dynar)
+{
+ return (uintptr_t) p >= (uintptr_t) dynar->data
+ && (uintptr_t) p < ((uintptr_t) dynar->data + dynar->used * dynar->elmsize);
+}
+
+static inline
+mc_smx_process_info_t MC_smx_process_get_info(smx_process_t p)
+{
+ assert(is_in_dynar(p, mc_model_checker->process().smx_process_infos)
+ || is_in_dynar(p, mc_model_checker->process().smx_old_process_infos));
+ mc_smx_process_info_t process_info =
+ (mc_smx_process_info_t)
+ ((char*) p - offsetof(s_mc_smx_process_info_t, copy));
+ return process_info;
+}
+
+/** Load the remote swag of processes into a dynar
+ *
+ * @param process MCed process
+ * @param target Local dynar (to be filled with copies of `s_smx_process_t`)
+ * @param remote_swag Address of the process SWAG in the remote list
+ */
+static void MC_process_refresh_simix_process_list(
+ mc_process_t process,
+ xbt_dynar_t target, xbt_swag_t remote_swag)
+{
+ // swag = REMOTE(*simix_global->process_list)
+ s_xbt_swag_t swag;
+ MC_process_read(process, MC_PROCESS_NO_FLAG, &swag, remote_swag, sizeof(swag),
+ MC_PROCESS_INDEX_ANY);
+
+ smx_process_t p;
+ xbt_dynar_reset(target);
+
+ // Load each element of the dynar from the MCed process:
+ int i = 0;
+ for (p = (smx_process_t) swag.head; p; ++i) {
+
+ s_mc_smx_process_info_t info;
+ info.address = p;
+ info.name = NULL;
+ info.hostname = NULL;
+ MC_process_read(process, MC_PROCESS_NO_FLAG,
+ &info.copy, p, sizeof(info.copy), MC_PROCESS_INDEX_ANY);
+ xbt_dynar_push(target, &info);
+
+ // Lookup next process address:
+ p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
+ }
+ assert(i == swag.count);
+}
+
+void MC_process_smx_refresh(mc_process_t process)
+{
+ xbt_assert(mc_mode == MC_MODE_SERVER);
+ xbt_assert(!MC_process_is_self(process));
+ if (process->cache_flags & MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES)
+ return;
+
+ // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
+
+ // simix_global_p = REMOTE(simix_global);
+ smx_global_t simix_global_p;
+ MC_process_read_variable(process, "simix_global", &simix_global_p, sizeof(simix_global_p));
+
+ // simix_global = REMOTE(*simix_global)
+ s_smx_global_t simix_global;
+ MC_process_read(process, MC_PROCESS_NO_FLAG, &simix_global, simix_global_p, sizeof(simix_global),
+ MC_PROCESS_INDEX_ANY);
+
+ MC_process_refresh_simix_process_list(
+ process, process->smx_process_infos, simix_global.process_list);
+ MC_process_refresh_simix_process_list(
+ process, process->smx_old_process_infos, simix_global.process_to_destroy);
+
+ process->cache_flags |= MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES;
+}
+
+/** Get the issuer of a simcall (`req->issuer`)
+ *
+ * In split-process mode, it does the black magic necessary to get an address
+ * of a (shallow) copy of the data structure the issuer SIMIX process in the local
+ * address space.
+ *
+ * @param process the MCed process
+ * @param req the simcall (copied in the local process)
+ */
+smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
+{
+ if (mc_mode == MC_MODE_CLIENT)
+ return req->issuer;
+
+ MC_process_smx_refresh(&mc_model_checker->process());
+
+ // This is the address of the smx_process in the MCed process:
+ void* address = req->issuer;
+
+ unsigned i;
+ mc_smx_process_info_t p;
+
+ // Lookup by address:
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, i, p)
+ if (p->address == address)
+ return &p->copy;
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, i, p)
+ if (p->address == address)
+ return &p->copy;
+
+ xbt_die("Issuer not found");
+}
+
+smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
+{
+ if (!process_remote_address)
+ return NULL;
+ if (mc_mode == MC_MODE_CLIENT)
+ return process_remote_address;
+
+ mc_smx_process_info_t process_info = MC_smx_resolve_process_info(process_remote_address);
+ if (process_info)
+ return &process_info->copy;
+ else
+ return NULL;
+}
+
+mc_smx_process_info_t MC_smx_resolve_process_info(smx_process_t process_remote_address)
+{
+ if (mc_mode == MC_MODE_CLIENT)
+ xbt_die("No process_info for local process is not enabled.");
+
+ unsigned index;
+ mc_smx_process_info_t process_info;
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, index, process_info)
+ if (process_info->address == process_remote_address)
+ return process_info;
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, index, process_info)
+ if (process_info->address == process_remote_address)
+ return process_info;
+ xbt_die("Process info not found");
+}
+
+const char* MC_smx_process_get_host_name(smx_process_t p)
+{
+ if (mc_mode == MC_MODE_CLIENT)
+ return SIMIX_host_get_name(p->smx_host);
+
+ mc_process_t process = &mc_model_checker->process();
+
+ // Currently, smx_host_t = xbt_dictelm_t.
+ // TODO, add an static_assert on this if switching to C++
+ // The host name is host->key and the host->key_len==strlen(host->key).
+ s_xbt_dictelm_t host_copy;
+ mc_smx_process_info_t info = MC_smx_process_get_info(p);
+ if (!info->hostname) {
+
+ // Read the hostname from the MCed process:
+ MC_process_read_simple(process, &host_copy, p->smx_host, sizeof(host_copy));
+ int len = host_copy.key_len + 1;
+ char hostname[len];
+ MC_process_read_simple(process, hostname, host_copy.key, len);
+ info->hostname = mc_model_checker->get_host_name(hostname);
+ }
+ return info->hostname;
+}
+
+const char* MC_smx_process_get_name(smx_process_t p)
+{
+ mc_process_t process = &mc_model_checker->process();
+ if (mc_mode == MC_MODE_CLIENT)
+ return p->name;
+ if (!p->name)
+ return NULL;
+
+ mc_smx_process_info_t info = MC_smx_process_get_info(p);
+ if (!info->name) {
+ info->name = MC_process_read_string(process, p->name);
+ }
+ return info->name;
+}
+
+int MC_smpi_process_count(void)
+{
+ if (mc_mode == MC_MODE_CLIENT)
+ return smpi_process_count();
+ else {
+ int res;
+ MC_process_read_variable(&mc_model_checker->process(), "process_count",
+ &res, sizeof(res));
+ return res;
+ }
+}
+
+unsigned long MC_smx_get_maxpid(void)
+{
+ unsigned long maxpid;
+ MC_process_read_variable(&mc_model_checker->process(), "simix_process_maxpid",
+ &maxpid, sizeof(maxpid));
+ return maxpid;
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_SMX_H
+#define MC_SMX_H
+
+#include <stddef.h>
+
+#include <xbt/log.h>
+#include <simgrid/simix.h>
+
+#include "smpi/private.h"
+
+#include "mc_process.h"
+#include "mc_protocol.h"
+
+/** @file
+ * @brief (Cross-process, MCer/MCed) Access to SMX structures
+ *
+ * We copy some C data structure from the MCed process in the MCer process.
+ * This is implemented by:
+ *
+ * - `model_checker->process.smx_process_infos`
+ * (copy of `simix_global->process_list`);
+ *
+ * - `model_checker->process.smx_old_process_infos`
+ * (copy of `simix_global->process_to_destroy`);
+ *
+ * - `model_checker->hostnames`.
+ *
+ * The process lists are currently refreshed each time MCed code is executed.
+ * We don't try to give a persistent MCer address for a given MCed process.
+ * For this reason, a MCer mc_process_t is currently not reusable after
+ * MCed code.
+ */
+
+SG_BEGIN_DECL()
+
+struct s_mc_smx_process_info {
+ /** MCed address of the process */
+ void* address;
+ /** (Flat) Copy of the process data structure */
+ struct s_smx_process copy;
+ /** Hostname (owned by `mc_modelchecker->hostnames`) */
+ const char* hostname;
+ char* name;
+};
+
+XBT_INTERNAL xbt_dynar_t MC_smx_process_info_list_new(void);
+
+XBT_INTERNAL void MC_process_smx_refresh(mc_process_t process);
+
+/** Get the issuer of a simcall (`req->issuer`)
+ *
+ * In split-process mode, it does the black magic necessary to get an address
+ * of a (shallow) copy of the data structure the issuer SIMIX process in the local
+ * address space.
+ *
+ * @param process the MCed process
+ * @param req the simcall (copied in the local process)
+ */
+XBT_INTERNAL smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req);
+
+XBT_INTERNAL const char* MC_smx_process_get_name(smx_process_t p);
+XBT_INTERNAL const char* MC_smx_process_get_host_name(smx_process_t p);
+
+#define MC_EACH_SIMIX_PROCESS(process, code) \
+ if (mc_mode == MC_MODE_CLIENT) { \
+ xbt_swag_foreach(process, simix_global->process_list) { \
+ code; \
+ } \
+ } else { \
+ MC_process_smx_refresh(&mc_model_checker->process()); \
+ unsigned int _smx_process_index; \
+ mc_smx_process_info_t _smx_process_info; \
+ xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, _smx_process_index, _smx_process_info) { \
+ smx_process_t process = &_smx_process_info->copy; \
+ code; \
+ } \
+ }
+
+/** Execute a given simcall */
+XBT_INTERNAL void MC_simcall_handle(smx_simcall_t req, int value);
+
+XBT_INTERNAL int MC_smpi_process_count(void);
+
+
+/* ***** Resolve (local/MCer structure from remote/MCed addresses) ***** */
+
+/** Get a local copy of the process from the process remote address */
+XBT_INTERNAL smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address);
+
+/** Get the process info structure from the process remote address */
+XBT_INTERNAL mc_smx_process_info_t MC_smx_resolve_process_info(smx_process_t process_remote_address);
+
+XBT_INTERNAL unsigned long MC_smx_get_maxpid(void);
+
+SG_END_DECL()
+
+#endif
#include "mc_snapshot.h"
#include "mc_private.h"
#include "mc_mmu.h"
-#include "mc_page_store.h"
+#include "PageStore.hpp"
+
+extern "C" {
/** @brief Find the snapshoted region from a pointer
*
* @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) {
+ 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;
- if (process_index < 0) {
-
- 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 >= (int) region->privatized.regions_count) {
xbt_die("Invalid process index");
}
-
- mc_mem_region_t region = snapshot->privatization_regions[process_index];
- if( mc_region_contain(region, addr) ) {
- return region;
- }
-
- }
- }
+ mc_mem_region_t priv_region = region->privatized.regions[process_index];
+ xbt_assert(mc_region_contain(priv_region, addr));
+ return priv_region;
+#else
+ xbt_die("Privatized region in a non SMPI build (this should not happen)");
#endif
-
- for (size_t i = 0; i != NB_REGIONS; ++i) {
- mc_mem_region_t region = snapshot->regions[i];
- if ( region && mc_region_contain(region, addr) ) {
- return region;
}
+
+ return region;
}
return NULL;
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer of original location)
*/
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
// Last byte of the memory area:
void* end = (char*) addr + size - 1;
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer or original location)
*/
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size)
+const void* MC_snapshot_read(
+ mc_snapshot_t snapshot, adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index)
{
- if (snapshot) {
- mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
- return mc_snapshot_read_region(addr, region, target, size);
- } else {
- return addr;
- }
+ mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
+ if (region)
+ return MC_region_read(region, target, addr, size);
+ else
+ return MC_process_read(snapshot->process, flags, target, addr, size, process_index);
}
/** Compare memory between snapshots (with known regions)
* @param snapshot2 Region of the address in the second snapshot
* @return same as memcmp
* */
-int mc_snapshot_region_memcmp(
- void* addr1, mc_mem_region_t region1,
- void* addr2, mc_mem_region_t region2,
+int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2,
size_t size)
{
// Using alloca() for large allocations may trigger stack overflow:
// use malloc if the buffer is too big.
bool stack_alloc = size < 64;
- void* buffer1a = (region1==NULL || region1->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
- void* buffer2a = (region2==NULL || region2->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
- void* buffer1 = mc_snapshot_read_region(addr1, region1, buffer1a, size);
- void* buffer2 = mc_snapshot_read_region(addr2, region2, buffer2a, size);
+ const bool region1_need_buffer = region1==NULL || region1->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+ const bool region2_need_buffer = region2==NULL || region2->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+ void* buffer1a = region1_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+ void* buffer2a = region2_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+ const void* buffer1 = MC_region_read(region1, buffer1a, addr1, size);
+ const void* buffer2 = MC_region_read(region2, buffer2a, addr2, size);
int res;
if (buffer1 == buffer2) {
res = 0;
* @param snapshot2 Second snapshot
* @return same as memcmp
* */
-int mc_snapshot_memcmp(
- void* addr1, mc_snapshot_t snapshot1,
- void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
+int MC_snapshot_memcmp(
+ const void* addr1, mc_snapshot_t snapshot1,
+ const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
{
mc_mem_region_t region1 = mc_get_snapshot_region(addr1, snapshot1, process_index);
mc_mem_region_t region2 = mc_get_snapshot_region(addr2, snapshot2, process_index);
- return mc_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
+ return MC_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
}
#ifdef SIMGRID_TEST
#include "mc/mc_snapshot.h"
#include "mc/mc_mmu.h"
+extern "C" {
+
XBT_TEST_SUITE("mc_snapshot", "Snapshots");
static inline void init_memory(void* mem, size_t size)
{
char* dest = (char*) mem;
- for (int i=0; i!=size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
dest[i] = rand() & 255;
}
}
static void test_snapshot(bool sparse_checkpoint);
-XBT_TEST_UNIT("page_snapshots", test_per_snpashots, "Test per-page snapshots")
-{
- test_snapshot(1);
-}
-
-
XBT_TEST_UNIT("flat_snapshot", test_flat_snapshots, "Test flat snapshots")
{
test_snapshot(0);
}
+XBT_TEST_UNIT("page_snapshots", test_per_snpashots, "Test per-page snapshots")
+{
+ test_snapshot(1);
+}
static void test_snapshot(bool sparse_checkpoint) {
xbt_test_add("Initialisation");
- _sg_mc_soft_dirty = 0;
_sg_mc_sparse_checkpoint = sparse_checkpoint;
xbt_assert(xbt_pagesize == getpagesize());
xbt_assert(1 << xbt_pagebits == xbt_pagesize);
- mc_model_checker = xbt_new0(s_mc_model_checker_t, 1);
- mc_model_checker->pages = mc_pages_store_new();
+ mc_model_checker = new ::simgrid::mc::ModelChecker(getpid(), -1);
for(int n=1; n!=256; ++n) {
// 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);
for(int i=0; i<n; i+=2) {
init_memory((char*) source + i*xbt_pagesize, xbt_pagesize);
}
- mc_mem_region_t region = mc_region_new_sparse(0, source, source, byte_size, NULL);
+ mc_mem_region_t region = mc_region_new_sparse(
+ MC_REGION_TYPE_UNKNOWN, source, source, byte_size);
void* destination = mmap(NULL, byte_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
xbt_assert(source!=MAP_FAILED, "Could not allocate destination memory");
xbt_test_add("Reading whole region data for %i page(s)", n);
- void* read = mc_snapshot_read_region(source, region, destination, byte_size);
- xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in mc_snapshot_read_region()");
+ const void* read = MC_region_read(region, destination, source, byte_size);
+ xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in MC_region_read()");
xbt_test_add("Reading parts of region data for %i page(s)", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- void* read = mc_snapshot_read_region((char*) source+offset, region, destination, size);
+ const void* read = MC_region_read(region, destination, (const char*) source+offset, size);
xbt_test_assert(!memcmp((char*) source+offset, read, size),
- "Mismatch in mc_snapshot_read_region()");
+ "Mismatch in MC_region_read()");
}
xbt_test_add("Compare whole region data for %i page(s)", n);
- xbt_test_assert(!mc_snapshot_region_memcmp(source, NULL, source, region, byte_size),
- "Mismatch in mc_snapshot_region_memcmp() for the whole region");
- xbt_test_assert(mc_snapshot_region_memcmp(source, region0, source, region, byte_size),
- "Unexpected match in mc_snapshot_region_memcmp() with previous snapshot");
+ xbt_test_assert(!MC_snapshot_region_memcmp(source, NULL, source, region, byte_size),
+ "Mismatch in MC_snapshot_region_memcmp() for the whole region");
+ xbt_test_assert(MC_snapshot_region_memcmp(source, region0, source, region, byte_size),
+ "Unexpected match in MC_snapshot_region_memcmp() with previous snapshot");
xbt_test_add("Compare parts of region data for %i page(s) with current value", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
xbt_test_add("Compare parts of region data for %i page(s) with itself", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
if (n==1) {
xbt_test_add("Read pointer for %i page(s)", n);
memcpy(source, &mc_model_checker, sizeof(void*));
- mc_mem_region_t region2 = mc_region_new_sparse(0, source, source, byte_size, NULL);
- xbt_test_assert(mc_snapshot_read_pointer_region(source, region2) == mc_model_checker,
- "Mismtach in mc_snapshot_read_pointer_region()");
+ mc_mem_region_t region2 = mc_region_new_sparse(
+ MC_REGION_TYPE_UNKNOWN, source, source, byte_size);
+ xbt_test_assert(MC_region_read_pointer(region2, source) == mc_model_checker,
+ "Mismtach in MC_region_read_pointer()");
MC_region_destroy(region2);
}
munmap(source, byte_size);
}
- mc_pages_store_delete(mc_model_checker->pages);
- xbt_free(mc_model_checker);
+ delete mc_model_checker;
mc_model_checker = NULL;
}
+}
+
#endif /* SIMGRID_TEST */
+
+}
#include <xbt/dynar.h>
#include "mc_forward.h"
-#include "mc_model_checker.h"
-#include "mc_page_store.h"
+#include "ModelChecker.hpp"
+#include "PageStore.hpp"
#include "mc_mmalloc.h"
+#include "mc_address_space.h"
+#include "mc_unw.h"
SG_BEGIN_DECL()
-void mc_softdirty_reset(void);
-
// ***** Snapshot region
-#define NB_REGIONS 3 /* binary data (data + BSS) (type = 2), libsimgrid data (data + BSS) (type = 1), std_heap (type = 0)*/
+typedef enum e_mc_region_type_t {
+ MC_REGION_TYPE_UNKNOWN = 0,
+ MC_REGION_TYPE_HEAP = 1,
+ MC_REGION_TYPE_DATA = 2
+} mc_region_type_t;
+
+// TODO, use OO instead of this
+typedef enum e_mc_region_storeage_type_t {
+ MC_REGION_STORAGE_TYPE_NONE = 0,
+ MC_REGION_STORAGE_TYPE_FLAT = 1,
+ MC_REGION_STORAGE_TYPE_CHUNKED = 2,
+ MC_REGION_STORAGE_TYPE_PRIVATIZED = 3
+} mc_region_storage_type_t;
/** @brief Copy/snapshot of a given memory region
*
- * Two types of region snapshots exist:
+ * Different types of region snapshot storage types exist:
* <ul>
* <li>flat/dense snapshots are a simple copy of the region;</li>
* <li>sparse/per-page snapshots are snaapshots which shared
* identical pages.</li>
+ * <li>privatized (SMPI global variable privatisation).
* </ul>
+ *
+ * This is handled with a variant based approch:
+ *
+ * * `storage_type` identified the type of storage;
+ * * an anonymous enum is used to distinguish the relevant types for
+ * each type.
*/
-typedef struct s_mc_mem_region{
+typedef struct s_mc_mem_region s_mc_mem_region_t, *mc_mem_region_t;
+
+struct s_mc_mem_region {
+ mc_region_type_t region_type;
+ mc_region_storage_type_t storage_type;
+ mc_object_info_t object_info;
+
/** @brief Virtual address of the region in the simulated process */
void *start_addr;
+ /** @brief Size of the data region in bytes */
+ size_t size;
+
/** @brief Permanent virtual address of the region
*
* This is usually the same address as the simuilated process address.
* */
void *permanent_addr;
- /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
- void *data;
+ union {
+ struct {
+ /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
+ void *data;
+ } flat;
+ struct {
+ /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
+ size_t* page_numbers;
+ } chunked;
+ struct {
+ size_t regions_count;
+ mc_mem_region_t* regions;
+ } privatized;
+ };
- /** @brief Size of the data region in bytes */
- size_t size;
-
- /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
- size_t* page_numbers;
-
-} s_mc_mem_region_t, *mc_mem_region_t;
+};
-mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* data_addr, size_t size, mc_mem_region_t ref_reg);
-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);
+MC_SHOULD_BE_INTERNAL mc_mem_region_t mc_region_new_sparse(
+ mc_region_type_t type, void *start_addr, void* data_addr, size_t size);
+MC_SHOULD_BE_INTERNAL void MC_region_destroy(mc_mem_region_t reg);
+XBT_INTERNAL void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t 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);
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];
- const void* snapshot_page = mc_page_store_get_page(mc_model_checker->pages, snapshot_pageno);
- return (char*) snapshot_page + mc_page_offset((void*) addr);
+ size_t pageno = mc_page_number(region->start_addr, (void*) addr);
+ size_t snapshot_pageno = region->chunked.page_numbers[pageno];
+ const void* snapshot_page =
+ mc_model_checker->page_store().get_page(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);
+XBT_INTERNAL mc_mem_region_t mc_get_snapshot_region(
+ const void* addr, mc_snapshot_t snapshot, int process_index);
/** \brief Translate a pointer from process address space to snapshot address space
*
return (void *) addr;
}
- // Flat snapshot:
- else if (region->data) {
- uintptr_t offset = addr - (uintptr_t) region->start_addr;
- return (void *) ((uintptr_t) region->data + offset);
- }
+ switch (region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ default:
+ xbt_die("Storage type not supported");
+
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ {
+ uintptr_t offset = addr - (uintptr_t) region->start_addr;
+ return (void *) ((uintptr_t) region->flat.data + offset);
+ }
- // Per-page snapshot:
- else if (region->page_numbers) {
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
return mc_translate_address_region(addr, region);
- }
- else {
- xbt_die("No data for this memory region");
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ {
+ xbt_assert(process_index >=0,
+ "Missing process index for privatized region");
+ xbt_assert((size_t) process_index < region->privatized.regions_count,
+ "Out of range process index");
+ mc_mem_region_t subregion = region->privatized.regions[process_index];
+ xbt_assert(subregion, "Missing memory region for process %i", process_index);
+ return mc_translate_address(addr, snapshot, process_index);
+ }
}
}
int flags;
}s_fd_infos_t, *fd_infos_t;
-struct s_mc_snapshot{
+struct s_mc_snapshot {
+ mc_process_t process;
+ int num_state;
+ s_mc_address_space_t address_space;
size_t heap_bytes_used;
- mc_mem_region_t regions[NB_REGIONS];
+ mc_mem_region_t* snapshot_regions;
+ size_t snapshot_regions_count;
xbt_dynar_t enabled_processes;
- mc_mem_region_t* privatization_regions;
int privatization_index;
size_t *stack_sizes;
xbt_dynar_t stacks;
fd_infos_t *current_fd;
};
-/** @brief Process index used when no process is available
- *
- * The expected behaviour is that if a process index is needed it will fail.
- * */
-#define MC_NO_PROCESS_INDEX -1
-
-/** @brief Process index when any process is suitable
- *
- * We could use a special negative value in the future.
- */
-#define MC_ANY_PROCESS_INDEX 0
-
static inline __attribute__ ((always_inline))
mc_mem_region_t mc_get_region_hinted(void* addr, mc_snapshot_t snapshot, int process_index, mc_mem_region_t region)
{
typedef struct s_mc_snapshot_stack{
xbt_dynar_t local_variables;
+ mc_unw_context_t context;
xbt_dynar_t stack_frames; // mc_stack_frame_t
int process_index;
}s_mc_snapshot_stack_t, *mc_snapshot_stack_t;
-typedef struct s_mc_global_t{
+typedef struct s_mc_global_t {
mc_snapshot_t snapshot;
- int raw_mem_set;
int prev_pair;
char *prev_req;
int initial_communications_pattern_done;
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);
-void MC_free_snapshot(mc_snapshot_t);
+XBT_INTERNAL mc_snapshot_t MC_take_snapshot(int num_state);
+XBT_INTERNAL void MC_restore_snapshot(mc_snapshot_t);
+XBT_INTERNAL void MC_free_snapshot(mc_snapshot_t);
-int mc_important_snapshot(mc_snapshot_t snapshot);
+XBT_INTERNAL size_t* mc_take_page_snapshot_region(mc_process_t process,
+ void* data, size_t page_count);
+XBT_INTERNAL void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count);
+XBT_INTERNAL void mc_restore_page_snapshot_region(
+ mc_process_t process,
+ void* start_addr, size_t page_count, size_t* pagenos);
-size_t* mc_take_page_snapshot_region(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);
+MC_SHOULD_BE_INTERNAL const void* MC_region_read_fragmented(
+ mc_mem_region_t region, void* target, const void* addr, size_t size);
-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);
+XBT_INTERNAL const void* MC_snapshot_read(mc_snapshot_t snapshot,
+ adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index);
+MC_SHOULD_BE_INTERNAL int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2, size_t size);
+XBT_INTERNAL 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);
+ return MC_process_get_heap(&mc_model_checker->process())->breakval;
}
/** @brief Read memory from a snapshot region
* @return Pointer where the data is located (target buffer of original location)
*/
static inline __attribute__((always_inline))
-void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
if (region==NULL)
+ // Should be deprecated:
return addr;
uintptr_t offset = (char*) addr - (char*) region->start_addr;
xbt_assert(mc_region_contain(region, addr),
"Trying to read out of the region boundary.");
- // Linear memory region:
- if (region->data) {
- return (char*) region->data + offset;
- }
-
- // Fragmented memory region:
- else if (region->page_numbers) {
- // Last byte of the region:
- void* end = (char*) addr + size - 1;
- if( mc_same_page(addr, end) ) {
- // The memory is contained in a single page:
- return mc_translate_address_region((uintptr_t) addr, region);
- } else {
- // The memory spans several pages:
- return mc_snapshot_read_fragmented(addr, region, target, size);
+ switch (region->storage_type) {
+ case MC_REGION_STORAGE_TYPE_NONE:
+ default:
+ xbt_die("Storage type not supported");
+
+ case MC_REGION_STORAGE_TYPE_FLAT:
+ return (char*) region->flat.data + offset;
+
+ case MC_REGION_STORAGE_TYPE_CHUNKED:
+ {
+ // Last byte of the region:
+ void* end = (char*) addr + size - 1;
+ if (mc_same_page(addr, end) ) {
+ // The memory is contained in a single page:
+ return mc_translate_address_region((uintptr_t) addr, region);
+ } else {
+ // The memory spans several pages:
+ return MC_region_read_fragmented(region, target, addr, size);
+ }
}
- }
- else {
- xbt_die("No data available for this region");
+ // We currently do not pass the process_index to this function so we assume
+ // that the privatized region has been resolved in the callers:
+ case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+ xbt_die("Storage type not supported");
}
}
static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer_region(void* addr, mc_mem_region_t region)
+void* MC_region_read_pointer(mc_mem_region_t region, const void* addr)
{
void* res;
- return *(void**) mc_snapshot_read_region(addr, region, &res, sizeof(void*));
+ return *(void**) MC_region_read(region, &res, addr, sizeof(void*));
}
SG_END_DECL()
+++ /dev/null
-/* Copyright (c) 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 "../simix/smx_private.h"
-#include "xbt/fifo.h"
-#include "mc_state.h"
-#include "mc_request.h"
-#include "mc_private.h"
-#include "mc_comm_pattern.h"
-
-static void copy_incomplete_communications_pattern(mc_state_t state) {
- int i;
- xbt_dynar_t incomplete_process_comms;
- mc_comm_pattern_t comm;
- unsigned int cursor;
- state->incomplete_comm_pattern = xbt_dynar_new(sizeof(xbt_dynar_t), xbt_dynar_free_voidp);
- for (i=0; i<simix_process_maxpid; i++) {
- incomplete_process_comms = xbt_dynar_get_as(incomplete_communications_pattern, i, xbt_dynar_t);
- xbt_dynar_t incomplete_process_comms_copy = xbt_dynar_new(sizeof(mc_comm_pattern_t), comm_pattern_free_voidp);
- xbt_dynar_foreach(incomplete_process_comms, cursor, comm) {
- mc_comm_pattern_t copy_comm = xbt_new0(s_mc_comm_pattern_t, 1);
- copy_comm->index = comm->index;
- copy_comm->type = comm->type;
- copy_comm->comm = comm->comm;
- copy_comm->rdv = strdup(comm->rdv);
- copy_comm->data_size = -1;
- copy_comm->data = NULL;
- if(comm->type == SIMIX_COMM_SEND){
- copy_comm->src_proc = comm->src_proc;
- copy_comm->src_host = comm->src_host;
- if (comm->data != NULL) {
- copy_comm->data_size = comm->data_size;
- copy_comm->data = xbt_malloc0(comm->data_size);
- memcpy(copy_comm->data, comm->data, comm->data_size);
- }
- }else{
- copy_comm->dst_proc = comm->dst_proc;
- copy_comm->dst_host = comm->dst_host;
- }
- xbt_dynar_push(incomplete_process_comms_copy, ©_comm);
- }
- xbt_dynar_insert_at(state->incomplete_comm_pattern, i, &incomplete_process_comms_copy);
- }
-}
-
-static void copy_index_communications_pattern(mc_state_t state) {
-
- state->index_comm = xbt_dynar_new(sizeof(unsigned int), NULL);
- mc_list_comm_pattern_t list_process_comm;
- unsigned int cursor;
- xbt_dynar_foreach(initial_communications_pattern, cursor, list_process_comm){
- xbt_dynar_push_as(state->index_comm, unsigned int, list_process_comm->index_comm);
- }
-}
-
-/**
- * \brief Creates a state data structure used by the exploration algorithm
- */
-mc_state_t MC_state_new()
-{
- mc_state_t state = NULL;
-
- state = xbt_new0(s_mc_state_t, 1);
- state->max_pid = simix_process_maxpid;
- state->proc_status = xbt_new0(s_mc_procstate_t, state->max_pid);
- state->system_state = NULL;
- state->num = ++mc_stats->expanded_states;
- state->in_visited_states = 0;
- state->incomplete_comm_pattern = NULL;
- /* Stateful model checking */
- if((_sg_mc_checkpoint > 0 && (mc_stats->expanded_states % _sg_mc_checkpoint == 0)) || _sg_mc_termination){
- state->system_state = MC_take_snapshot(state->num);
- if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
- copy_incomplete_communications_pattern(state);
- copy_index_communications_pattern(state);
- }
- }
- return state;
-}
-
-/**
- * \brief Deletes a state data structure
- * \param trans The state to be deleted
- */
-void MC_state_delete(mc_state_t state, int free_snapshot){
- if (state->system_state && free_snapshot){
- MC_free_snapshot(state->system_state);
- }
- if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
- xbt_free(state->index_comm);
- xbt_free(state->incomplete_comm_pattern);
- }
- xbt_free(state->proc_status);
- xbt_free(state);
-}
-
-void MC_state_interleave_process(mc_state_t state, smx_process_t process)
-{
- state->proc_status[process->pid].state = MC_INTERLEAVE;
- state->proc_status[process->pid].interleave_count = 0;
-}
-
-void MC_state_remove_interleave_process(mc_state_t state, smx_process_t process)
-{
- if (state->proc_status[process->pid].state == MC_INTERLEAVE)
- state->proc_status[process->pid].state = MC_DONE;
-}
-
-unsigned int MC_state_interleave_size(mc_state_t state)
-{
- unsigned int i, size = 0;
-
- for (i = 0; i < state->max_pid; i++) {
- if ((state->proc_status[i].state == MC_INTERLEAVE)
- || (state->proc_status[i].state == MC_MORE_INTERLEAVE))
- size++;
- }
-
- return size;
-}
-
-int MC_state_process_is_done(mc_state_t state, smx_process_t process)
-{
- return state->proc_status[process->pid].state == MC_DONE ? TRUE : FALSE;
-}
-
-void MC_state_set_executed_request(mc_state_t state, smx_simcall_t req,
- int value)
-{
- state->executed_req = *req;
- state->req_num = value;
- smx_process_t process = NULL;
- mc_procstate_t procstate = NULL;
-
- /* The waitany and testany request are transformed into a wait or test request over the
- * corresponding communication action so it can be treated later by the dependence
- * function. */
- switch (req->call) {
- case SIMCALL_COMM_WAITANY:
- state->internal_req.call = SIMCALL_COMM_WAIT;
- state->internal_req.issuer = req->issuer;
- state->internal_comm =
- *xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value,
- smx_synchro_t);
- simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
- simcall_comm_wait__set__timeout(&state->internal_req, 0);
- break;
-
- case SIMCALL_COMM_TESTANY:
- state->internal_req.call = SIMCALL_COMM_TEST;
- state->internal_req.issuer = req->issuer;
-
- if (value > 0)
- state->internal_comm =
- *xbt_dynar_get_as(simcall_comm_testany__get__comms(req), value,
- smx_synchro_t);
-
- simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
- simcall_comm_test__set__result(&state->internal_req, value);
- break;
-
- case SIMCALL_COMM_WAIT:
- state->internal_req = *req;
- state->internal_comm = *(simcall_comm_wait__get__comm(req));
- simcall_comm_wait__set__comm(&state->executed_req, &state->internal_comm);
- simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
- break;
-
- case SIMCALL_COMM_TEST:
- state->internal_req = *req;
- state->internal_comm = *simcall_comm_test__get__comm(req);
- simcall_comm_test__set__comm(&state->executed_req, &state->internal_comm);
- simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
- break;
-
- case SIMCALL_MC_RANDOM:
- state->internal_req = *req;
- if (value != simcall_mc_random__get__max(req)) {
- xbt_swag_foreach(process, simix_global->process_list) {
- procstate = &state->proc_status[process->pid];
- if (process->pid == req->issuer->pid) {
- procstate->state = MC_MORE_INTERLEAVE;
- break;
- }
- }
- }
- break;
-
- default:
- state->internal_req = *req;
- break;
- }
-}
-
-smx_simcall_t MC_state_get_executed_request(mc_state_t state, int *value)
-{
- *value = state->req_num;
- return &state->executed_req;
-}
-
-smx_simcall_t MC_state_get_internal_request(mc_state_t state)
-{
- return &state->internal_req;
-}
-
-smx_simcall_t MC_state_get_request(mc_state_t state, int *value)
-{
- smx_process_t process = NULL;
- mc_procstate_t procstate = NULL;
- unsigned int start_count;
- smx_synchro_t act = NULL;
-
- xbt_swag_foreach(process, simix_global->process_list) {
- procstate = &state->proc_status[process->pid];
-
- if (procstate->state == MC_INTERLEAVE
- || procstate->state == MC_MORE_INTERLEAVE) {
- if (MC_process_is_enabled(process)) {
- switch (process->simcall.call) {
- case SIMCALL_COMM_WAITANY:
- *value = -1;
- while (procstate->interleave_count <
- xbt_dynar_length(simcall_comm_waitany__get__comms
- (&process->simcall))) {
- if (MC_request_is_enabled_by_idx
- (&process->simcall, procstate->interleave_count++)) {
- *value = procstate->interleave_count - 1;
- break;
- }
- }
-
- if (procstate->interleave_count >=
- xbt_dynar_length(simcall_comm_waitany__get__comms
- (&process->simcall)))
- procstate->state = MC_DONE;
-
- if (*value != -1)
- return &process->simcall;
-
- break;
-
- case SIMCALL_COMM_TESTANY:
- start_count = procstate->interleave_count;
- *value = -1;
- while (procstate->interleave_count <
- xbt_dynar_length(simcall_comm_testany__get__comms
- (&process->simcall))) {
- if (MC_request_is_enabled_by_idx
- (&process->simcall, procstate->interleave_count++)) {
- *value = procstate->interleave_count - 1;
- break;
- }
- }
-
- if (procstate->interleave_count >=
- xbt_dynar_length(simcall_comm_testany__get__comms
- (&process->simcall)))
- procstate->state = MC_DONE;
-
- if (*value != -1 || start_count == 0)
- return &process->simcall;
-
- break;
-
- case SIMCALL_COMM_WAIT:
- act = simcall_comm_wait__get__comm(&process->simcall);
- if (act->comm.src_proc && act->comm.dst_proc) {
- *value = 0;
- } else {
- if (act->comm.src_proc == NULL && act->comm.type == SIMIX_COMM_READY
- && act->comm.detached == 1)
- *value = 0;
- else
- *value = -1;
- }
- procstate->state = MC_DONE;
- return &process->simcall;
-
- break;
-
- case SIMCALL_MC_RANDOM:
- if (procstate->state == MC_INTERLEAVE)
- *value = 0;
- else {
- if (state->req_num < simcall_mc_random__get__max(&process->simcall))
- *value = state->req_num + 1;
- }
- procstate->state = MC_DONE;
- return &process->simcall;
- break;
-
- default:
- procstate->state = MC_DONE;
- *value = 0;
- return &process->simcall;
- break;
- }
- }
- }
- }
-
- return NULL;
-}
--- /dev/null
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <assert.h>
+
+#include "../simix/smx_private.h"
+#include "xbt/fifo.h"
+#include "mc_state.h"
+#include "mc_request.h"
+#include "mc_private.h"
+#include "mc_comm_pattern.h"
+#include "mc_smx.h"
+
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_state, mc,
+ "Logging specific to MC (state)");
+
+/**
+ * \brief Creates a state data structure used by the exploration algorithm
+ */
+mc_state_t MC_state_new()
+{
+ mc_state_t state = xbt_new0(s_mc_state_t, 1);
+
+ state->max_pid = MC_smx_get_maxpid();
+ state->proc_status = xbt_new0(s_mc_procstate_t, state->max_pid);
+ state->system_state = NULL;
+ state->num = ++mc_stats->expanded_states;
+ state->in_visited_states = 0;
+ state->incomplete_comm_pattern = NULL;
+ /* Stateful model checking */
+ if((_sg_mc_checkpoint > 0 && (mc_stats->expanded_states % _sg_mc_checkpoint == 0)) || _sg_mc_termination){
+ state->system_state = MC_take_snapshot(state->num);
+ if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
+ MC_state_copy_incomplete_communications_pattern(state);
+ MC_state_copy_index_communications_pattern(state);
+ }
+ }
+ return state;
+}
+
+/**
+ * \brief Deletes a state data structure
+ * \param trans The state to be deleted
+ */
+void MC_state_delete(mc_state_t state, int free_snapshot){
+ if (state->system_state && free_snapshot){
+ MC_free_snapshot(state->system_state);
+ }
+ if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
+ xbt_free(state->index_comm);
+ xbt_free(state->incomplete_comm_pattern);
+ }
+ xbt_free(state->proc_status);
+ xbt_free(state);
+}
+
+void MC_state_interleave_process(mc_state_t state, smx_process_t process)
+{
+ assert(state);
+ state->proc_status[process->pid].state = MC_INTERLEAVE;
+ state->proc_status[process->pid].interleave_count = 0;
+}
+
+void MC_state_remove_interleave_process(mc_state_t state, smx_process_t process)
+{
+ if (state->proc_status[process->pid].state == MC_INTERLEAVE)
+ state->proc_status[process->pid].state = MC_DONE;
+}
+
+unsigned int MC_state_interleave_size(mc_state_t state)
+{
+ unsigned int i, size = 0;
+
+ for (i = 0; i < state->max_pid; i++) {
+ if ((state->proc_status[i].state == MC_INTERLEAVE)
+ || (state->proc_status[i].state == MC_MORE_INTERLEAVE))
+ size++;
+ }
+
+ return size;
+}
+
+int MC_state_process_is_done(mc_state_t state, smx_process_t process)
+{
+ return state->proc_status[process->pid].state == MC_DONE ? TRUE : FALSE;
+}
+
+void MC_state_set_executed_request(mc_state_t state, smx_simcall_t req,
+ int value)
+{
+ state->executed_req = *req;
+ state->req_num = value;
+
+ smx_process_t process = NULL;
+
+ /* The waitany and testany request are transformed into a wait or test request over the
+ * corresponding communication action so it can be treated later by the dependence
+ * function. */
+ switch (req->call) {
+ case SIMCALL_COMM_WAITANY:
+ state->internal_req.call = SIMCALL_COMM_WAIT;
+ state->internal_req.issuer = req->issuer;
+ MC_process_read_dynar_element(&mc_model_checker->process(),
+ &state->internal_comm, simcall_comm_waitany__get__comms(req),
+ value, sizeof(state->internal_comm));
+ simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
+ simcall_comm_wait__set__timeout(&state->internal_req, 0);
+ break;
+
+ case SIMCALL_COMM_TESTANY:
+ state->internal_req.call = SIMCALL_COMM_TEST;
+ state->internal_req.issuer = req->issuer;
+
+ if (value > 0)
+ MC_process_read_dynar_element(&mc_model_checker->process(),
+ &state->internal_comm, simcall_comm_testany__get__comms(req),
+ value, sizeof(state->internal_comm));
+
+ simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
+ simcall_comm_test__set__result(&state->internal_req, value);
+ break;
+
+ case SIMCALL_COMM_WAIT:
+ state->internal_req = *req;
+ MC_process_read_simple(&mc_model_checker->process(), &state->internal_comm ,
+ simcall_comm_wait__get__comm(req), sizeof(state->internal_comm));
+ simcall_comm_wait__set__comm(&state->executed_req, &state->internal_comm);
+ simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
+ break;
+
+ case SIMCALL_COMM_TEST:
+ state->internal_req = *req;
+ MC_process_read_simple(&mc_model_checker->process(), &state->internal_comm,
+ simcall_comm_test__get__comm(req), sizeof(state->internal_comm));
+ simcall_comm_test__set__comm(&state->executed_req, &state->internal_comm);
+ simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
+ break;
+
+ case SIMCALL_MC_RANDOM: {
+ state->internal_req = *req;
+ int random_max = simcall_mc_random__get__max(req);
+ if (value != random_max) {
+ MC_EACH_SIMIX_PROCESS(process,
+ mc_procstate_t procstate = &state->proc_status[process->pid];
+ const smx_process_t issuer = MC_smx_simcall_get_issuer(req);
+ if (process->pid == issuer->pid) {
+ procstate->state = MC_MORE_INTERLEAVE;
+ break;
+ }
+ );
+ }
+ break;
+ }
+
+ default:
+ state->internal_req = *req;
+ break;
+ }
+}
+
+smx_simcall_t MC_state_get_executed_request(mc_state_t state, int *value)
+{
+ *value = state->req_num;
+ return &state->executed_req;
+}
+
+smx_simcall_t MC_state_get_internal_request(mc_state_t state)
+{
+ return &state->internal_req;
+}
+
+static inline smx_simcall_t MC_state_get_request_for_process(
+ mc_state_t state, int*value, smx_process_t process)
+{
+ mc_procstate_t procstate = &state->proc_status[process->pid];
+
+ if (procstate->state != MC_INTERLEAVE
+ && procstate->state != MC_MORE_INTERLEAVE)
+ return NULL;
+ if (!MC_process_is_enabled(process))
+ return NULL;
+
+ switch (process->simcall.call) {
+
+ case SIMCALL_COMM_WAITANY:
+ *value = -1;
+ while (procstate->interleave_count <
+ MC_process_read_dynar_length(&mc_model_checker->process(),
+ simcall_comm_waitany__get__comms(&process->simcall))) {
+ if (MC_request_is_enabled_by_idx
+ (&process->simcall, procstate->interleave_count++)) {
+ *value = procstate->interleave_count - 1;
+ break;
+ }
+ }
+
+ if (procstate->interleave_count >=
+ MC_process_read_dynar_length(&mc_model_checker->process(),
+ simcall_comm_waitany__get__comms(&process->simcall)))
+ procstate->state = MC_DONE;
+
+ if (*value != -1)
+ return &process->simcall;
+
+ break;
+
+ case SIMCALL_COMM_TESTANY: {
+ unsigned start_count = procstate->interleave_count;
+ *value = -1;
+ while (procstate->interleave_count <
+ MC_process_read_dynar_length(&mc_model_checker->process(),
+ simcall_comm_testany__get__comms(&process->simcall))) {
+ if (MC_request_is_enabled_by_idx
+ (&process->simcall, procstate->interleave_count++)) {
+ *value = procstate->interleave_count - 1;
+ break;
+ }
+ }
+
+ if (procstate->interleave_count >=
+ MC_process_read_dynar_length(&mc_model_checker->process(),
+ simcall_comm_testany__get__comms(&process->simcall)))
+ procstate->state = MC_DONE;
+
+ if (*value != -1 || start_count == 0)
+ return &process->simcall;
+
+ break;
+ }
+
+ case SIMCALL_COMM_WAIT: {
+ smx_synchro_t remote_act = simcall_comm_wait__get__comm(&process->simcall);
+ s_smx_synchro_t act;
+ MC_process_read_simple(&mc_model_checker->process(),
+ &act, remote_act, sizeof(act));
+ if (act.comm.src_proc && act.comm.dst_proc) {
+ *value = 0;
+ } else {
+ if (act.comm.src_proc == NULL && act.comm.type == SIMIX_COMM_READY
+ && act.comm.detached == 1)
+ *value = 0;
+ else
+ *value = -1;
+ }
+ procstate->state = MC_DONE;
+ return &process->simcall;
+ }
+
+ case SIMCALL_MC_RANDOM:
+ if (procstate->state == MC_INTERLEAVE)
+ *value = simcall_mc_random__get__min(&process->simcall);
+ else {
+ if (state->req_num < simcall_mc_random__get__max(&process->simcall))
+ *value = state->req_num + 1;
+ }
+ procstate->state = MC_DONE;
+ return &process->simcall;
+
+ default:
+ procstate->state = MC_DONE;
+ *value = 0;
+ return &process->simcall;
+ }
+ return NULL;
+}
+
+smx_simcall_t MC_state_get_request(mc_state_t state, int *value)
+{
+ smx_process_t process = NULL;
+ MC_EACH_SIMIX_PROCESS(process,
+ smx_simcall_t res = MC_state_get_request_for_process(state, value, process);
+ if (res)
+ return res;
+ );
+
+ return NULL;
+}
+
+}
SG_BEGIN_DECL()
-extern mc_global_t initial_global_state;
+extern XBT_INTERNAL mc_global_t initial_global_state;
/* Possible exploration status of a process in a state */
typedef enum {
mc_snapshot_t system_state; /* Snapshot of system state */
int num;
int in_visited_states;
- xbt_dynar_t incomplete_comm_pattern; // comm determinism verification
+ // comm determinism verification (xbt_dynar_t<xbt_dynar_t<mc_comm_pattern_t>):
+ xbt_dynar_t incomplete_comm_pattern;
xbt_dynar_t index_comm; // comm determinism verification
} s_mc_state_t, *mc_state_t;
-mc_state_t MC_state_new(void);
-void MC_state_delete(mc_state_t state, int free_snapshot);
-void MC_state_interleave_process(mc_state_t state, smx_process_t process);
-unsigned int MC_state_interleave_size(mc_state_t state);
-int MC_state_process_is_done(mc_state_t state, smx_process_t process);
-void MC_state_set_executed_request(mc_state_t state, smx_simcall_t req, int value);
-smx_simcall_t MC_state_get_executed_request(mc_state_t state, int *value);
-smx_simcall_t MC_state_get_internal_request(mc_state_t state);
-smx_simcall_t MC_state_get_request(mc_state_t state, int *value);
-void MC_state_remove_interleave_process(mc_state_t state, smx_process_t process);
+XBT_INTERNAL mc_state_t MC_state_new(void);
+XBT_INTERNAL void MC_state_delete(mc_state_t state, int free_snapshot);
+XBT_INTERNAL void MC_state_interleave_process(mc_state_t state, smx_process_t process);
+XBT_INTERNAL unsigned int MC_state_interleave_size(mc_state_t state);
+XBT_INTERNAL int MC_state_process_is_done(mc_state_t state, smx_process_t process);
+XBT_INTERNAL void MC_state_set_executed_request(mc_state_t state, smx_simcall_t req, int value);
+XBT_INTERNAL smx_simcall_t MC_state_get_executed_request(mc_state_t state, int *value);
+XBT_INTERNAL smx_simcall_t MC_state_get_internal_request(mc_state_t state);
+XBT_INTERNAL smx_simcall_t MC_state_get_request(mc_state_t state, int *value);
+XBT_INTERNAL void MC_state_remove_interleave_process(mc_state_t state, smx_process_t process);
SG_END_DECL()
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+/** \file
+ * Libunwind support for mc_address_space objects.
+ */
+
+// We need this for the register indices:
+// #define _GNU_SOURCE
+
+#include <string.h>
+
+// On x86_64, libunwind unw_context_t has the same layout as ucontext_t:
+#include <sys/ucontext.h>
+
+#include <libunwind.h>
+
+#include "mc_object_info.h"
+#include "mc_process.h"
+#include "mc_unw.h"
+
+extern "C" {
+
+// ***** 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,
+ MC_ADDRESS_SPACE_READ_FLAGS_NONE, 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 = (greg_t*) 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,
+ &put_unwind_info,
+ &get_dyn_info_list_addr,
+ &access_mem,
+ &access_reg,
+ &access_fpreg,
+ &resume,
+ &get_proc_name
+ };
+
+// ***** Context management
+
+int mc_unw_init_context(
+ mc_unw_context_t context, mc_process_t process, unw_context_t* c)
+{
+ context->address_space = (mc_address_space_t) process;
+ context->process = process;
+
+ // Take a copy of the context for our own purpose:
+ context->context = *c;
+#if defined(PROCESSOR_x86_64) || defined(PROCESSOR_i686)
+ // On x86_64, ucontext_t contains a pointer to itself for FP registers.
+ // We don't really need support for FR registers as they are caller saved
+ // and probably never use those fields as libunwind-x86_64 does not read
+ // FP registers from the unw_context_t
+ // but we fix the pointer in order to avoid dangling pointers:
+ context->context.uc_mcontext.fpregs = &(context->context.__fpregs_mem);
+#else
+ // Do we need to do any fixup like this?
+ #error Target CPU type is not handled.
+#endif
+
+ return 0;
+}
+
+int mc_unw_destroy_context(mc_unw_context_t context)
+{
+ context->address_space = NULL;
+ context->process = NULL;
+ return 0;
+}
+
+// ***** Cursor management
+
+int mc_unw_init_cursor(unw_cursor_t *cursor, mc_unw_context_t context)
+{
+ if (!context->process || !context->address_space)
+ return -UNW_EUNSPEC;
+ mc_address_space_t as = context->address_space;
+
+ // Use local unwinding for current process:
+ if (MC_is_process(as) && MC_process_is_self((mc_process_t) as))
+ return unw_init_local(cursor, &context->context);
+
+ return unw_init_remote(cursor, context->process->unw_addr_space, context);
+}
+
+}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+
+/ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_UNW_H
+#define MC_UNW_H
+
+/** \file
+ * Libunwind implementation for the model-checker
+ *
+ * Libunwind provides an pluggable stack unwinding API: the way the current
+ * registers and memory is accessed, the way unwinding informations is found
+ * is pluggable.
+ *
+ * This component implements the libunwind API for he model-checker:
+ *
+ * * reading memory from a mc_address_space_t;
+ *
+ * * reading stack registers from a saved snapshot (context).
+ *
+ * Parts of the libunwind information fetching is currently handled by the
+ * standard `libunwind` implementations (either the local one or the ptrace one)
+ * because parsing `.eh_frame` section is not fun and `libdw` does not help
+ * much here.
+ */
+
+#include "mc_process.h"
+
+SG_BEGIN_DECL()
+
+// ***** Libunwind namespace
+
+/** Virtual table for our `libunwind-process_vm_readv` implementation.
+ *
+ * This implementation reuse most the code of `libunwind-ptrace` but
+ * does not use ptrace() to read the target process memory by
+ * `process_vm_readv()` or `/dev/${pid}/mem` if possible.
+ *
+ * Does not support any MC-specific behaviour (privatisation, snapshots)
+ * and `ucontext_t`.
+ *
+ * It works with `void*` contexts allocated with `_UPT_create(pid)`.
+ */
+extern unw_accessors_t mc_unw_vmread_accessors;
+
+/** Virtual table for our `libunwind` implementation
+ *
+ * Stack unwinding on a `mc_process_t` (for memory, unwinding information)
+ * and `ucontext_t` (for processor registers).
+ *
+ * It works with the `s_mc_unw_context_t` context.
+ */
+extern XBT_INTERNAL 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 */
+XBT_INTERNAL 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 */
+XBT_INTERNAL int mc_unw_destroy_context(mc_unw_context_t context);
+
+// ***** Libunwind cursor
+
+/** Initialises a `libunwind` cursor */
+XBT_INTERNAL int mc_unw_init_cursor(unw_cursor_t *cursor, mc_unw_context_t context);
+
+SG_END_DECL()
+
+#endif
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include "mc_unw.h"
+
+extern "C" {
+
+/** \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 = (_UPT_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;
+ 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 };
+ ssize_t s = process_vm_readv(pid, &local, 1, &remote, 1, 0);
+ if (s >= 0) {
+ if ((size_t) 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 =
+ {
+ &_UPT_find_proc_info,
+ &_UPT_put_unwind_info,
+ &_UPT_get_dyn_info_list_addr,
+ &access_mem,
+ &_UPT_access_reg,
+ &_UPT_access_fpreg,
+ &_UPT_resume,
+ &_UPT_get_proc_name
+ };
+
+}
#include "mc_safety.h"
#include "mc_liveness.h"
#include "mc_private.h"
+#include "mc_process.h"
+#include "mc_smx.h"
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_visited, mc,
"Logging specific to state equaity detection mechanisms");
*/
static mc_visited_state_t visited_state_new()
{
- 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->nb_processes = xbt_swag_size(simix_global->process_list);
+ mc_process_t process = &(mc_model_checker->process());
+ mc_visited_state_t new_state = xbt_new0(s_mc_visited_state_t, 1);
+ new_state->heap_bytes_used = mmalloc_get_bytes_used_remote(
+ MC_process_get_heap(process)->heaplimit,
+ MC_process_get_malloc_info(process));
+
+ if (MC_process_is_self(&mc_model_checker->process())) {
+ new_state->nb_processes = xbt_swag_size(simix_global->process_list);
+ } else {
+ MC_process_smx_refresh(&mc_model_checker->process());
+ new_state->nb_processes = xbt_dynar_length(
+ mc_model_checker->process().smx_process_infos);
+ }
+
new_state->system_state = MC_take_snapshot(mc_stats->expanded_states);
new_state->num = mc_stats->expanded_states;
new_state->other_num = -1;
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->nb_processes = xbt_swag_size(simix_global->process_list);
+ pair->heap_bytes_used = mmalloc_get_bytes_used_remote(
+ MC_process_get_heap(process)->heaplimit,
+ MC_process_get_malloc_info(process));
+ if (MC_process_is_self(&mc_model_checker->process())) {
+ pair->nb_processes = xbt_swag_size(simix_global->process_list);
+ } else {
+ MC_process_smx_refresh(&mc_model_checker->process());
+ pair->nb_processes = xbt_dynar_length(
+ mc_model_checker->process().smx_process_infos);
+ }
pair->automaton_state = automaton_state;
pair->num = pair_num;
pair->other_num = -1;
*/
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;
-
- int cursor = 0, previous_cursor, next_cursor;
+ int cursor = 0, previous_cursor;
int nb_processes, heap_bytes_used, nb_processes_test, heap_bytes_used_test;
void *ref_test;
*min = previous_cursor;
previous_cursor--;
}
- next_cursor = cursor + 1;
+ size_t next_cursor = cursor + 1;
while (next_cursor < xbt_dynar_length(list)) {
if (_sg_mc_liveness) {
ref_test = (mc_visited_pair_t) xbt_dynar_get_as(list, next_cursor, mc_visited_pair_t);
*max = next_cursor;
next_cursor++;
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
return -1;
}
}
}
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
return cursor;
}
communications are not finished (at least, data are transfered). These communications
are incomplete and they cannot be analyzed and compared with the initial pattern. */
if (_sg_mc_comms_determinism || _sg_mc_send_determinism) {
- int current_process = 1;
- while (current_process < simix_process_maxpid) {
+ size_t current_process = 1;
+ while (current_process < MC_smx_get_maxpid()) {
if (!xbt_dynar_is_empty((xbt_dynar_t)xbt_dynar_get_as(incomplete_communications_pattern, current_process, xbt_dynar_t))){
XBT_DEBUG("Some communications are not finished, cannot stop the exploration ! State not visited.");
partial_comm = 1;
}
}
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
mc_visited_state_t new_state = visited_state_new();
graph_state->system_state = new_state->system_state;
graph_state->in_visited_states = 1;
if (xbt_dynar_is_empty(visited_states)) {
xbt_dynar_push(visited_states, &new_state);
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
return NULL;
} else {
XBT_DEBUG("State %d already visited ! (equal to state %d (state %d in dot_output))", new_state->num, state_test->num, new_state->other_num);
xbt_dynar_remove_at(visited_states, (min + res) - 1, NULL);
xbt_dynar_insert_at(visited_states, (min+res) - 1, &new_state);
- if(!raw_mem_set)
- MC_SET_STD_HEAP;
return new_state->other_num;
} */
- if(!partial_comm && initial_global_state->initial_communications_pattern_done){
+ if (_sg_mc_safety || (!partial_comm
+ && initial_global_state->initial_communications_pattern_done)) {
cursor = min;
while (cursor <= max) {
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;
return state_test;
}
cursor++;
}
// We have reached the maximum number of stored states;
- if (xbt_dynar_length(visited_states) > _sg_mc_visited) {
+ if ((ssize_t) xbt_dynar_length(visited_states) > _sg_mc_visited) {
XBT_DEBUG("Try to remove visited state (maximum number of stored states reached)");
unsigned int cursor2 = 0;
unsigned int index2 = 0;
xbt_dynar_foreach(visited_states, cursor2, state_test){
- if (!mc_important_snapshot(state_test->system_state) && state_test->num < min2) {
+ if (state_test->num < min2) {
index2 = cursor2;
min2 = state_test->num;
}
XBT_DEBUG("Remove visited state (maximum number of stored states reached)");
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
return NULL;
-
}
}
if (_sg_mc_visited == 0)
return -1;
- int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
mc_visited_pair_t new_visited_pair = NULL;
if (visited_pair == NULL) {
MC_pair_delete(pair_test);
}
}
- if(!raw_mem_set)
- MC_SET_STD_HEAP;
return pair->other_num;
} */
cursor = min;
} else {
MC_visited_pair_delete(pair_test);
}
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
return new_visited_pair->other_num;
}
}
}
}
- if (xbt_dynar_length(visited_pairs) > _sg_mc_visited) {
+ if ((ssize_t) xbt_dynar_length(visited_pairs) > _sg_mc_visited) {
int min2 = mc_stats->expanded_pairs;
unsigned int cursor2 = 0;
unsigned int index2 = 0;
xbt_dynar_foreach(visited_pairs, cursor2, pair_test) {
- if (!mc_important_snapshot(pair_test->graph_state->system_state) && pair_test->num < min2) {
+ if (pair_test->num < min2) {
index2 = cursor2;
min2 = pair_test->num;
}
}
}
-
- if (!mc_mem_set)
- MC_SET_STD_HEAP;
-
return -1;
}
+
+}
-/* Copyright (c) 2008-2014. The SimGrid Team.
+/* Copyright (c) 2008-2015. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#include "internal_config.h"
#include "mc_object_info.h"
-#include "mc_private.h"
+#include "mc/mc_private.h"
#include "smpi/private.h"
#include "mc/mc_snapshot.h"
+#include "mc/mc_ignore.h"
+#include "mc/mc_protocol.h"
+#include "mc/mc_client.h"
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_ignore, mc,
+extern "C" {
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mcer_ignore, mc,
"Logging specific to MC ignore mechanism");
+// ***** Ignore heap chunks
-/**************************** Global variables ******************************/
-xbt_dynar_t mc_checkpoint_ignore;
extern xbt_dynar_t mc_heap_comparison_ignore;
-extern xbt_dynar_t stacks_areas;
-
-/**************************** Structures ******************************/
-typedef struct s_mc_stack_ignore_variable {
- char *var_name;
- char *frame;
-} s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t;
-
-/**************************** Free functions ******************************/
-
-static void stack_ignore_variable_free(mc_stack_ignore_variable_t v)
-{
- xbt_free(v->var_name);
- xbt_free(v->frame);
- xbt_free(v);
-}
-
-static void stack_ignore_variable_free_voidp(void *v)
-{
- stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
-}
void heap_ignore_region_free(mc_heap_ignore_region_t r)
{
heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
}
-static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r)
-{
- xbt_free(r);
-}
-static void checkpoint_ignore_region_free_voidp(void *r)
+void MC_heap_region_ignore_insert(mc_heap_ignore_region_t region)
{
- checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
-}
-
-/***********************************************************************/
-
-void MC_ignore_heap(void *address, size_t size)
-{
-
- 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]++;
- }
-
if (mc_heap_comparison_ignore == NULL) {
mc_heap_comparison_ignore =
xbt_dynar_new(sizeof(mc_heap_ignore_region_t),
heap_ignore_region_free_voidp);
xbt_dynar_push(mc_heap_comparison_ignore, ®ion);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
}
int start = 0;
int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
+ // Find the position where we want to insert the mc_heap_ignore_region_t:
while (start <= end) {
cursor = (start + end) / 2;
current_region =
(mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
cursor,
mc_heap_ignore_region_t);
- if (current_region->address == address) {
+ if (current_region->address == region->address) {
heap_ignore_region_free(region);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
- } else if (current_region->address < address) {
+ } else if (current_region->address < region->address) {
start = cursor + 1;
} else {
end = cursor - 1;
}
}
- if (current_region->address < address)
+ // Insert it mc_heap_ignore_region_t:
+ if (current_region->address < region->address)
xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, ®ion);
else
xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, ®ion);
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
}
-void MC_remove_ignore_heap(void *address, size_t size)
+void MC_heap_region_ignore_remove(void *address, size_t size)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- MC_SET_MC_HEAP;
-
unsigned int cursor = 0;
int start = 0;
int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
MC_remove_ignore_heap(address, size);
}
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
-
}
-void MC_ignore_global_variable(const char *name)
+// ***** Ignore global variables
+
+void MCer_ignore_global_variable(const char *name)
{
+ mc_process_t process = &mc_model_checker->process();
+ xbt_assert(process->object_infos, "MC subsystem not initialized");
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
+ size_t n = process->object_infos_size;
+ for (size_t i=0; i!=n; ++i) {
+ mc_object_info_t info = process->object_infos[i];
- MC_SET_MC_HEAP;
+ // 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;
+ }
+ }
+ }
+}
- xbt_assert(mc_libsimgrid_info, "MC subsystem not initialized");
+// ***** Ignore local variables
- unsigned int cursor = 0;
- dw_variable_t current_var;
- int start = 0;
- int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
+static void mc_ignore_local_variable_in_scope(const char *var_name,
+ const char *subprogram_name,
+ dw_frame_t subprogram,
+ dw_frame_t scope);
+static void MC_ignore_local_variable_in_object(const char *var_name,
+ const char *subprogram_name,
+ mc_object_info_t info);
- 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;
- }
+void MC_ignore_local_variable(const char *var_name, const char *frame_name)
+{
+ mc_process_t process = &mc_model_checker->process();
+ if (strcmp(frame_name, "*") == 0)
+ frame_name = NULL;
+
+ 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;
+static void MC_ignore_local_variable_in_object(const char *var_name,
+ const char *subprogram_name,
+ mc_object_info_t info)
+{
+ xbt_dict_cursor_t cursor2;
+ dw_frame_t frame;
+ char *key;
+ xbt_dict_foreach(info->subprograms, cursor2, key, frame) {
+ mc_ignore_local_variable_in_scope(var_name, subprogram_name, frame, frame);
+ }
}
/** \brief Ignore a local variable in a scope
{
// Processing of direct variables:
- // If the current subprogram matche the given name:
+ // If the current subprogram matches the given name:
if (!subprogram_name ||
(subprogram->name && strcmp(subprogram_name, subprogram->name) == 0)) {
}
}
-static void MC_ignore_local_variable_in_object(const char *var_name,
- const char *subprogram_name,
- mc_object_info_t info)
-{
- xbt_dict_cursor_t cursor2;
- dw_frame_t frame;
- char *key;
- xbt_dict_foreach(info->subprograms, cursor2, key, frame) {
- mc_ignore_local_variable_in_scope(var_name, subprogram_name, frame, frame);
- }
-}
+// ****** Checkpoint ignore:
-void MC_ignore_local_variable(const char *var_name, const char *frame_name)
+static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r)
{
-
- int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
- if (strcmp(frame_name, "*") == 0)
- frame_name = NULL;
-
- 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);
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
-
+ xbt_free(r);
}
-/** @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
- * they are with this function.
- *
- * @param stack
- * @param process Process owning the stack
- * @param context
- * @param size Size of the stack
- */
-void MC_new_stack_area(void *stack, smx_process_t process, void *context, size_t size)
+static void checkpoint_ignore_region_free_voidp(void *r)
{
-
- 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);
- region->address = stack;
- region->process_name = process && process->name ? strdup(process->name) : NULL;
- region->context = context;
- region->size = size;
- region->block =
- ((char *) stack -
- (char *) std_heap->heapbase) / BLOCKSIZE + 1;
-#ifdef HAVE_SMPI
- if (smpi_privatize_global_variables && process) {
- region->process_index = smpi_process_index_of_smx_process(process);
- } else
-#endif
- region->process_index = -1;
-
- xbt_dynar_push(stacks_areas, ®ion);
-
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
+ checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
}
-void MC_ignore(void *addr, 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;
-
- if (mc_checkpoint_ignore == NULL)
- mc_checkpoint_ignore =
- xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t),
- checkpoint_ignore_region_free_voidp);
+// ***** Generic memory ignore mechanism
+void MC_process_ignore_memory(mc_process_t process, void *addr, size_t size)
+{
+ xbt_dynar_t checkpoint_ignore = process->checkpoint_ignore;
mc_checkpoint_ignore_region_t region =
xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
region->addr = addr;
region->size = size;
- if (xbt_dynar_is_empty(mc_checkpoint_ignore)) {
- xbt_dynar_push(mc_checkpoint_ignore, ®ion);
+ if (xbt_dynar_is_empty(checkpoint_ignore)) {
+ xbt_dynar_push(checkpoint_ignore, ®ion);
} else {
unsigned int cursor = 0;
int start = 0;
- int end = xbt_dynar_length(mc_checkpoint_ignore) - 1;
+ int end = xbt_dynar_length(checkpoint_ignore) - 1;
mc_checkpoint_ignore_region_t current_region = NULL;
while (start <= end) {
cursor = (start + end) / 2;
current_region =
- (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(mc_checkpoint_ignore,
+ (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(checkpoint_ignore,
cursor,
mc_checkpoint_ignore_region_t);
if (current_region->addr == addr) {
if (current_region->size == size) {
checkpoint_ignore_region_free(region);
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
return;
} else if (current_region->size < size) {
start = cursor + 1;
if (current_region->addr == addr) {
if (current_region->size < size) {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, ®ion);
} else {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor, ®ion);
}
} else if (current_region->addr < addr) {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, ®ion);
} else {
- xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ xbt_dynar_insert_at(checkpoint_ignore, cursor, ®ion);
}
}
+}
+
+extern xbt_dynar_t stacks_areas;
+
+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);
+}
- if (!raw_mem_set)
- MC_SET_STD_HEAP;
}
--- /dev/null
+/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/dynar.h>
+
+#include "mc/datatypes.h"
+#include "mc/mc_process.h"
+
+#include "xbt/misc.h" /* SG_BEGIN_DECL */
+
+SG_BEGIN_DECL();
+
+XBT_INTERNAL void MCer_ignore_global_variable(const char *var_name);
+XBT_INTERNAL void MC_heap_region_ignore_insert(mc_heap_ignore_region_t region);
+XBT_INTERNAL void MC_heap_region_ignore_remove(void *address, size_t size);
+XBT_INTERNAL void MC_process_ignore_memory(mc_process_t process, void *addr, size_t size);
+
+SG_END_DECL();
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <stdlib.h>
+
+#include <sys/types.h>
+
#include "mc_memory_map.h"
#include "mc_private.h"
-#include <stdlib.h>
+
+extern "C" {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory_map, mc,
"Logging specific to algorithms for memory_map");
-memory_map_t MC_get_memory_map(void)
+memory_map_t MC_get_memory_map(pid_t pid)
{
- FILE *fp; /* File pointer to process's proc maps file */
- char *line = NULL; /* Temporal storage for each line that is readed */
- ssize_t read; /* Number of bytes readed */
- size_t n = 0; /* Amount of bytes to read by xbt_getline */
- memory_map_t ret = NULL; /* The memory map to return */
-
-/* The following variables are used during the parsing of the file "maps" */
- s_map_region_t memreg; /* temporal map region used for creating the map */
- char *lfields[6], *tok, *endptr;
- int i;
-
-/* Open the actual process's proc maps file and create the memory_map_t */
-/* to be returned. */
- fp = fopen("/proc/self/maps", "r");
-
+ /* Open the actual process's proc maps file and create the memory_map_t */
+ /* to be returned. */
+ char* path = bprintf("/proc/%i/maps", (int) pid);
+ FILE *fp = fopen(path, "r");
+ free(path);
if(fp == NULL)
perror("fopen failed");
-
xbt_assert(fp,
- "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug.");
-
+ "Cannot open %s to investigate the memory map of the process.", path);
setbuf(fp, NULL);
- ret = xbt_new0(s_memory_map_t, 1);
+ memory_map_t ret = xbt_new0(s_memory_map_t, 1);
/* Read one line at the time, parse it and add it to the memory map to be returned */
+ ssize_t read; /* Number of bytes readed */
+ char* line = NULL;
+ size_t n = 0; /* Amount of bytes to read by xbt_getline */
while ((read = xbt_getline(&line, &n, fp)) != -1) {
//fprintf(stderr,"%s", line);
/* Tokenize the line using spaces as delimiters and store each token */
/* in lfields array. We expect 5 tokens/fields */
+ char* lfields[6];
lfields[0] = strtok(line, " ");
+ int i;
for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
lfields[i] = strtok(NULL, " ");
}
/* Ok we are good enough to try to get the info we need */
/* First get the start and the end address of the map */
- tok = strtok(lfields[0], "-");
+ char *tok = strtok(lfields[0], "-");
if (tok == NULL)
xbt_abort();
+ s_map_region_t memreg; /* temporal map region used for creating the map */
+ char *endptr;
memreg.start_addr = (void *) strtoul(tok, &endptr, 16);
/* Make sure that the entire string was an hex number */
if (*endptr != '\0')
/* Create space for a new map region in the region's array and copy the */
/* parsed stuff from the temporal memreg variable */
- ret->regions =
+ XBT_DEBUG("Found region for %s",
+ memreg.pathname ? memreg.pathname : "(null)");
+ ret->regions = (map_region_t)
xbt_realloc(ret->regions, sizeof(memreg) * (ret->mapsize + 1));
memcpy(ret->regions + ret->mapsize, &memreg, sizeof(memreg));
ret->mapsize++;
}
free(line);
-
fclose(fp);
-
return ret;
}
xbt_free(map->regions);
xbt_free(map);
}
+
+}
--- /dev/null
+ /* Copyright (c) 2015. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <exception>
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+
+#include <signal.h>
+#include <poll.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
+#include <xbt/log.h>
+
+#include "simgrid/sg_config.h"
+#include "xbt_modinter.h"
+
+#include "mc_base.h"
+#include "mc_private.h"
+#include "mc_protocol.h"
+#include "mc_server.h"
+#include "mc_safety.h"
+#include "mc_comm_pattern.h"
+#include "mc_liveness.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_main, mc, "Entry point for simgrid-mc");
+
+static int do_child(int socket, char** argv)
+{
+ XBT_DEBUG("Inside the child process PID=%i", (int) getpid());
+
+#ifdef __linux__
+ // Make sure we do not outlive our parent:
+ if (prctl(PR_SET_PDEATHSIG, SIGHUP) != 0) {
+ std::perror("simgrid-mc");
+ return MC_SERVER_ERROR;
+ }
+#endif
+
+ 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_model_checker(child, socket);
+ if (_sg_mc_comms_determinism || _sg_mc_send_determinism)
+ MC_modelcheck_comm_determinism();
+ else if (!_sg_mc_property_file || _sg_mc_property_file[0] == '\0')
+ MC_modelcheck_safety();
+ else
+ MC_modelcheck_liveness();
+ mc_server->shutdown();
+ mc_server->exit();
+ }
+ catch(std::exception& e) {
+ XBT_ERROR("Exception: %s", 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 = true;
+ 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_die("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;
+}
fflush(stderr);
if (MC_is_active()) {
- MC_do_the_modelcheck_for_real();
+ MC_run();
} else {
SIMIX_run();
}
MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
double timeout)
{
- xbt_ex_t e;
msg_error_t ret = MSG_OK;
simdata_task_t t_simdata = NULL;
msg_process_t process = MSG_process_self();
p_simdata->waiting_task = task;
+ xbt_ex_t e;
/* Try to send it by calling SIMIX network layer */
TRY {
smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simix call */
int argc, char **argv,
xbt_dict_t properties)
{
- xbt_assert(code != NULL && host != NULL, "Invalid parameters");
+ xbt_assert(code != NULL && host != NULL, "Invalid parameters: host and code params must not be NULL");
simdata_process_t simdata = xbt_new0(s_simdata_process_t, 1);
msg_process_t process;
*/
void* MSG_process_get_data(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: first parameter must not be NULL!");
/* get from SIMIX the MSG process data, and then the user data */
simdata_process_t simdata = simcall_process_get_data(process);
*/
msg_error_t MSG_process_set_data(msg_process_t process, void *data)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: first parameter must not be NULL!");
simdata_process_t simdata = simcall_process_get_data(process);
simdata->data = data;
*/
int MSG_process_get_PPID(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
return simcall_process_get_PPID(process);
}
*/
const char *MSG_process_get_name(msg_process_t process)
{
- xbt_assert(process, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
return simcall_process_get_name(process);
}
*/
xbt_dict_t MSG_process_get_properties(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
return simcall_process_get_properties(process);
*/
msg_error_t MSG_process_suspend(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
TRACE_msg_process_suspend(process);
simcall_process_suspend(process);
*/
msg_error_t MSG_process_resume(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
TRACE_msg_process_resume(process);
simcall_process_resume(process);
*/
int MSG_process_is_suspended(msg_process_t process)
{
- xbt_assert(process != NULL, "Invalid parameter");
+ xbt_assert(process != NULL, "Invalid parameter: First argument must not be NULL");
return simcall_process_is_suspended(process);
}
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
+typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
- * existing scanners that call yyless() from OUTSIDE dax_lex.
+ * existing scanners that call yyless() from OUTSIDE dax_lex.
* One obvious solution it to make yy_act a global. I tried that, and saw
* a 5% performance hit in a non-dax_lineno scanner, because yy_act is
* normally declared as a register variable-- so it is not worth it.
if ( *p == '\n' )\
--dax_lineno;\
}while(0)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[141] =
{ 0,
-0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
- 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, };
static yy_state_type yy_last_accepting_state;
* FleXML is Copyright (C) 1999-2005 Kristoffer Rose. All rights reserved.
* FleXML is Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
* (1.9.6).
- *
+ *
* There are two, intertwined parts to this program, part A and part B.
*
* Part A
* ------
- *
- * Some parts, here collectively called "Part A", are found in the
+ *
+ * Some parts, here collectively called "Part A", are found in the
* FleXML package. They are Copyright (C) 1999-2005 Kristoffer Rose
* and Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
*
* Notice that these are explicit rights granted to you for files
* generated by the FleXML system. For your rights in connection with
* the FleXML system itself please consult the GNU General Public License.
- *
+ *
* Part B
* ------
- *
- * The other parts, here collectively called "Part B", and which came
- * from the DTD used by FleXML to generate this program, can be
+ *
+ * The other parts, here collectively called "Part B", and which came
+ * from the DTD used by FleXML to generate this program, can be
* distributed (or not, as the case may be) under the terms of whoever
- * wrote them, provided these terms respect and obey the two conditions
+ * wrote them, provided these terms respect and obey the two conditions
* above under the heading "Part A".
*
* The author of and contributors to FleXML specifically disclaim
- * any copyright interest in "Part B", unless "Part B" was written
+ * any copyright interest in "Part B", unless "Part B" was written
* by the author of or contributors to FleXML.
- *
+ *
*/
/* Version strings. */
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
-
+
#if defined(_XBT_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__TOS_WIN__)
# ifndef __STRICT_ANSI__
# include <io.h>
#else
# include <unistd.h>
#endif
-
+
#ifndef FLEXML_INDEXSTACKSIZE
#define FLEXML_INDEXSTACKSIZE 1000
#endif
{
ck_ilimit();
indexstack[inext++] = p;
- indexstack[inext++] = bnext;
+ indexstack[inext++] = bnext;
}
static int popbuffer(void)
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = NULL;
-
+
static void yy_push_state (int new_state );
-
+
static void yy_pop_state (void );
-
+
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
if ( !(yy_init) )
{
(yy_init) = 1;
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
yy_size_t yyl;
for ( yyl = 0; yyl < dax_leng; ++yyl )
if ( dax_text[yyl] == '\n' )
-
+
dax_lineno++;
;
}
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
-SET(ROOT_dax__adag);
+SET(ROOT_dax__adag);
YY_BREAK
case 12:
/* rule 12 can match eol */
*/
static int yy_get_next_buffer (void)
{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
static yy_state_type yy_get_previous_state (void)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
yy_current_state = (yy_start);
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
{
int c;
-
+
*(yy_c_buf_p) = (yy_hold_char);
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
(yy_hold_char) = *++(yy_c_buf_p);
if ( c == '\n' )
-
+
dax_lineno++;
;
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
- *
+ *
* @note This function does not reset the start condition to @c INITIAL .
*/
void dax_restart (FILE * input_file )
{
-
+
if ( ! YY_CURRENT_BUFFER ){
dax_ensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
- *
+ *
*/
void dax__switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
-
+
/* TODO. We should be able to replace this entire function body
* with
* dax_pop_buffer_state();
/** Allocate and initialize an input buffer state.
* @param file A readable stream.
* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- *
+ *
* @return the allocated buffer state.
*/
YY_BUFFER_STATE dax__create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) dax_alloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in dax__create_buffer()" );
/** Destroy the buffer.
* @param b a buffer created with dax__create_buffer()
- *
+ *
*/
void dax__delete_buffer (YY_BUFFER_STATE b )
{
-
+
if ( ! b )
return;
{
int oerrno = errno;
-
+
dax__flush_buffer(b );
b->yy_input_file = file;
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- *
+ *
*/
void dax__flush_buffer (YY_BUFFER_STATE b )
{
* the current state. This function will allocate the stack
* if necessary.
* @param new_buffer The new state.
- *
+ *
*/
void dax_push_buffer_state (YY_BUFFER_STATE new_buffer )
{
/** Removes and deletes the top of the stack, if present.
* The next element becomes the new top.
- *
+ *
*/
void dax_pop_buffer_state (void)
{
static void dax_ensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
-
+
if (!(yy_buffer_stack)) {
/* First allocation is just for 2 elements, since we don't know if this
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in dax_ensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
/** Setup the input buffer state to scan directly from a user-specified character buffer.
* @param base the character buffer
* @param size the size in bytes of the character buffer
- *
- * @return the newly allocated buffer state object.
+ *
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE dax__scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/** Setup the input buffer state to scan a string. The next call to dax_lex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
- *
+ *
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* dax__scan_bytes() instead.
*/
YY_BUFFER_STATE dax__scan_string (yyconst char * yystr )
{
-
+
return dax__scan_bytes(yystr,strlen(yystr) );
}
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- *
+ *
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE dax__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
char *buf;
yy_size_t n;
yy_size_t i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) dax_alloc(n );
/* Accessor methods (get/set functions) to struct members. */
/** Get the current line number.
- *
+ *
*/
int dax_get_lineno (void)
{
-
+
return dax_lineno;
}
/** Get the input stream.
- *
+ *
*/
FILE *dax_get_in (void)
{
}
/** Get the output stream.
- *
+ *
*/
FILE *dax_get_out (void)
{
}
/** Get the length of the current token.
- *
+ *
*/
yy_size_t dax_get_leng (void)
{
}
/** Get the current token.
- *
+ *
*/
char *dax_get_text (void)
/** Set the current line number.
* @param line_number
- *
+ *
*/
void dax_set_lineno (int line_number )
{
-
+
dax_lineno = line_number;
}
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
- *
+ *
* @see dax__switch_to_buffer
*/
void dax_set_in (FILE * in_str )
/* We do not touch dax_lineno unless the option is enabled. */
dax_lineno = 1;
-
+
(yy_buffer_stack) = 0;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
/* dax_lex_destroy is for both reentrant and non-reentrant scanners. */
int dax_lex_destroy (void)
{
-
+
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
dax__delete_buffer(YY_CURRENT_BUFFER );
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
#include "mc/mc.h"
#include "mc/mc_record.h"
#include "simgrid/instr.h"
+#include "mc/mc_replay.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_config, surf,
"About the configuration of simgrid");
xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_sparse_checkpoint, NULL);
xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/sparse-checkpoint", "no");
- /* do stateful model-checking */
- xbt_cfg_register(&_sg_cfg_set, "model-check/soft-dirty",
- "Use sparse per-page snapshots.",
- xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_soft_dirty, NULL);
- xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/soft-dirty", "no");
-
/* do liveness model-checking */
xbt_cfg_register(&_sg_cfg_set, "model-check/property",
"Specify the name of the file containing the property. It must be the result of the ltl2ba program.",
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)",
xbt_cfgelm_string, 0, 1, &_sg_cfg_cb__coll_reduce, NULL);
#endif // HAVE_SMPI
+ xbt_cfg_register(&_sg_cfg_set, "exception/cutpath",
+ "\"yes\" or \"no\". \"yes\" will cut all path information from call traces, used e.g. in exceptions.",
+ xbt_cfgelm_boolean, 1, 1, NULL, NULL);
+ xbt_cfg_setdefault_boolean(_sg_cfg_set, "exception/cutpath", "no");
+
xbt_cfg_register(&_sg_cfg_set, "clean_atexit",
"\"yes\" or \"no\". \"yes\" enables all the cleanups of SimGrid (XBT,SIMIX,MSG) to be registered with atexit. \"no\" may be useful if your code segfaults when calling the exit function.",
xbt_cfgelm_boolean, 1, 1, _sg_cfg_cb_clean_atexit, NULL);
/* retrieves the current directory of the current process */
const char *initial_path = __surf_get_initial_path();
xbt_assert((initial_path),
- "__surf_get_initial_path() failed! Can't resolves current Windows directory");
+ "__surf_get_initial_path() failed! Can't resolve current Windows directory");
surf_path = xbt_dynar_new(sizeof(char *), NULL);
xbt_cfg_setdefault_string(_sg_cfg_set, "path", initial_path);
/* 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/mc_replay.h"
#include "smx_private.h"
-#include "mc/mc_interface.h"
+#include "mc/mc_forward.h"
#include "xbt/ex.h"
#include <math.h> /* isfinite() */
+#include "mc/mc.h"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix);
if (simix_global->kill_process_function) {
XBT_DEBUG("Set kill time %f for process %s(%s)",kill_time, process->name,
sg_host_name(process->smx_host));
- SIMIX_timer_set(kill_time, simix_global->kill_process_function, process);
+ process->kill_timer = SIMIX_timer_set(kill_time, simix_global->kill_process_function, process);
}
}
}
*/
#include "smx_private.h"
-#include "mc/mc_interface.h"
+#include "mc/mc_forward.h"
#include "xbt/ex.h"
inline static smx_host_t simcall_BODY_host_get_by_name(const char* name) {
#include "smx_private.h"
#ifdef HAVE_MC
+#include "mc/mc_process.h"
#endif
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);
XBT_PUBLIC(const char*) simcall_names[]; /* Name of each simcall */
#include "popping_enum.h" /* Definition of e_smx_simcall_t, with one value per simcall */
-#include "mc/mc_interface.h" /* Definition of mc_snapshot_t, used by one simcall */
+#include "mc/mc_forward.h" /* Definition of mc_snapshot_t, used by one simcall */
typedef int (*simix_match_func_t)(void *, void *, smx_synchro_t);
typedef void (*simix_copy_data_func_t)(smx_synchro_t, void*, size_t);
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('#endif\n');
fd.write('\n');
fd.write('XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);\n\n');
###
fd = header('popping_bodies.c')
fd.write('#include "smx_private.h"\n')
- fd.write('#include "mc/mc_interface.h"\n')
+ fd.write('#include "mc/mc_forward.h"\n')
fd.write('#include "xbt/ex.h"\n')
handle(fd, Simcall.body, simcalls, simcalls_dict)
fd.close()
sysv_maestro_context = context;
}
+#ifdef HAVE_MC
if (MC_is_active() && code) {
- MC_new_stack_area(context->stack, ((smx_context_t)context)->process,
+ MC_register_stack_area(context->stack, ((smx_context_t)context)->process,
&(context->uc), smx_context_usable_stack_size);
}
+#endif
return (smx_context_t) context;
}
unsigned int cursor;
xbt_dynar_foreach(simix_global->process_to_run, cursor, process) {
+ XBT_DEBUG("Handling %p",process);
xbt_os_sem_release(((smx_ctx_thread_t) process->context)->begin);
xbt_os_sem_acquire(((smx_ctx_thread_t) process->context)->end);
}
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include <stdlib.h>
+
#include "smx_private.h"
#include "xbt/heap.h"
#include "xbt/sysdep.h"
#include "xbt/str.h"
#include "xbt/ex.h" /* ex_backtrace_display */
#include "mc/mc.h"
+#include "mc/mc_replay.h"
#include "simgrid/sg_config.h"
#ifdef HAVE_MC
#include "mc/mc_private.h"
+#include "mc/mc_protocol.h"
+#include "mc/mc_client.h"
#endif
#include "mc/mc_record.h"
if (sg_cfg_get_boolean("clean_atexit"))
atexit(SIMIX_clean);
+#ifdef HAVE_MC
+ // The communication initialisation is done ASAP.
+ // We need to commuicate initialisation of the different layers to the model-checker.
+ if (mc_mode == MC_MODE_NONE) {
+ if (getenv(MC_ENV_SOCKET_FD)) {
+ mc_mode = MC_MODE_CLIENT;
+ MC_client_init();
+ MC_client_hello();
+ MC_client_handle_messages();
+ }
+ }
+#endif
+
if (_sg_cfg_exit_asap)
exit(0);
}
SIMIX_simcall_handle(&process->simcall, 0);
}
}
+ /* Wake up all processes waiting for a Surf action to finish */
+ xbt_dynar_foreach(model_list, iter, model) {
+ XBT_DEBUG("Handling process whose action failed");
+ while ((action = surf_model_extract_failed_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
+ XBT_DEBUG("Handling process whose action terminated normally");
+ while ((action = surf_model_extract_done_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ if (surf_action_get_data(action) == NULL)
+ XBT_DEBUG("probably vcpu's action %p, skip", action);
+ else
+ SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
+ }
}
time = SIMIX_timer_next();
- if (time != -1.0 || xbt_swag_size(simix_global->process_list) != 0)
+ if (time != -1.0 || xbt_swag_size(simix_global->process_list) != 0) {
+ XBT_DEBUG("Calling surf_solve");
time = surf_solve(time);
-
+ XBT_DEBUG("Moving time ahead : %g", time);
+ }
/* Notify all the hosts that have failed */
/* FIXME: iterate through the list of failed host and mark each of them */
/* as failed. On each host, signal all the running processes with host_fail */
/* Wake up all processes waiting for a Surf action to finish */
xbt_dynar_foreach(model_list, iter, model) {
- while ((action = surf_model_extract_failed_action_set(model)))
+ XBT_DEBUG("Handling process whose action failed");
+ while ((action = surf_model_extract_failed_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
-
- while ((action = surf_model_extract_done_action_set(model)))
+ }
+ XBT_DEBUG("Handling process whose action terminated normally");
+ while ((action = surf_model_extract_done_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
if (surf_action_get_data(action) == NULL)
XBT_DEBUG("probably vcpu's action %p, skip", action);
else
SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
}
/* Autorestart all process */
* \param arg Parameters of the function
*
*/
-XBT_INLINE void SIMIX_timer_set(double date, void *function, void *arg)
+XBT_INLINE smx_timer_t SIMIX_timer_set(double date, void *function, void *arg)
{
smx_timer_t timer = xbt_new0(s_smx_timer_t, 1);
timer->func = function;
timer->args = arg;
xbt_heap_push(simix_timers, timer, date);
+ return timer;
+}
+/** @brief cancels a timer that was added earlier */
+XBT_INLINE void SIMIX_timer_remove(smx_timer_t timer) {
+ xbt_heap_rm_elm(simix_timers, timer, timer->date);
+}
+
+/** @brief Returns the date at which the timer will trigger (or 0 if NULL timer) */
+XBT_INLINE double SIMIX_timer_get_date(smx_timer_t timer) {
+ return timer?timer->date:0;
}
/**
#include "xbt/log.h"
#include "xbt/dict.h"
#include "mc/mc.h"
+#include "mc/mc_replay.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_host, simix,
"SIMIX hosts");
#include "smx_private.h"
#include "xbt/log.h"
#include "mc/mc.h"
+#include "mc/mc_replay.h"
#include "xbt/dict.h"
#include "smpi/private.h"
-
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_network, simix,
"SIMIX network-related synchronization");
#include "xbt/log.h"
#include "xbt/dict.h"
#include "mc/mc.h"
+#include "mc/mc_replay.h"
+#include "mc/mc_client.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
"Logging specific to SIMIX (process)");
SIMIX_process_on_exit_runall(process);
+ /* Unregister from the kill timer if any */
+ if (process->kill_timer != NULL)
+ SIMIX_timer_remove(process->kill_timer);
+
/* cancel non-blocking communications */
smx_synchro_t synchro;
while ((synchro = xbt_fifo_pop(process->comms))) {
}
}
+ XBT_DEBUG("%p should not be run anymore",process);
xbt_swag_remove(process, simix_global->process_list);
xbt_swag_remove(process, SIMIX_host_priv(process->smx_host)->process_list);
xbt_swag_insert(process, simix_global->process_to_destroy);
smx_process_t process = NULL;
while ((process = xbt_swag_extract(simix_global->process_to_destroy))) {
+ XBT_DEBUG("Getting rid of %p",process);
+
SIMIX_context_free(process->context);
/* Free the exception allocated at creation time */
if (arg->auto_restart && !SIMIX_host_get_state(arg->smx_host)) {
SIMIX_host_add_auto_restart_process(arg->smx_host,arg->name,arg->code, arg->data,
sg_host_name(arg->smx_host),
- arg->kill_time,
+ SIMIX_timer_get_date(arg->kill_timer),
arg->argc,arg->argv,arg->properties,
arg->auto_restart);
}
(*process)->code = code;
(*process)->argc = argc;
(*process)->argv = argv;
- (*process)->kill_time = kill_time;
XBT_VERB("Create context %s", (*process)->name);
if (kill_time > SIMIX_get_clock() && simix_global->kill_process_function) {
XBT_DEBUG("Process %s(%s) will be kill at time %f", (*process)->name,
sg_host_name((*process)->smx_host), kill_time);
- SIMIX_timer_set(kill_time, simix_global->kill_process_function, *process);
+ (*process)->kill_timer = SIMIX_timer_set(kill_time, simix_global->kill_process_function, *process);
}
}
}
}
}
if(!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != issuer) {
+ XBT_DEBUG("Inserting %s in the to_run list", process->name);
xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
break;
case SIMIX_SYNC_SLEEP:
- SIMIX_process_sleep_destroy(process->waiting_synchro);
- break;
-
case SIMIX_SYNC_JOIN:
SIMIX_process_sleep_destroy(process->waiting_synchro);
+ if (!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self()) {
+ XBT_DEBUG("Inserting %s in the to_run list", process->name);
+ xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+ }
break;
case SIMIX_SYNC_SYNCHRO:
}
process->waiting_synchro = NULL;
- if (!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self())
- xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
void simcall_HANDLER_process_killall(smx_simcall_t simcall, int reset_pid) {
smx_process_t simcall_HANDLER_process_restart(smx_simcall_t simcall, smx_process_t process) {
return SIMIX_process_restart(process, simcall->issuer);
}
-/**
- * \brief Restart a process.
- * Restart a process, starting it again from the beginning.
- */
+/** @brief Restart a process, starting it again from the beginning. */
smx_process_t SIMIX_process_restart(smx_process_t process, smx_process_t issuer) {
XBT_DEBUG("Restarting process %s on %s", process->name, sg_host_name(process->smx_host));
//retrieve the arguments of the old process
- //FIXME: Factorise this with SIMIX_host_add_auto_restart_process ?
+ //FIXME: Factorize this with SIMIX_host_add_auto_restart_process ?
s_smx_process_arg_t arg;
arg.code = process->code;
arg.hostname = sg_host_name(process->smx_host);
- arg.kill_time = process->kill_time;
+ arg.kill_time = SIMIX_timer_get_date(process->kill_timer);
arg.argc = process->argc;
arg.data = process->data;
int i;
xbt_main_func_t code;
int argc;
char **argv;
- double kill_time;
-
+ smx_timer_t kill_timer;
} s_smx_process_t;
/* Copyright: Rolf Rabenseifner, 1997
* Computing Center University of Stuttgart
- * rabenseifner@rus.uni-stuttgart.de
+ * rabenseifner@rus.uni-stuttgart.de
*
- * The usage of this software is free,
+ * The usage of this software is free,
* but this header must not be removed.
- */
+ */
#include "colls_private.h"
#include <stdio.h>
MPI: /opt/ctl/mpt/1.1.0.3
datatype: MPI_DOUBLE
Ldb[][] = {{ 896,1728, 576, 736},{ 448,1280, 512, 512}}
- env: export MPI_BUFFER_MAX=4099
+ env: export MPI_BUFFER_MAX=4099
compiled with: cc -c -O3 -h restrict=f
old = binary tree protocol of the vendor
MPIM_UNSIGNED, MPIM_UNSIGNED_LONG, MPIM_FLOAT,
MPIM_DOUBLE, MPIM_BYTE} MPIM_Datatype;
-typedef enum {MPIM_MAX, MPIM_MIN, MPIM_SUM, MPIM_PROD,
- MPIM_LAND, MPIM_BAND, MPIM_LOR, MPIM_BOR,
+typedef enum {MPIM_MAX, MPIM_MIN, MPIM_SUM, MPIM_PROD,
+ MPIM_LAND, MPIM_BAND, MPIM_LOR, MPIM_BOR,
MPIM_LXOR, MPIM_BXOR} MPIM_Op;
#define MPI_I_DO_OP_C_INTEGER(MPI_I_do_op_TYPE,TYPE) \
static void MPI_I_do_op_TYPE(TYPE* b1,TYPE* b2,TYPE* rslt, int cnt,MPIM_Op op)\
MPI_Status status;
size_t scrlng;
int new_prot;
- MPIM_Datatype datatype = MPIM_INT; MPIM_Op op = MPIM_MAX;
-
+ MPIM_Datatype datatype = MPIM_INT; MPIM_Op op = MPIM_MAX;
+
if (mpi_datatype==MPI_SHORT ) datatype=MPIM_SHORT;
else if(mpi_datatype==MPI_INT ) datatype=MPIM_INT;
else if(mpi_datatype==MPI_LONG ) datatype=MPIM_LONG;
else if(mpi_datatype==MPI_FLOAT ) datatype=MPIM_FLOAT;
else if(mpi_datatype==MPI_DOUBLE ) datatype=MPIM_DOUBLE;
else if(mpi_datatype==MPI_BYTE ) datatype=MPIM_BYTE;
-
+
if (mpi_op==MPI_MAX ) op=MPIM_MAX;
else if(mpi_op==MPI_MIN ) op=MPIM_MIN;
else if(mpi_op==MPI_SUM ) op=MPIM_SUM;
new_prot = 0;
MPI_Comm_size(comm, &size);
if (size > 1) /*otherwise no balancing_protocol*/
- { register int ss;
+ { int ss;
if (size==2) ss=0;
else if (size==3) ss=1;
- else { register int s = size; while (!(s & 1)) s = s >> 1;
+ else { int s = size; while (!(s & 1)) s = s >> 1;
if (s==1) /* size == power of 2 */ ss = 2;
else /* size != power of 2 */ ss = 3; }
switch(op) {
extern double smpi_cpu_threshold;
extern double smpi_running_power;
extern int smpi_privatize_global_variables;
-extern char* start_data_exe; //start of the data+bss segment of the executable
-extern int size_data_exe; //size of the data+bss segment of the executable
+extern char* smpi_start_data_exe; //start of the data+bss segment of the executable
+extern int smpi_size_data_exe; //size of the data+bss segment of the executable
void smpi_switch_data_segment(int dest);
typedef struct s_smpi_privatisation_region {
void* address;
int file_descriptor;
-} *smpi_privatisation_region_t;
+} s_smpi_privatisation_region_t, *smpi_privatisation_region_t;
extern smpi_privatisation_region_t smpi_privatisation_regions;
-
extern int smpi_loaded_page;
+extern int smpi_universe_size;
int SIMIX_process_get_PID(smx_process_t self);
#include "private.h"
#include "xbt/virtu.h"
#include "mc/mc.h"
+#include "mc/mc_replay.h"
#include "xbt/replay.h"
#include <errno.h>
#include "simix/smx_private.h"
oldbuf = request->buf;
if (!smpi_process_get_replaying() && oldbuf && request->size!=0){
if((smpi_privatize_global_variables)
- && ((char*)request->buf >= start_data_exe)
- && ((char*)request->buf < start_data_exe + size_data_exe )){
+ && ((char*) request->buf >= smpi_start_data_exe)
+ && ((char*)request->buf < smpi_start_data_exe + smpi_size_data_exe )){
XBT_DEBUG("Privatization : We are sending from a zone inside global memory. Switch data segment ");
- smpi_switch_data_segment(request->src);
- }
+ smpi_switch_data_segment(request->src);
+ }
buf = xbt_malloc(request->size);
memcpy(buf,oldbuf,request->size);
XBT_DEBUG("buf %p copied into %p",oldbuf,buf);
if((req->flags & ACCUMULATE) || (datatype->has_subtype == 1)){
if (!smpi_process_get_replaying()){
if( smpi_privatize_global_variables
- && ((char*)req->old_buf >= start_data_exe)
- && ((char*)req->old_buf < start_data_exe + size_data_exe )
+ && ((char*)req->old_buf >= smpi_start_data_exe)
+ && ((char*)req->old_buf < smpi_start_data_exe + smpi_size_data_exe )
){
XBT_VERB("Privatization : We are unserializing to a zone in global memory - Switch data segment ");
smpi_switch_data_segment(smpi_process_index());
#include "surf/surf.h"
#include "simgrid/sg_config.h"
#include "simgrid/modelchecker.h"
+#include "mc/mc_replay.h"
#ifndef WIN32
#include <sys/mman.h>
double smpi_running_power;
int smpi_loaded_page = -1;
-char* start_data_exe = NULL;
-int size_data_exe = 0;
+char* smpi_start_data_exe = NULL;
+int smpi_size_data_exe = 0;
int smpi_privatize_global_variables;
double smpi_total_benched_time = 0;
-
-
smpi_privatisation_region_t smpi_privatisation_regions;
typedef struct {
*/
void smpi_really_switch_data_segment(int dest) {
- if(size_data_exe == 0)//no need to switch
+ if(smpi_size_data_exe == 0)//no need to switch
return;
#ifdef HAVE_MMAP
int i;
if(smpi_loaded_page==-1){//initial switch, do the copy from the real page here
for (i=0; i< SIMIX_process_count(); i++){
- memcpy(smpi_privatisation_regions[i].address,TOPAGE(start_data_exe),size_data_exe);
+ memcpy(smpi_privatisation_regions[i].address,
+ TOPAGE(smpi_start_data_exe), smpi_size_data_exe);
}
}
+ // 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);
- if (tmp != TOPAGE(start_data_exe))
+ void* tmp = mmap (TOPAGE(smpi_start_data_exe), smpi_size_data_exe,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
+ if (tmp != TOPAGE(smpi_start_data_exe))
xbt_die("Couldn't map the new region");
- smpi_loaded_page=dest;
+ smpi_loaded_page = dest;
#endif
}
if(i>=6){
if(strcmp(lfields[1], ".data") == 0){
size_data_binary = strtoul(lfields[2], NULL, 16);
- start_data_exe = (char*) strtoul(lfields[4], NULL, 16);
+ smpi_start_data_exe = (char*) strtoul(lfields[4], NULL, 16);
found++;
}else if(strcmp(lfields[1], ".bss") == 0){
//the beginning of bss is not exactly the end of data if not aligned, grow bss reported size accordingly
//TODO : check if this is OK, as some segments may be inserted between them..
- size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (start_data_exe + size_data_binary))
+ size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (smpi_start_data_exe + size_data_binary))
+ strtoul(lfields[2], NULL, 16);
found++;
}
}
- size_data_exe =(unsigned long)start_data_exe - (unsigned long)TOPAGE(start_data_exe)+ size_data_binary+size_bss_binary;
+ smpi_size_data_exe = (unsigned long) smpi_start_data_exe
+ - (unsigned long) TOPAGE(smpi_start_data_exe)
+ + size_data_binary+size_bss_binary;
xbt_free(command);
xbt_free(line);
pclose(fp);
unsigned int i = 0;
smpi_get_executable_global_size();
- XBT_DEBUG ("bss+data segment found : size %d starting at %p",size_data_exe, start_data_exe );
+ XBT_DEBUG ("bss+data segment found : size %d starting at %p",
+ smpi_size_data_exe, smpi_start_data_exe );
- if(size_data_exe == 0){//no need to switch
+ if (smpi_size_data_exe == 0){//no need to switch
smpi_privatize_global_variables=0;
return;
}
if (status)
xbt_die("Impossible to unlink temporary file for memory mapping");
- status = ftruncate(file_descriptor, size_data_exe);
+ status = ftruncate(file_descriptor, smpi_size_data_exe);
if(status)
xbt_die("Impossible to set the size of the temporary file for memory mapping");
/* Ask for a free region */
- address = mmap (NULL, size_data_exe, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0);
+ address = mmap (NULL, smpi_size_data_exe, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0);
if (address == MAP_FAILED)
xbt_die("Couldn't find a free region for memory mapping");
//initialize the values
- memcpy(address,TOPAGE(start_data_exe),size_data_exe);
+ memcpy(address, TOPAGE(smpi_start_data_exe), smpi_size_data_exe);
//store the address of the mapping for further switches
smpi_privatisation_regions[i].file_descriptor = file_descriptor;
}
void smpi_destroy_global_memory_segments(){
- if(size_data_exe == 0)//no need to switch
+ if (smpi_size_data_exe == 0)//no need to switch
return;
#ifdef HAVE_MMAP
int i;
for (i=0; i< smpi_process_count(); i++){
- if(munmap(smpi_privatisation_regions[i].address,size_data_exe) < 0) {
+ if(munmap(smpi_privatisation_regions[i].address, smpi_size_data_exe) < 0) {
XBT_WARN("Unmapping of fd %d failed: %s",
smpi_privatisation_regions[i].file_descriptor, strerror(errno));
}
"Logging specific to SMPI (comm)");
xbt_dict_t smpi_comm_keyvals = NULL;
-int comm_keyval_id=MPI_TAG_UB+1;//avoid collisions
+int comm_keyval_id = 0;//avoid collisions
/* Support for cartesian topology was added, but there are 2 other types of
* topology, graph et dist graph. In order to support them, we have to add a
xbt_free(elem);
return MPI_SUCCESS;
}
-
#include "surf/surf.h"
#include "simix/smx_private.h"
#include "simgrid/sg_config.h"
+#include "mc/mc_replay.h"
#include <float.h> /* DBL_MAX */
#include <stdint.h>
static smpi_process_data_t *process_data = NULL;
int process_count = 0;
+int smpi_universe_size = 0;
int* index_to_process_data = NULL;
extern double smpi_total_benched_time;
xbt_os_timer_t global_timer;
MPI_Comm MPI_COMM_WORLD = MPI_COMM_UNINITIALIZED;
-int MPI_UNIVERSE_SIZE;
MPI_Errhandler *MPI_ERRORS_RETURN = NULL;
MPI_Errhandler *MPI_ERRORS_ARE_FATAL = NULL;
void* tmpbuff=buff;
if((smpi_privatize_global_variables)
- && ((char*)buff >= start_data_exe)
- && ((char*)buff < start_data_exe + size_data_exe )
+ && ((char*)buff >= smpi_start_data_exe)
+ && ((char*)buff < smpi_start_data_exe + smpi_size_data_exe )
){
XBT_DEBUG("Privatization : We are copying from a zone inside global memory... Saving data to temp buffer !");
smpi_switch_data_segment(((smpi_process_data_t)SIMIX_process_get_data(comm->comm.src_proc))->index);
if((smpi_privatize_global_variables)
- && ((char*)comm->comm.dst_buff >= start_data_exe)
- && ((char*)comm->comm.dst_buff < start_data_exe + size_data_exe )
+ && ((char*)comm->comm.dst_buff >= smpi_start_data_exe)
+ && ((char*)comm->comm.dst_buff < smpi_start_data_exe + smpi_size_data_exe )
){
XBT_DEBUG("Privatization : We are copying to a zone inside global memory - Switch data segment");
smpi_switch_data_segment(((smpi_process_data_t)SIMIX_process_get_data(comm->comm.dst_proc))->index);
process_count = SIMIX_process_count();
smpirun=1;
}
+ smpi_universe_size = process_count;
process_data = xbt_new0(smpi_process_data_t, process_count);
for (i = 0; i < process_count; i++) {
process_data[i] = xbt_new(s_smpi_process_data_t, 1);
if(smpirun){
group = smpi_group_new(process_count);
MPI_COMM_WORLD = smpi_comm_new(group, NULL);
+ MPI_Attr_put(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, (void *)(MPI_Aint)process_count);
xbt_bar_t bar=xbt_barrier_init(process_count);
- MPI_UNIVERSE_SIZE = smpi_comm_size(MPI_COMM_WORLD);
for (i = 0; i < process_count; i++) {
smpi_group_set_mapping(group, i, i);
process_data[i]->finalization_barrier = bar;
fflush(stderr);
if (MC_is_active()) {
- MC_do_the_modelcheck_for_real();
+ MC_run();
} else {
SIMIX_run();
}
int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
+ static int one = 1;
+ static int zero = 0;
+ static int tag_ub = 1000000;
+ static int last_used_code = MPI_ERR_LASTCODE;
+
if (comm==MPI_COMM_NULL){
- *flag=0;
+ *flag = 0;
return MPI_ERR_COMM;
- } else if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO
- ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
- ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE){
+ }
+
+ switch (keyval) {
+ case MPI_HOST:
+ case MPI_IO:
+ case MPI_APPNUM:
+ *flag = 1;
+ *(int**)attr_value = &zero;
+ return MPI_SUCCESS;
+
+ case MPI_UNIVERSE_SIZE:
+ *flag = 1;
+ *(int**)attr_value = &smpi_universe_size;
+ return MPI_SUCCESS;
+
+ case MPI_LASTUSEDCODE:
+ *flag = 1;
+ *(int**)attr_value = &last_used_code;
+ return MPI_SUCCESS;
+
+ case MPI_TAG_UB:
*flag=1;
- //FIXME : not ideal and leaky, but should not be called too much
- int* res = xbt_new(int, 1);
- *res=keyval;
- *(int**)attr_value=res;
+ *(int**)attr_value = &tag_ub;
+ return MPI_SUCCESS;
+
+ case MPI_WTIME_IS_GLOBAL:
+ *flag = 1;
+ *(int**)attr_value = &one;
return MPI_SUCCESS;
- } else
- return smpi_comm_attr_get(comm, keyval, attr_value, flag);
+
+ default:
+ return smpi_comm_attr_get(comm, keyval, attr_value, flag);
+ }
}
int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
int PMPI_Win_unlock(int rank, MPI_Win win){
NOT_YET_IMPLEMENTED
}
-
xbt_die("could not find dst node active comms !");
// act_dst->rate=rate;
- ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair<IBNode*,IBNode*>(act_src, act_dst);
+ ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair(act_src, act_dst);
//post the action in the second dist, to retrieve in the other callback
XBT_DEBUG("IB callback - action %p init", action);
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
+typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
- * existing scanners that call yyless() from OUTSIDE surf_parse_lex.
+ * existing scanners that call yyless() from OUTSIDE surf_parse_lex.
* One obvious solution it to make yy_act a global. I tried that, and saw
* a 5% performance hit in a non-surf_parse_lineno scanner, because yy_act is
* normally declared as a register variable-- so it is not worth it.
if ( *p == '\n' )\
--surf_parse_lineno;\
}while(0)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[596] =
{ 0,
-0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
- 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
- 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
- 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, };
static yy_state_type yy_last_accepting_state;
* FleXML is Copyright (C) 1999-2005 Kristoffer Rose. All rights reserved.
* FleXML is Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
* (1.9.6).
- *
+ *
* There are two, intertwined parts to this program, part A and part B.
*
* Part A
* ------
- *
- * Some parts, here collectively called "Part A", are found in the
+ *
+ * Some parts, here collectively called "Part A", are found in the
* FleXML package. They are Copyright (C) 1999-2005 Kristoffer Rose
* and Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
*
* Notice that these are explicit rights granted to you for files
* generated by the FleXML system. For your rights in connection with
* the FleXML system itself please consult the GNU General Public License.
- *
+ *
* Part B
* ------
- *
- * The other parts, here collectively called "Part B", and which came
- * from the DTD used by FleXML to generate this program, can be
+ *
+ * The other parts, here collectively called "Part B", and which came
+ * from the DTD used by FleXML to generate this program, can be
* distributed (or not, as the case may be) under the terms of whoever
- * wrote them, provided these terms respect and obey the two conditions
+ * wrote them, provided these terms respect and obey the two conditions
* above under the heading "Part A".
*
* The author of and contributors to FleXML specifically disclaim
- * any copyright interest in "Part B", unless "Part B" was written
+ * any copyright interest in "Part B", unless "Part B" was written
* by the author of or contributors to FleXML.
- *
+ *
*/
/* Version strings. */
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
-
+
#if defined(_XBT_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__TOS_WIN__)
# ifndef __STRICT_ANSI__
# include <io.h>
#else
# include <unistd.h>
#endif
-
+
#ifndef FLEXML_INDEXSTACKSIZE
#define FLEXML_INDEXSTACKSIZE 1000
#endif
{
ck_ilimit();
indexstack[inext++] = p;
- indexstack[inext++] = bnext;
+ indexstack[inext++] = bnext;
}
static int popbuffer(void)
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = NULL;
-
+
static void yy_push_state (int new_state );
-
+
static void yy_pop_state (void );
-
+
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
if ( !(yy_init) )
{
(yy_init) = 1;
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
yy_size_t yyl;
for ( yyl = 0; yyl < surf_parse_leng; ++yyl )
if ( surf_parse_text[yyl] == '\n' )
-
+
surf_parse_lineno++;
;
}
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
-SET(DOCTYPE);
+SET(DOCTYPE);
YY_BREAK
case 12:
/* rule 12 can match eol */
*/
static int yy_get_next_buffer (void)
{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
static yy_state_type yy_get_previous_state (void)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
yy_current_state = (yy_start);
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
{
int c;
-
+
*(yy_c_buf_p) = (yy_hold_char);
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
(yy_hold_char) = *++(yy_c_buf_p);
if ( c == '\n' )
-
+
surf_parse_lineno++;
;
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
- *
+ *
* @note This function does not reset the start condition to @c INITIAL .
*/
void surf_parse_restart (FILE * input_file )
{
-
+
if ( ! YY_CURRENT_BUFFER ){
surf_parse_ensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
- *
+ *
*/
void surf_parse__switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
-
+
/* TODO. We should be able to replace this entire function body
* with
* surf_parse_pop_buffer_state();
/** Allocate and initialize an input buffer state.
* @param file A readable stream.
* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- *
+ *
* @return the allocated buffer state.
*/
YY_BUFFER_STATE surf_parse__create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) surf_parse_alloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in surf_parse__create_buffer()" );
/** Destroy the buffer.
* @param b a buffer created with surf_parse__create_buffer()
- *
+ *
*/
void surf_parse__delete_buffer (YY_BUFFER_STATE b )
{
-
+
if ( ! b )
return;
{
int oerrno = errno;
-
+
surf_parse__flush_buffer(b );
b->yy_input_file = file;
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- *
+ *
*/
void surf_parse__flush_buffer (YY_BUFFER_STATE b )
{
* the current state. This function will allocate the stack
* if necessary.
* @param new_buffer The new state.
- *
+ *
*/
void surf_parse_push_buffer_state (YY_BUFFER_STATE new_buffer )
{
/** Removes and deletes the top of the stack, if present.
* The next element becomes the new top.
- *
+ *
*/
void surf_parse_pop_buffer_state (void)
{
static void surf_parse_ensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
-
+
if (!(yy_buffer_stack)) {
/* First allocation is just for 2 elements, since we don't know if this
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in surf_parse_ensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
/** Setup the input buffer state to scan directly from a user-specified character buffer.
* @param base the character buffer
* @param size the size in bytes of the character buffer
- *
- * @return the newly allocated buffer state object.
+ *
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE surf_parse__scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/** Setup the input buffer state to scan a string. The next call to surf_parse_lex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
- *
+ *
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* surf_parse__scan_bytes() instead.
*/
YY_BUFFER_STATE surf_parse__scan_string (yyconst char * yystr )
{
-
+
return surf_parse__scan_bytes(yystr,strlen(yystr) );
}
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- *
+ *
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE surf_parse__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
char *buf;
yy_size_t n;
yy_size_t i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) surf_parse_alloc(n );
/* Accessor methods (get/set functions) to struct members. */
/** Get the current line number.
- *
+ *
*/
int surf_parse_get_lineno (void)
{
-
+
return surf_parse_lineno;
}
/** Get the input stream.
- *
+ *
*/
FILE *surf_parse_get_in (void)
{
}
/** Get the output stream.
- *
+ *
*/
FILE *surf_parse_get_out (void)
{
}
/** Get the length of the current token.
- *
+ *
*/
yy_size_t surf_parse_get_leng (void)
{
}
/** Get the current token.
- *
+ *
*/
char *surf_parse_get_text (void)
/** Set the current line number.
* @param line_number
- *
+ *
*/
void surf_parse_set_lineno (int line_number )
{
-
+
surf_parse_lineno = line_number;
}
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
- *
+ *
* @see surf_parse__switch_to_buffer
*/
void surf_parse_set_in (FILE * in_str )
/* We do not touch surf_parse_lineno unless the option is enabled. */
surf_parse_lineno = 1;
-
+
(yy_buffer_stack) = 0;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
/* surf_parse_lex_destroy is for both reentrant and non-reentrant scanners. */
int surf_parse_lex_destroy (void)
{
-
+
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
surf_parse__delete_buffer(YY_CURRENT_BUFFER );
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
m_lastUpdate = now;
m_lastValue = lmm_variable_getvalue(getVariable());
}
-
#include "xbt/automaton.h"
#include <stdio.h> /* printf */
+struct xbt_automaton_propositional_symbol{
+ char* pred;
+ /** Callback used to evaluate the value of the symbol */
+ int (*callback)(void*);
+ /** Additional data for the callback.
+ Alternatively it can be used as a pointer to the data. */
+ void* data;
+ //** Optional callback used to free the data field */
+ void (*free_function)(void*);
+};
+
xbt_automaton_t xbt_automaton_new(){
xbt_automaton_t automaton = NULL;
automaton = xbt_new0(struct xbt_automaton, 1);
return a->current_state;
}
-xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct){
+static int call_simple_function(void* function)
+{
+ return ((int (*)(void)) function)();
+}
+
+xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void)){
xbt_automaton_propositional_symbol_t prop_symb = NULL;
prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
prop_symb->pred = strdup(id);
- prop_symb->function = fct;
+ prop_symb->callback = call_simple_function;
+ prop_symb->data = fct;
+ prop_symb->free_function = NULL;
xbt_dynar_push(a->propositional_symbols, &prop_symb);
return prop_symb;
}
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value)
+{
+ xbt_automaton_propositional_symbol_t prop_symb = NULL;
+ prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+ prop_symb->pred = strdup(id);
+ prop_symb->callback = NULL;
+ prop_symb->data = value;
+ prop_symb->free_function = NULL;
+ xbt_dynar_push(a->propositional_symbols, &prop_symb);
+ return prop_symb;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+ xbt_automaton_t a, const char* id,
+ xbt_automaton_propositional_symbol_callback_type callback,
+ void* data, xbt_automaton_propositional_symbol_free_function_type free_function)
+{
+ xbt_automaton_propositional_symbol_t prop_symb = NULL;
+ prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+ prop_symb->pred = strdup(id);
+ prop_symb->callback = callback;
+ prop_symb->data = data;
+ prop_symb->free_function = free_function;
+ xbt_dynar_push(a->propositional_symbols, &prop_symb);
+ return prop_symb;
+}
+
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol)
+{
+ if (symbol->callback)
+ return (symbol->callback)(symbol->data);
+ else
+ return *(int*) symbol->data;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->callback;
+}
+
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->data;
+}
+
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol)
+{
+ return symbol->pred;
+}
+
int xbt_automaton_state_compare(xbt_automaton_state_t s1, xbt_automaton_state_t s2){
/* single id for each state, id and type sufficient for comparison*/
}
void xbt_automaton_propositional_symbol_free_voidp(void *ps){
- xbt_automaton_propositional_symbol_free((xbt_automaton_propositional_symbol_t) * (void **) ps);
+ xbt_automaton_propositional_symbol_t symbol = (xbt_automaton_propositional_symbol_t) * (void **) ps;
+ if (symbol->free_function)
+ symbol->free_function(symbol->data);
+ xbt_free(symbol->pred);
+ xbt_automaton_propositional_symbol_free(symbol);
}
void xbt_automaton_free(xbt_automaton_t a){
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
+typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
#define YY_LESS_LINENO(n)
#define YY_LINENO_REWIND_TO(ptr)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
#include <stdio.h>
#include "parserPromela.tab.hacc"
-
+
extern YYSTYPE yylval;
-
+
#line 538 "automaton_lexer.yy.c"
#define INITIAL 0
#endif
static void yyunput (int c,char *buf_ptr );
-
+
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int );
#endif
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
if ( !(yy_init) )
{
(yy_init) = 1;
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
case 19:
YY_RULE_SETUP
#line 59 "parserPromela.lex"
-{ sscanf(xbt_automaton_parser_text,"%lf",&yylval.real);
+{ sscanf(xbt_automaton_parser_text,"%lf",&yylval.real);
return (LITT_REEL); }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 62 "parserPromela.lex"
-{ sscanf(xbt_automaton_parser_text,"%d",&yylval.integer);
+{ sscanf(xbt_automaton_parser_text,"%d",&yylval.integer);
return (LITT_ENT); }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 65 "parserPromela.lex"
{ yylval.string=(char *)malloc(strlen(xbt_automaton_parser_text)+1);
- sscanf(xbt_automaton_parser_text,"%s",yylval.string);
+ sscanf(xbt_automaton_parser_text,"%s",yylval.string);
return (LITT_CHAINE); }
YY_BREAK
case 22:
*/
static int yy_get_next_buffer (void)
{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
static yy_state_type yy_get_previous_state (void)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
yy_current_state = (yy_start);
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
return yy_is_jam ? 0 : yy_current_state;
}
- static void yyunput (int c, register char * yy_bp )
+ static void yyunput (int c, char * yy_bp )
{
- register char *yy_cp;
-
+ char *yy_cp;
+
yy_cp = (yy_c_buf_p);
/* undo effects of setting up xbt_automaton_parser_text */
if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
- register yy_size_t number_to_move = (yy_n_chars) + 2;
- register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ yy_size_t number_to_move = (yy_n_chars) + 2;
+ char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
- register char *source =
+ char *source =
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
{
int c;
-
+
*(yy_c_buf_p) = (yy_hold_char);
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
- *
+ *
* @note This function does not reset the start condition to @c INITIAL .
*/
void xbt_automaton_parser_restart (FILE * input_file )
{
-
+
if ( ! YY_CURRENT_BUFFER ){
xbt_automaton_parser_ensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
- *
+ *
*/
void xbt_automaton_parser__switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
-
+
/* TODO. We should be able to replace this entire function body
* with
* xbt_automaton_parser_pop_buffer_state();
/** Allocate and initialize an input buffer state.
* @param file A readable stream.
* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- *
+ *
* @return the allocated buffer state.
*/
YY_BUFFER_STATE xbt_automaton_parser__create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) xbt_automaton_parser_alloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in xbt_automaton_parser__create_buffer()" );
/** Destroy the buffer.
* @param b a buffer created with xbt_automaton_parser__create_buffer()
- *
+ *
*/
void xbt_automaton_parser__delete_buffer (YY_BUFFER_STATE b )
{
-
+
if ( ! b )
return;
{
int oerrno = errno;
-
+
xbt_automaton_parser__flush_buffer(b );
b->yy_input_file = file;
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- *
+ *
*/
void xbt_automaton_parser__flush_buffer (YY_BUFFER_STATE b )
{
* the current state. This function will allocate the stack
* if necessary.
* @param new_buffer The new state.
- *
+ *
*/
void xbt_automaton_parser_push_buffer_state (YY_BUFFER_STATE new_buffer )
{
/** Removes and deletes the top of the stack, if present.
* The next element becomes the new top.
- *
+ *
*/
void xbt_automaton_parser_pop_buffer_state (void)
{
static void xbt_automaton_parser_ensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
-
+
if (!(yy_buffer_stack)) {
/* First allocation is just for 2 elements, since we don't know if this
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in xbt_automaton_parser_ensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
/** Setup the input buffer state to scan directly from a user-specified character buffer.
* @param base the character buffer
* @param size the size in bytes of the character buffer
- *
- * @return the newly allocated buffer state object.
+ *
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE xbt_automaton_parser__scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/** Setup the input buffer state to scan a string. The next call to xbt_automaton_parser_lex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
- *
+ *
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* xbt_automaton_parser__scan_bytes() instead.
*/
YY_BUFFER_STATE xbt_automaton_parser__scan_string (yyconst char * yystr )
{
-
+
return xbt_automaton_parser__scan_bytes(yystr,strlen(yystr) );
}
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- *
+ *
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE xbt_automaton_parser__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
char *buf;
yy_size_t n;
yy_size_t i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) xbt_automaton_parser_alloc(n );
/* Accessor methods (get/set functions) to struct members. */
/** Get the current line number.
- *
+ *
*/
int xbt_automaton_parser_get_lineno (void)
{
-
+
return xbt_automaton_parser_lineno;
}
/** Get the input stream.
- *
+ *
*/
FILE *xbt_automaton_parser_get_in (void)
{
}
/** Get the output stream.
- *
+ *
*/
FILE *xbt_automaton_parser_get_out (void)
{
}
/** Get the length of the current token.
- *
+ *
*/
yy_size_t xbt_automaton_parser_get_leng (void)
{
}
/** Get the current token.
- *
+ *
*/
char *xbt_automaton_parser_get_text (void)
/** Set the current line number.
* @param line_number
- *
+ *
*/
void xbt_automaton_parser_set_lineno (int line_number )
{
-
+
xbt_automaton_parser_lineno = line_number;
}
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
- *
+ *
* @see xbt_automaton_parser__switch_to_buffer
*/
void xbt_automaton_parser_set_in (FILE * in_str )
/* xbt_automaton_parser_lex_destroy is for both reentrant and non-reentrant scanners. */
int xbt_automaton_parser_lex_destroy (void)
{
-
+
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
xbt_automaton_parser__delete_buffer(YY_CURRENT_BUFFER );
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
static void xbt_dict_rehash(xbt_dict_t dict)
{
const int oldsize = dict->table_size + 1;
- register int newsize = oldsize * 2;
- register int i;
- register xbt_dictelm_t *currcell;
- register xbt_dictelm_t *twincell;
- register xbt_dictelm_t bucklet;
- register xbt_dictelm_t *pprev;
+ int newsize = oldsize * 2;
+ int i;
+ xbt_dictelm_t *currcell;
+ xbt_dictelm_t *twincell;
+ xbt_dictelm_t bucklet;
+ xbt_dictelm_t *pprev;
currcell =
(xbt_dictelm_t *) xbt_realloc((char *) dict->table,
xbt_dict_free(&head);
}
+XBT_TEST_UNIT("ext", test_dict_int, "Test dictionnary with int keys")
+{
+ xbt_dict_t dict = xbt_dict_new();
+ int count = 500;
+
+ xbt_test_add("Insert elements");
+ int i;
+ for (i = 0; i < count; ++i)
+ xbt_dict_set_ext(dict, (char*) &i, sizeof(i), (void*) (intptr_t) i, NULL);
+ xbt_test_assert(xbt_dict_size(dict) == count,
+ "Bad number of elements in the dictionnary");
+
+ xbt_test_add("Check elements");
+ for (i = 0; i < count; ++i) {
+ int res = (int) (intptr_t) xbt_dict_get_ext(dict, (char*) &i, sizeof(i));
+ xbt_test_assert(xbt_dict_size(dict) == count,
+ "Unexpected value at index %i, expected %i but was %i", i, i, res);
+ }
+
+ xbt_test_add("Free the array");
+ xbt_dict_free(&dict);
+}
+
#endif /* SIMGRID_TEST */
xbt_test_log("Pop %d, length=%lu", cpt, xbt_dynar_length(d));
}
+ int* pi;
+ xbt_dynar_foreach_ptr(d, cursor, pi) {
+ *pi = 0;
+ }
+ xbt_dynar_foreach(d, cursor, i) {
+ xbt_test_assert(i == 0, "The value is not the same as the expected one.");
+ }
+ xbt_dynar_foreach_ptr(d, cursor, pi) {
+ *pi = 1;
+ }
+ xbt_dynar_foreach(d, cursor, i) {
+ xbt_test_assert(i == 1, "The value is not the same as the expected one.");
+ }
+
/* 5. Free the resources */
xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
#include "xbt_modinter.h" /* backtrace initialization headers */
#include "xbt/ex_interface.h"
+#include "simgrid/sg_config.h" /* Configuration mechanism of SimGrid */
+
#undef HAVE_BACKTRACE
#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
int i;
fprintf(stderr, "\n");
- for (i = 0; i < e->used; i++)
- fprintf(stderr, "%s\n", e->bt_strings[i]);
+ for (i = 0; i < e->used; i++) {
+ if (sg_cfg_get_boolean("exception/cutpath")) {
+ char* p = e->bt_strings[i];
+ xbt_str_rtrim(p, ":0123456789");
+ char* filename = strrchr(p, '/')+1;
+ char* end_of_message = strrchr(p, ' ');
+
+ int length = strlen(p)-strlen(end_of_message);
+ char* dest = malloc(length);
+
+ memcpy(dest, &p[0], length);
+ dest[length] = 0;
+
+ fprintf(stderr, "%s %s\n", dest, filename);
+
+ free(dest);
+ }
+ else {
+ fprintf(stderr, "%s\n", e->bt_strings[i]);
+ }
+ }
} else
#endif
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
+typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
- * existing scanners that call yyless() from OUTSIDE xbt_graph_parse_lex.
+ * existing scanners that call yyless() from OUTSIDE xbt_graph_parse_lex.
* One obvious solution it to make yy_act a global. I tried that, and saw
* a 5% performance hit in a non-xbt_graph_parse_lineno scanner, because yy_act is
* normally declared as a register variable-- so it is not worth it.
if ( *p == '\n' )\
--xbt_graph_parse_lineno;\
}while(0)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[93] =
{ 0,
-0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, };
static yy_state_type yy_last_accepting_state;
* FleXML is Copyright (C) 1999-2005 Kristoffer Rose. All rights reserved.
* FleXML is Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
* (1.9.6).
- *
+ *
* There are two, intertwined parts to this program, part A and part B.
*
* Part A
* ------
- *
- * Some parts, here collectively called "Part A", are found in the
+ *
+ * Some parts, here collectively called "Part A", are found in the
* FleXML package. They are Copyright (C) 1999-2005 Kristoffer Rose
* and Copyright (C) 2003-2013 Martin Quinson. All rights reserved.
*
* Notice that these are explicit rights granted to you for files
* generated by the FleXML system. For your rights in connection with
* the FleXML system itself please consult the GNU General Public License.
- *
+ *
* Part B
* ------
- *
- * The other parts, here collectively called "Part B", and which came
- * from the DTD used by FleXML to generate this program, can be
+ *
+ * The other parts, here collectively called "Part B", and which came
+ * from the DTD used by FleXML to generate this program, can be
* distributed (or not, as the case may be) under the terms of whoever
- * wrote them, provided these terms respect and obey the two conditions
+ * wrote them, provided these terms respect and obey the two conditions
* above under the heading "Part A".
*
* The author of and contributors to FleXML specifically disclaim
- * any copyright interest in "Part B", unless "Part B" was written
+ * any copyright interest in "Part B", unless "Part B" was written
* by the author of or contributors to FleXML.
- *
+ *
*/
/* Version strings. */
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
-
+
#if defined(_XBT_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__TOS_WIN__)
# ifndef __STRICT_ANSI__
# include <io.h>
#else
# include <unistd.h>
#endif
-
+
#ifndef FLEXML_INDEXSTACKSIZE
#define FLEXML_INDEXSTACKSIZE 1000
#endif
{
ck_ilimit();
indexstack[inext++] = p;
- indexstack[inext++] = bnext;
+ indexstack[inext++] = bnext;
}
static int popbuffer(void)
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = NULL;
-
+
static void yy_push_state (int new_state );
-
+
static void yy_pop_state (void );
-
+
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
if ( !(yy_init) )
{
(yy_init) = 1;
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
yy_size_t yyl;
for ( yyl = 0; yyl < xbt_graph_parse_leng; ++yyl )
if ( xbt_graph_parse_text[yyl] == '\n' )
-
+
xbt_graph_parse_lineno++;
;
}
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
-SET(DOCTYPE);
+SET(DOCTYPE);
YY_BREAK
case 12:
/* rule 12 can match eol */
*/
static int yy_get_next_buffer (void)
{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
static yy_state_type yy_get_previous_state (void)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
yy_current_state = (yy_start);
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
{
int c;
-
+
*(yy_c_buf_p) = (yy_hold_char);
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
(yy_hold_char) = *++(yy_c_buf_p);
if ( c == '\n' )
-
+
xbt_graph_parse_lineno++;
;
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
- *
+ *
* @note This function does not reset the start condition to @c INITIAL .
*/
void xbt_graph_parse_restart (FILE * input_file )
{
-
+
if ( ! YY_CURRENT_BUFFER ){
xbt_graph_parse_ensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
- *
+ *
*/
void xbt_graph_parse__switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
-
+
/* TODO. We should be able to replace this entire function body
* with
* xbt_graph_parse_pop_buffer_state();
/** Allocate and initialize an input buffer state.
* @param file A readable stream.
* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- *
+ *
* @return the allocated buffer state.
*/
YY_BUFFER_STATE xbt_graph_parse__create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) xbt_graph_parse_alloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in xbt_graph_parse__create_buffer()" );
/** Destroy the buffer.
* @param b a buffer created with xbt_graph_parse__create_buffer()
- *
+ *
*/
void xbt_graph_parse__delete_buffer (YY_BUFFER_STATE b )
{
-
+
if ( ! b )
return;
{
int oerrno = errno;
-
+
xbt_graph_parse__flush_buffer(b );
b->yy_input_file = file;
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- *
+ *
*/
void xbt_graph_parse__flush_buffer (YY_BUFFER_STATE b )
{
* the current state. This function will allocate the stack
* if necessary.
* @param new_buffer The new state.
- *
+ *
*/
void xbt_graph_parse_push_buffer_state (YY_BUFFER_STATE new_buffer )
{
/** Removes and deletes the top of the stack, if present.
* The next element becomes the new top.
- *
+ *
*/
void xbt_graph_parse_pop_buffer_state (void)
{
static void xbt_graph_parse_ensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
-
+
if (!(yy_buffer_stack)) {
/* First allocation is just for 2 elements, since we don't know if this
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in xbt_graph_parse_ensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
/** Setup the input buffer state to scan directly from a user-specified character buffer.
* @param base the character buffer
* @param size the size in bytes of the character buffer
- *
- * @return the newly allocated buffer state object.
+ *
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE xbt_graph_parse__scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/** Setup the input buffer state to scan a string. The next call to xbt_graph_parse_lex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
- *
+ *
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* xbt_graph_parse__scan_bytes() instead.
*/
YY_BUFFER_STATE xbt_graph_parse__scan_string (yyconst char * yystr )
{
-
+
return xbt_graph_parse__scan_bytes(yystr,strlen(yystr) );
}
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- *
+ *
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE xbt_graph_parse__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
char *buf;
yy_size_t n;
yy_size_t i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) xbt_graph_parse_alloc(n );
/* Accessor methods (get/set functions) to struct members. */
/** Get the current line number.
- *
+ *
*/
int xbt_graph_parse_get_lineno (void)
{
-
+
return xbt_graph_parse_lineno;
}
/** Get the input stream.
- *
+ *
*/
FILE *xbt_graph_parse_get_in (void)
{
}
/** Get the output stream.
- *
+ *
*/
FILE *xbt_graph_parse_get_out (void)
{
}
/** Get the length of the current token.
- *
+ *
*/
yy_size_t xbt_graph_parse_get_leng (void)
{
}
/** Get the current token.
- *
+ *
*/
char *xbt_graph_parse_get_text (void)
/** Set the current line number.
* @param line_number
- *
+ *
*/
void xbt_graph_parse_set_lineno (int line_number )
{
-
+
xbt_graph_parse_lineno = line_number;
}
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
- *
+ *
* @see xbt_graph_parse__switch_to_buffer
*/
void xbt_graph_parse_set_in (FILE * in_str )
/* We do not touch xbt_graph_parse_lineno unless the option is enabled. */
xbt_graph_parse_lineno = 1;
-
+
(yy_buffer_stack) = 0;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
/* xbt_graph_parse_lex_destroy is for both reentrant and non-reentrant scanners. */
int xbt_graph_parse_lex_destroy (void)
{
-
+
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
xbt_graph_parse__delete_buffer(YY_CURRENT_BUFFER );
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
return;
}
-
/**
* @brief Extracts from the heap and returns the element with the smallest key.
* \param H the heap we're working on
return xbt_heap_pop(H);
}
+/** @brief Remove an arbitrary element from the heap
+ * @param H the heap we're working on
+ * @param content the object you want to add to the heap
+ * @param key the key associated to this object
+ */
+void xbt_heap_rm_elm(xbt_heap_t H, void *content, double key) {
+ int i=0;
+ while (i < H->count && (KEY(H, i) != key || CONTENT(H, i) != content))
+ i++;
+ if (i == H->count)
+ return;
+ xbt_heap_remove(H,i);
+}
/**
* @brief Updates an element of the heap with a new value.
XBT_LOG_CONNECT(mc_compare);
XBT_LOG_CONNECT(mc_diff);
XBT_LOG_CONNECT(mc_dwarf);
- XBT_LOG_CONNECT(mc_global);
XBT_LOG_CONNECT(mc_hash);
XBT_LOG_CONNECT(mc_ignore);
+ XBT_LOG_CONNECT(mcer_ignore);
XBT_LOG_CONNECT(mc_liveness);
XBT_LOG_CONNECT(mc_memory);
XBT_LOG_CONNECT(mc_memory_map);
XBT_LOG_CONNECT(mc_request);
XBT_LOG_CONNECT(mc_safety);
XBT_LOG_CONNECT(mc_visited);
+ XBT_LOG_CONNECT(mc_client);
+ XBT_LOG_CONNECT(mc_client_api);
+ XBT_LOG_CONNECT(mc_comm_pattern);
+ XBT_LOG_CONNECT(mc_process);
+ XBT_LOG_CONNECT(mc_protocol);
+ XBT_LOG_CONNECT(mc_server);
+ XBT_LOG_CONNECT(mc_state);
#endif
+ XBT_LOG_CONNECT(mc_global);
+ XBT_LOG_CONNECT(mc_config);
+ XBT_LOG_CONNECT(mc_record);
/* msg */
XBT_LOG_CONNECT(msg);
{
int type;
size_t block, frag_nb;
- register size_t i;
+ size_t i;
int it;
mmalloc_paranoia(mdp);
UNLOCK(mdp);
THROWF(system_error, 0, "Asked to free a fragment in a block that is already free. I'm puzzled.\n");
break;
-
+
case MMALLOC_TYPE_UNFRAGMENTED:
/* Get as many statistics as early as we can. */
mdp -> heapstats.chunks_used--;
mdp -> heapstats.bytes_free -= bytes;
} */
- /* Set the next search to begin at this block.
- This is probably important to the trick where realloc returns the block to
+ /* Set the next search to begin at this block.
+ This is probably important to the trick where realloc returns the block to
the system before reasking for the same block with a bigger size. */
mdp->heapindex = block;
break;
mdp->heapinfo[block].type = MMALLOC_TYPE_UNFRAGMENTED;
mdp->heapinfo[block].busy_block.size = 1;
mdp->heapinfo[block].busy_block.busy_size = 0;
-
+
/* Keep the statistics accurate. */
mdp -> heapstats.chunks_used++;
mdp -> heapstats.bytes_used += BLOCKSIZE;
mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
mdp -> heapstats.bytes_free -= BLOCKSIZE;
-
+
mfree((void *) mdp, (void *) ADDRESS(block));
} else if (mdp->heapinfo[block].busy_frag.nfree != 0) {
/* If some fragments of this block are free, you know what? I'm already happy. */
* under the terms of the license (GNU LGPL) which comes with this package. */
/* Redefine the classical malloc/free/realloc functions so that they fit well in the mmalloc framework */
+#define _GNU_SOURCE
+#include <stdlib.h>
+
+#include <dlfcn.h>
+
+#include "../../mc/mc_base.h"
#include "mmprivate.h"
#include "xbt_modinter.h"
#include "internal_config.h"
#include <math.h>
+#include "../mc/mc_protocol.h"
-//#define MM_LEGACY_VERBOSE 1 /* define this to see which version of malloc gets used */
+/* ***** Whether to use `mmalloc` of the undrlying malloc ***** */
+
+static int __malloc_use_mmalloc;
+
+int malloc_use_mmalloc(void)
+{
+ return __malloc_use_mmalloc;
+}
+
+/* ***** Current heap ***** */
/* The mmalloc() package can use a single implicit malloc descriptor
for mmalloc/mrealloc/mfree operations which do not supply an explicit
backwards compatibility with the non-mmap'd version. */
xbt_mheap_t __mmalloc_default_mdp = NULL;
-
-static xbt_mheap_t __mmalloc_current_heap = NULL; /* The heap we are currently using. */
+/* The heap we are currently using. */
+static xbt_mheap_t __mmalloc_current_heap = NULL;
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 <dlfcn.h>
-static void * (*real_malloc) (size_t) = NULL;
-static void * (*real_realloc) (void*,size_t) = NULL;
-static void * (*real_free) (void*) = NULL;
+/* ***** Temporary allocator
+ *
+ * This is used before we have found the real malloc implementation with dlsym.
+ */
-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;
-}
+#define BUFFER_SIZE 32
+static size_t fake_alloc_index;
+static uint64_t buffer[BUFFER_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.
+/* Fake implementations, they are used to fool dlsym:
+ * dlsym used calloc and falls back to some other mechanism
+ * if this fails.
*/
-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;
+static void* mm_fake_malloc(size_t n)
+{
+ // How many uint64_t do w need?
+ size_t count = n / sizeof(uint64_t);
+ if (n % sizeof(uint64_t))
+ count++;
+ // Check that we have enough availabel memory:
+ if (fake_alloc_index + count >= BUFFER_SIZE)
+ exit(127);
+ // Allocate it:
+ uint64_t* res = buffer + fake_alloc_index;
+ fake_alloc_index += count;
+ return res;
}
-void *malloc(size_t n)
+static void* mm_fake_calloc(size_t nmemb, size_t size)
{
- return malloc_or_calloc(n, 0);
+ // This is fresh .bss data, we don't need to clear it:
+ size_t n = nmemb * size;
+ return mm_fake_malloc(n);
}
-void *calloc(size_t nmemb, size_t size)
+static void* mm_fake_realloc(void *p, size_t s)
{
- return malloc_or_calloc(nmemb*size, 1);
+ return mm_fake_malloc(s);
}
-void *realloc(void *p, size_t s)
+static void mm_fake_free(void *p)
{
- 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);
- }
+/* 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);
- return ret;
-}
+/* Function pointers to the real/next implementations: */
+static mm_malloc_t mm_real_malloc;
+static mm_free_t mm_real_free;
+static mm_calloc_t mm_real_calloc;
+static mm_realloc_t mm_real_realloc;
-void free(void *p)
+static int mm_initializing;
+static int mm_initialized;
+
+/** Constructor functions used to initialize the malloc implementation
+ */
+static void __attribute__((constructor(101))) mm_legacy_constructor()
{
- if (p==NULL)
+ if (mm_initialized)
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);
- }
+ mm_initializing = 1;
+ __malloc_use_mmalloc = getenv(MC_ENV_VARIABLE) ? 1 : 0;
+ if (__malloc_use_mmalloc) {
+ __mmalloc_current_heap = mmalloc_preinit();
} 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.
- }
+ mm_real_realloc = dlsym(RTLD_NEXT, "realloc");
+ mm_real_malloc = dlsym(RTLD_NEXT, "malloc");
+ mm_real_free = dlsym(RTLD_NEXT, "free");
+ mm_real_calloc = dlsym(RTLD_NEXT, "calloc");
}
+ mm_initializing = 0;
+ mm_initialized = 1;
}
+/* ***** malloc/free implementation
+ *
+ * They call either the underlying/native/RTLD_NEXT implementation (non MC mode)
+ * or the mm implementation (MC mode).
+ *
+ * If we are initializing the malloc subsystem, we call the fake/dummy `malloc`
+ * implementation. This is necessary because `dlsym` calls `malloc` and friends.
+ */
+
+#define GET_HEAP() __mmalloc_current_heap
-#else /* NO GNU_LD */
-void *malloc(size_t n)
+void* malloc_no_memset(size_t n)
{
- xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
+ if (!mm_initialized) {
+ if (mm_initializing)
+ return mm_fake_malloc(n);
+ mm_legacy_constructor();
+ }
+
+ if (!__malloc_use_mmalloc) {
+ return mm_real_malloc(n);
+ }
+
+ xbt_mheap_t mdp = GET_HEAP();
+ if (!mdp)
+ return NULL;
LOCK(mdp);
- void *ret = mmalloc(mdp, n);
+ void *ret = mmalloc_no_memset(mdp, n);
UNLOCK(mdp);
+ return ret;
+}
+
+void *malloc(size_t n)
+{
+ if (!mm_initialized) {
+ if (mm_initializing)
+ return mm_fake_malloc(n);
+ mm_legacy_constructor();
+ }
+
+ if (!__malloc_use_mmalloc) {
+ return mm_real_malloc(n);
+ }
+ 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 (!mm_initialized) {
+ if (mm_initializing)
+ return mm_fake_calloc(nmemb, size);
+ mm_legacy_constructor();
+ }
+
+ 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 (!mm_initialized) {
+ if (mm_initializing)
+ return mm_fake_realloc(p, s);
+ mm_legacy_constructor();
+ }
+
+ 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();
+ if (!mm_initialized) {
+ if (mm_initializing)
+ return mm_fake_free(p);
+ mm_legacy_constructor();
+ }
- LOCK(mdp);
- mfree(mdp, p);
- UNLOCK(mdp);
+ if (!__malloc_use_mmalloc) {
+ mm_real_free(p);
+ return;
}
+
+ if (!p)
+ return;
+
+ xbt_mheap_t mdp = GET_HEAP();
+ LOCK(mdp);
+ mfree(mdp, p);
+ UNLOCK(mdp);
}
-#endif /* NO GNU_LD */
#endif /* WANT_MALLOC_OVERRIDE */
}
xbt_assert(__mmalloc_default_mdp != NULL);
-#if 0 && defined(HAVE_GNU_LD) && defined(MMALLOC_WANT_OVERRIDE_LEGACY)
- mm_gnuld_legacy_init();
-#endif
-
return __mmalloc_default_mdp;
}
// xbt_mheap_destroy_no_free(__mmalloc_default_mdp);
}
-size_t mmalloc_get_bytes_used(xbt_mheap_t heap){
- int i = 0, j = 0;
+// This is the underlying implementation of mmalloc_get_bytes_used_remote.
+// Is it used directly in order to evaluate the bytes used from a different
+// process.
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo)
+{
int bytes = 0;
-
- while(i<=((struct mdesc *)heap)->heaplimit){
- if(((struct mdesc *)heap)->heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
- if(((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size > 0)
- bytes += ((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size;
-
- } else if(((struct mdesc *)heap)->heapinfo[i].type > 0){
- for(j=0; j < (size_t) (BLOCKSIZE >> ((struct mdesc *)heap)->heapinfo[i].type); j++){
- if(((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j] > 0)
- bytes += ((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j];
+ for (size_t i=0; i<=heaplimit; ++i){
+ if (heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
+ if (heapinfo[i].busy_block.busy_size > 0)
+ bytes += heapinfo[i].busy_block.busy_size;
+ } else if (heapinfo[i].type > 0) {
+ for (size_t j=0; j < (size_t) (BLOCKSIZE >> heapinfo[i].type); j++){
+ if(heapinfo[i].busy_frag.frag_size[j] > 0)
+ bytes += heapinfo[i].busy_frag.frag_size[j];
}
}
- i++;
}
-
return bytes;
}
+size_t mmalloc_get_bytes_used(const xbt_mheap_t heap){
+ const struct mdesc* heap_data = (const struct mdesc *) heap;
+ return mmalloc_get_bytes_used_remote(heap_data->heaplimit, heap_data->heapinfo);
+}
+
ssize_t mmalloc_get_busy_size(xbt_mheap_t heap, void *ptr){
ssize_t block = ((char*)ptr - (char*)(heap->heapbase)) / BLOCKSIZE + 1;
{
void *result;
size_t block, blocks, lastblocks, start;
- register size_t i;
- register size_t log;
+ size_t i;
+ size_t log;
int it;
size_t requested_size = size; // The amount of memory requested by user, for real
mdp->heapinfo[block].busy_frag.ignore[0] = 0;
//xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_frag.bt[0],XBT_BACKTRACE_SIZE);
//xbt_libunwind_backtrace(mdp->heapinfo[block].busy_frag.bt[0],XBT_BACKTRACE_SIZE);
-
+
/* update stats */
mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1;
mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log);
mdp->heapinfo[block].busy_block.busy_size = requested_size;
//mdp->heapinfo[block].busy_block.bt_size = xbt_backtrace_no_malloc(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE);
//mdp->heapinfo[block].busy_block.bt_size = xbt_libunwind_backtrace(mdp->heapinfo[block].busy_block.bt,XBT_BACKTRACE_SIZE);
-
+
mdp -> heapstats.chunks_used++;
mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE;
#ifndef __MMPRIVATE_H
#define __MMPRIVATE_H 1
+#include <xbt/misc.h>
+
#include "portable.h"
#include "xbt/xbt_os_thread.h"
#include "xbt/mmalloc.h"
#define ADDRESS(B) ((void*) (((ADDR2UINT(B)) - 1) * BLOCKSIZE + (char*) mdp -> heapbase))
+SG_BEGIN_DECL()
+
/* Doubly linked lists of free fragments. */
struct list {
struct list *next;
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);
+
+SG_END_DECL()
+
#endif /* __MMPRIVATE_H */
#endif
#define fast_memcpy(d,s,n) \
- { register size_t nn = (size_t)(n); \
+ { size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memcpy((d), (s), nn); \
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
- register char *dd; register const char *ss; \
+ char *dd; const char *ss; \
for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
#define fast_memset(d,c,n) \
- { register size_t nn = (size_t)(n); \
+ { size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memset((d), (int)(c), nn); \
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
- register char *dd; register const int cc=(int)(c); \
+ char *dd; const int cc=(int)(c); \
for (dd=(d); nn>0; nn--) *dd++ = cc; } }
/* prototypes */
++xbt_pagebits;
}
-#ifdef MMALLOC_WANT_OVERRIDE_LEGACY
- mmalloc_preinit();
-#endif
#ifdef _TWO_DIGIT_EXPONENT
/* Even printf behaves differently on Windows... */
_set_output_format(_TWO_DIGIT_EXPONENT);
#define XBT_MODINTER_H
#include "xbt/misc.h"
+SG_BEGIN_DECL()
+
/* Modules definitions */
void xbt_backtrace_preinit(void);
void xbt_backtrace_postexit(void);
void *mmalloc_preinit(void);
void mmalloc_postexit(void);
+SG_END_DECL()
#endif /* XBT_MODINTER_H */
if(HAVE_MC)
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
- add_executable(dwarf dwarf.c)
+ add_executable(dwarf dwarf.cpp)
target_link_libraries(dwarf simgrid)
endif()
)
set(testsuite_src
${testsuite_src}
- ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.cpp
PARENT_SCOPE
)
return NULL;
}
-static dw_variable_t find_global_variable_by_name(mc_object_info_t info, const char* name) {
- unsigned int cursor = 0;
- dw_variable_t variable;
- xbt_dynar_foreach(info->global_variables, cursor, variable){
- if(!strcmp(name, variable->name))
- return variable;
- }
-
- return NULL;
-}
-
static dw_frame_t find_function_by_name(mc_object_info_t info, const char* name) {
xbt_dict_cursor_t cursor = 0;
dw_frame_t subprogram;
}
-static dw_variable_t test_global_variable(mc_object_info_t info, const char* name, void* address, long byte_size) {
- dw_variable_t variable = find_global_variable_by_name(info, name);
+static dw_variable_t test_global_variable(mc_process_t process, mc_object_info_t info, const char* name, void* address, long byte_size) {
+
+ dw_variable_t variable = MC_file_object_info_find_variable_by_name(info, name);
xbt_assert(variable, "Global variable %s was not found", name);
xbt_assert(!strcmp(variable->name, name), "Name mismatch for %s", name);
xbt_assert(variable->global, "Variable %s is not global", name);
xbt_assert(variable->address == address,
"Address mismatch for %s : %p expected but %p found", name, address, variable->address);
- dw_type_t type = xbt_dict_get_or_null(mc_binary_info->types, variable->type_origin);
+ dw_type_t type = (dw_type_t) xbt_dict_get_or_null(process->binary_info->types, variable->type_origin);
xbt_assert(type!=NULL, "Missing type for %s", name);
xbt_assert(type->byte_size = byte_size, "Byte size mismatch for %s", name);
return variable;
typedef struct foo {int i;} s_foo;
-static void test_type_by_name(s_foo my_foo) {
- assert(xbt_dict_get_or_null(mc_binary_info->full_types_by_name, "struct foo"));
+static void test_type_by_name(mc_process_t process, s_foo my_foo) {
+ assert(xbt_dict_get_or_null(process->binary_info->full_types_by_name, "struct foo"));
}
-int main(int argc, char** argv) {
-
- // xbt_init(&argc, argv);
+int main(int argc, char** argv)
+{
SIMIX_global_init(&argc, argv);
- MC_memory_init();
- MC_init();
dw_variable_t var;
dw_type_t type;
- test_global_variable(mc_binary_info, "some_local_variable", &some_local_variable, sizeof(int));
+ s_mc_process_t p;
+ mc_process_t process = &p;
+ MC_process_init(&p, getpid(), -1);
+
+ 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 = (dw_type_t) 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 = (dw_type_t) xbt_dict_get_or_null(process->binary_info->types, var->type_origin);
+ assert(find_member(process->binary_info, "first", type)->offset == 0);
+ assert(find_member(process->binary_info, "second", type)->offset
== ((const char*)&test_some_struct.second) - (const char*)&test_some_struct);
unw_context_t context;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
- test_local_variable(mc_binary_info, "main", "argc", &argc, &cursor);
+ test_local_variable(process->binary_info, "main", "argc", &argc, &cursor);
{
int lexical_block_variable = 50;
- test_local_variable(mc_binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
+ test_local_variable(process->binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
}
s_foo my_foo;
- test_type_by_name(my_foo);
+ test_type_by_name(process, my_foo);
_exit(0);
}
#! ./tesh
$ $SG_TEST_EXENV ${bindir:=.}/dwarf
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
#include "../src/mc/mc_private.h"
#include "../src/mc/mc_object_info.h"
+static s_mc_process_t process;
+
static
uintptr_t eval_binary_operation(mc_expression_state_t state, int op, uintptr_t a, uintptr_t b) {
state->stack_size = 0;
}
int main(int argc, char** argv) {
+ MC_process_init(&process, getpid(), -1);
+
s_mc_expression_state_t state;
memset(&state, 0, sizeof(s_mc_expression_state_t));
+ state.address_space = (mc_address_space_t) &process;
basic_test(&state);
#include <stdio.h>
+#include <xbt/log.h>
#include <simgrid/msg.h>
#include <simgrid/modelchecker.h>
+XBT_LOG_NEW_DEFAULT_CATEGORY(random_bug, "Application");
+
/** An (fake) application with a bug occuring for some random values
*/
static int app(int argc, char *argv[])
MSG_function_register("app", &app);
MSG_create_environment(argv[1]);
MSG_launch_application(argv[2]);
- return (int) MSG_main();
+ return MSG_main();
}
#!/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) **************************
-> [ 0.000000] (1:app@Tremblay) Counter-example execution trace:
-> [ 0.000000] (1:app@Tremblay) Path = 1/3;1/4
-> [ 0.000000] (1:app@Tremblay) [(1)Tremblay (app)] MC_RANDOM(3)
-> [ 0.000000] (1:app@Tremblay) [(1)Tremblay (app)] MC_RANDOM(4)
-> [ 0.000000] (1:app@Tremblay) Expanded states = 27
-> [ 0.000000] (1:app@Tremblay) Visited states = 68
-> [ 0.000000] (1:app@Tremblay) Executed transitions = 46
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) *** PROPERTY NOT VALID ***
+> [ 0.000000] (0:@) **************************
+> [ 0.000000] (0:@) Counter-example execution trace:
+> [ 0.000000] (0:@) Path = 1/3;1/4
+> [ 0.000000] (0:@) [(1)Tremblay (app)] MC_RANDOM(3)
+> [ 0.000000] (0:@) [(1)Tremblay (app)] MC_RANDOM(4)
+> [ 0.000000] (0:@) Expanded states = 27
+> [ 0.000000] (0:@) Visited states = 68
+> [ 0.000000] (0:@) Executed transitions = 46
#!/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
test = 5;
if (xbt_dynar_search_or_negative(tests, &test)!=-1){
XBT_INFO("Test 5 (turn off dest during a communication : Create a Process/task to make a communication between Tremblay and Jupiter and turn off Jupiter during the communication");
+ XBT_INFO("Warning! I think this test is completely broken and it was revealed by exception/exception test.");
+ XBT_INFO("At time 20, Jupiter should wake up with a HOST_FAILURE and it gets a TRANSFERT_FAILURE. This is because when turning off Jupiter, its processes are killed, which cancels/destroys the corresponding surf communication instead of canceling a src_ or dst_timeout.");
MSG_host_on(jupiter);
MSG_process_sleep(10);
argvF = xbt_new(char*, 2);
MSG_process_sleep(10);
XBT_INFO(" Turn Jupiter off");
MSG_host_off(jupiter);
- XBT_INFO("Test 4 seems ok, cool !(number of Process : %d, it should be 2", MSG_process_get_number());
+ XBT_INFO("Test 5 seems ok, cool !(number of Process : %d, it should be 2", MSG_process_get_number());
}
test =6;
> [Tremblay:commRX:(2) 20.000000] [msg_test/INFO] RX Done
> [20.000000] [msg_test/INFO] Simulation time 20
+# This test is broken:
$ ./host_on_off_processes ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/host_on_off_processes_d.xml 5 --log=no_loc --log=msg.thresh:error --log=surf_maxmin.thresh:error
> [Tremblay:test_launcher:(1) 0.000000] [msg_test/INFO] Test 5 (turn off dest during a communication : Create a Process/task to make a communication between Tremblay and Jupiter and turn off Jupiter during the communication
> [Jupiter:commRX:(2) 10.000000] [msg_test/INFO] Start RX
> [Tremblay:commTX:(3) 10.000000] [msg_test/INFO] Start TX
> [Tremblay:test_launcher:(1) 10.000000] [msg_test/INFO] number of processes: 3
> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Turn Jupiter off
-> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test 4 seems ok, cool !(number of Process : 2, it should be 2
+> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test 5 seems ok, cool !(number of Process : 2, it should be 2
> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test done. See you!
> [Tremblay:commTX:(3) 40.000000] [msg_test/INFO] TX done
> [40.000000] [msg_test/INFO] Simulation time 40
> [Jupiter:slave:(2) 0.993652] [msg_test/INFO] Handling task "cancel"
> [Jupiter:worker1:(3) 0.993652] [msg_test/INFO] Start cancel
> [Jupiter:slave:(2) 1.093652] [msg_test/INFO] Canceling task "cancel"
-> [Jupiter:worker1:(3) 1.112666] [msg_test/INFO] Task failed
+> [Jupiter:worker1:(3) 1.093652] [msg_test/INFO] Task failed
> [Tremblay:master:(1) 1.262806] [msg_test/INFO] Goodbye now!
> [Jupiter:slave:(2) 1.262806] [msg_test/INFO] Handling task "finalize"
> [Jupiter:slave:(2) 1.262806] [msg_test/INFO] Destroying task "finalize"
#! ./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 -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock4
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock5
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock6
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-wait-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 29
> [0.000000] [mc_global/INFO] Executed transitions = 28
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 24
> [0.000000] [mc_global/INFO] Executed transitions = 23
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 29
> [0.000000] [mc_global/INFO] Executed transitions = 28
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_create
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" --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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Executed transitions = 22
> (1) Got MPI_COMM_NULL
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_dup
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_split
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Executed transitions = 34
> (1) Derived communicator too small (size = 1)
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/bcast-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 4
> [0.000000] [mc_global/INFO] Executed transitions = 3
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder-allreduce
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 23
> [0.000000] [mc_global/INFO] Executed transitions = 22
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 45
> [0.000000] [mc_global/INFO] Executed transitions = 44
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/complex-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 26
> [0.000000] [mc_global/INFO] Executed transitions = 25
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/deadlock-config
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> WARNING: This test depends on the MPI's eager limit. Set it appropriately.
> Initializing (0 of 3)
> (0) is alive on Tremblay
> [0.000000] [mc_global/INFO] Visited states = 4
> [0.000000] [mc_global/INFO] Executed transitions = 3
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/finalize-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (1) Finished normally
> (2) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/irecv-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> [0.000000] [mc_global/INFO] Visited states = 22
> [0.000000] [mc_global/INFO] Executed transitions = 21
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (0) Finished normally
> (1) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3-any_src
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-
#! ./tesh
! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -wrapper "${bindir:=.}/../../../../bin/simgrid-mc" -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 --log=smpi_coll.thresh:error
+> [0.000000] [mc_safety/INFO] Check a safety property
> [0.000000] [surf_config/INFO] Switching workstation model to compound since you changed the network and/or cpu model(s)
-> [0.000000] [mc_global/INFO] Check a safety property
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
> (0) is alive on Tremblay
> (1) is alive on Jupiter
> (2) is alive on Fafard
> (2) Finished normally
> (0) Finished normally
> Aborted
-