Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr/gitroot/simgrid/simgrid
authorAdrien Lebre <alebre@dhcp-2-16.rech172-28.emn.fr>
Tue, 19 May 2015 13:35:27 +0000 (15:35 +0200)
committerAdrien Lebre <alebre@dhcp-2-16.rech172-28.emn.fr>
Tue, 19 May 2015 13:35:27 +0000 (15:35 +0200)
232 files changed:
.gitignore
CMakeLists.txt
ChangeLog
buildtools/Cmake/AddTests.cmake
buildtools/Cmake/CompleteInFiles.cmake
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/Distrib.cmake
buildtools/Cmake/Flags.cmake
buildtools/Cmake/MaintainerMode.cmake
buildtools/Cmake/MakeLib.cmake
buildtools/Cmake/PrintArgs.cmake
buildtools/Cmake/UnitTesting.cmake
buildtools/Cmake/src/internal_config.h.in
doc/Doxyfile.in
doc/doxygen/contributing.doc
doc/doxygen/getting_started.doc
examples/java/cloud/Master.java
examples/java/cloud/cloud.tesh
examples/java/cloud/migration/Test.java
examples/java/cloud/migration/TestHostOnOff.java
examples/java/cloud/migration/migration.tesh
examples/msg/chord/chord.c
examples/msg/cloud/master_worker_vm.tesh
examples/msg/cloud/simple_vm.tesh
examples/msg/exception/exception.c
examples/msg/exception/exception.tesh
examples/msg/mc/bugged1.c
examples/msg/mc/bugged1.tesh
examples/msg/mc/bugged1_liveness.c
examples/msg/mc/bugged1_liveness.tesh
examples/msg/mc/bugged1_liveness_sparse.tesh
examples/msg/mc/bugged1_liveness_visited.tesh
examples/msg/mc/bugged1_liveness_visited_sparse.tesh
examples/msg/mc/bugged2.c
examples/msg/mc/bugged2.tesh
examples/msg/mc/bugged2_liveness.c
examples/msg/mc/bugged3.c
examples/msg/mc/electric_fence.c
examples/msg/start_kill_time/deployment.xml
examples/msg/start_kill_time/deployment_kill.xml
examples/msg/start_kill_time/deployment_start.xml
examples/msg/start_kill_time/deployment_start_kill.xml
examples/msg/start_kill_time/sk_time.c
examples/msg/start_kill_time/start_kill_time.tesh
examples/smpi/mc/bugged1_liveness.c
examples/smpi/mc/non_deterministic.tesh [new file with mode: 0644]
examples/smpi/mc/only_send_deterministic.tesh
include/msg/datatypes.h [new file with mode: 0644]
include/msg/msg.h [new file with mode: 0644]
include/simdag/datatypes.h [new file with mode: 0644]
include/simdag/simdag.h [new file with mode: 0644]
include/simgrid/modelchecker.h
include/simgrid/simix.h
include/smpi/mpif.h.in
include/smpi/smpi.h
include/xbt/automaton.h
include/xbt/dynar.h
include/xbt/ex.h
include/xbt/fifo.h
include/xbt/heap.h
include/xbt/misc.h
include/xbt/mmalloc.h
include/xbt/str.h
include/xbt/swag.h
src/bindings/java/jmsg_comm.c
src/bindings/java/jmsg_comm.h
src/bindings/java/jmsg_rngstream.c
src/bindings/java/jmsg_rngstream.h
src/bindings/java/jmsg_synchro.c
src/bindings/java/jmsg_synchro.h
src/bindings/java/jmsg_task.c
src/bindings/java/jmsg_task.h
src/bindings/java/jmsg_vm.c
src/bindings/java/jmsg_vm.h
src/bindings/java/org/simgrid/msg/Comm.java
src/bindings/java/org/simgrid/msg/Mutex.java
src/bindings/java/org/simgrid/msg/Process.java
src/bindings/java/org/simgrid/msg/RngStream.java
src/bindings/java/org/simgrid/msg/Semaphore.java
src/bindings/java/org/simgrid/msg/Task.java
src/bindings/java/org/simgrid/msg/VM.java
src/include/mc/datatypes.h
src/include/mc/mc.h
src/mc/ModelChecker.cpp [new file with mode: 0644]
src/mc/ModelChecker.hpp [new file with mode: 0644]
src/mc/PageStore.cpp [moved from src/mc/mc_page_store.cpp with 89% similarity]
src/mc/PageStore.hpp [moved from src/mc/mc_page_store.h with 88% similarity]
src/mc/mc_address_space.cpp [new file with mode: 0644]
src/mc/mc_address_space.h [new file with mode: 0644]
src/mc/mc_base.c [deleted file]
src/mc/mc_base.cpp [new file with mode: 0644]
src/mc/mc_base.h
src/mc/mc_checkpoint.cpp [moved from src/mc/mc_checkpoint.c with 58% similarity]
src/mc/mc_client.cpp [new file with mode: 0644]
src/mc/mc_client.h [new file with mode: 0644]
src/mc/mc_client_api.cpp [new file with mode: 0644]
src/mc/mc_comm_determinism.cpp [moved from src/mc/mc_comm_determinism.c with 62% similarity]
src/mc/mc_comm_pattern.cpp [new file with mode: 0644]
src/mc/mc_comm_pattern.h
src/mc/mc_compare.cpp
src/mc/mc_config.cpp [moved from src/mc/mc_config.c with 94% similarity]
src/mc/mc_diff.cpp [moved from src/mc/mc_diff.c with 85% similarity]
src/mc/mc_dwarf.cpp [moved from src/mc/mc_dwarf.c with 91% similarity]
src/mc/mc_dwarf_expression.cpp [moved from src/mc/mc_dwarf_expression.c with 87% similarity]
src/mc/mc_forward.h
src/mc/mc_global.cpp [moved from src/mc/mc_global.c with 53% similarity]
src/mc/mc_hash.cpp [moved from src/mc/mc_hash.c with 84% similarity]
src/mc/mc_ignore.cpp [new file with mode: 0644]
src/mc/mc_ignore.h [new file with mode: 0644]
src/mc/mc_interface.h [deleted file]
src/mc/mc_liveness.cpp [moved from src/mc/mc_liveness.c with 89% similarity]
src/mc/mc_liveness.h
src/mc/mc_location.h
src/mc/mc_member.cpp [moved from src/mc/mc_member.c with 89% similarity]
src/mc/mc_memory.c [deleted file]
src/mc/mc_memory.cpp [new file with mode: 0644]
src/mc/mc_memory_map.h
src/mc/mc_mmalloc.h
src/mc/mc_mmu.h
src/mc/mc_model_checker.h [deleted file]
src/mc/mc_object_info.cpp [new file with mode: 0644]
src/mc/mc_object_info.h
src/mc/mc_page_snapshot.cpp
src/mc/mc_pair.cpp [moved from src/mc/mc_pair.c with 98% similarity]
src/mc/mc_private.h
src/mc/mc_process.cpp [new file with mode: 0644]
src/mc/mc_process.h [new file with mode: 0644]
src/mc/mc_protocol.cpp [new file with mode: 0644]
src/mc/mc_protocol.h [new file with mode: 0644]
src/mc/mc_record.cpp [moved from src/mc/mc_record.c with 94% similarity]
src/mc/mc_record.h
src/mc/mc_replay.h [new file with mode: 0644]
src/mc/mc_request.c [deleted file]
src/mc/mc_request.cpp [new file with mode: 0644]
src/mc/mc_request.h
src/mc/mc_safety.cpp [moved from src/mc/mc_safety.c with 79% similarity]
src/mc/mc_safety.h
src/mc/mc_server.cpp [new file with mode: 0644]
src/mc/mc_server.h [new file with mode: 0644]
src/mc/mc_set.cpp [deleted file]
src/mc/mc_smx.cpp [new file with mode: 0644]
src/mc/mc_smx.h [new file with mode: 0644]
src/mc/mc_snapshot.cpp [moved from src/mc/mc_snapshot.c with 63% similarity]
src/mc/mc_snapshot.h
src/mc/mc_state.c [deleted file]
src/mc/mc_state.cpp [new file with mode: 0644]
src/mc/mc_state.h
src/mc/mc_unw.cpp [new file with mode: 0644]
src/mc/mc_unw.h [new file with mode: 0644]
src/mc/mc_unw_vmread.cpp [new file with mode: 0644]
src/mc/mc_visited.cpp [moved from src/mc/mc_visited.c with 91% similarity]
src/mc/mcer_ignore.cpp [moved from src/mc/mc_ignore.c with 56% similarity]
src/mc/mcer_ignore.h [new file with mode: 0644]
src/mc/memory_map.cpp [moved from src/mc/memory_map.c with 80% similarity]
src/mc/simgrid_mc.cpp [new file with mode: 0644]
src/msg/msg_global.c
src/msg/msg_mailbox.c
src/msg/msg_process.c
src/simdag/dax_dtd.c
src/simgrid/sg_config.c
src/simix/libsmx.c
src/simix/popping_bodies.c
src/simix/popping_generated.c
src/simix/popping_private.h
src/simix/simcalls.py
src/simix/smx_context_sysv.c
src/simix/smx_context_thread.c
src/simix/smx_global.c
src/simix/smx_host.c
src/simix/smx_network.c
src/simix/smx_process.c
src/simix/smx_process_private.h
src/smpi/colls/reduce-rab.c
src/smpi/private.h
src/smpi/smpi_base.c
src/smpi/smpi_bench.c
src/smpi/smpi_comm.c
src/smpi/smpi_global.c
src/smpi/smpi_pmpi.c
src/surf/network_ib.cpp
src/surf/simgrid_dtd.c
src/surf/surf_interface.cpp
src/xbt/automaton/automaton.c
src/xbt/automaton/automaton_lexer.yy.c
src/xbt/dict.c
src/xbt/dynar.c
src/xbt/ex.c
src/xbt/graphxml.c
src/xbt/heap.c
src/xbt/log.c
src/xbt/mmalloc/mfree.c
src/xbt/mmalloc/mm_legacy.c
src/xbt/mmalloc/mm_module.c
src/xbt/mmalloc/mmalloc.c
src/xbt/mmalloc/mmprivate.h
src/xbt/snprintf.c
src/xbt/xbt_main.c
src/xbt_modinter.h
teshsuite/mc/dwarf/CMakeLists.txt
teshsuite/mc/dwarf/dwarf.cpp [moved from teshsuite/mc/dwarf/dwarf.c with 70% similarity]
teshsuite/mc/dwarf/dwarf.tesh
teshsuite/mc/dwarf_expression/dwarf_expression.c
teshsuite/mc/replay/random_bug.c
teshsuite/mc/replay/random_bug.tesh
teshsuite/mc/replay/random_bug_replay.tesh
teshsuite/msg/host_on_off_processes/host_on_off_processes.c
teshsuite/msg/host_on_off_processes/host_on_off_processes.tesh
teshsuite/msg/task_destroy_cancel/task_destroy_cancel.tesh
teshsuite/smpi/isp/umpire/any_src-can-deadlock10.tesh
teshsuite/smpi/isp/umpire/any_src-can-deadlock4.tesh
teshsuite/smpi/isp/umpire/any_src-can-deadlock5.tesh
teshsuite/smpi/isp/umpire/any_src-can-deadlock6.tesh
teshsuite/smpi/isp/umpire/any_src-wait-deadlock.tesh
teshsuite/smpi/isp/umpire/any_src-waitall-deadlock2.tesh
teshsuite/smpi/isp/umpire/any_src-waitall-deadlock3.tesh
teshsuite/smpi/isp/umpire/any_src-waitany-deadlock.tesh
teshsuite/smpi/isp/umpire/any_src-waitany-deadlock2.tesh
teshsuite/smpi/isp/umpire/basic-deadlock-comm_create.tesh
teshsuite/smpi/isp/umpire/basic-deadlock-comm_dup.tesh
teshsuite/smpi/isp/umpire/basic-deadlock-comm_split.tesh
teshsuite/smpi/isp/umpire/basic-deadlock.tesh
teshsuite/smpi/isp/umpire/bcast-deadlock.tesh
teshsuite/smpi/isp/umpire/collective-misorder-allreduce.tesh
teshsuite/smpi/isp/umpire/collective-misorder.tesh
teshsuite/smpi/isp/umpire/complex-deadlock.tesh
teshsuite/smpi/isp/umpire/deadlock-config.tesh
teshsuite/smpi/isp/umpire/finalize-deadlock.tesh
teshsuite/smpi/isp/umpire/irecv-deadlock.tesh
teshsuite/smpi/isp/umpire/no-error.tesh
teshsuite/smpi/isp/umpire/no-error2.tesh
teshsuite/smpi/isp/umpire/no-error3-any_src.tesh
teshsuite/smpi/isp/umpire/no-error3.tesh

index 973db9c..a3bc468 100644 (file)
@@ -1057,7 +1057,7 @@ examples/smpi/mc/smpi_non_deterministic
 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
index 3e01411..aa3279e 100644 (file)
@@ -4,9 +4,6 @@ if(WIN32)
   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)
 
index dc3e85d..455983d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,8 @@ SimGrid (3.12) NOT RELEASED; urgency=low
    - 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
@@ -30,6 +32,8 @@ SimGrid (3.12) NOT RELEASED; urgency=low
    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
index f24aff1..9b19319 100644 (file)
@@ -212,6 +212,8 @@ IF(NOT enable_memcheck)
   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)
index d15f1c6..ff67e27 100644 (file)
@@ -172,6 +172,7 @@ CHECK_FUNCTION_EXISTS(asprintf HAVE_ASPRINTF)
 CHECK_FUNCTION_EXISTS(vasprintf HAVE_VASPRINTF)
 CHECK_FUNCTION_EXISTS(makecontext HAVE_MAKECONTEXT)
 CHECK_FUNCTION_EXISTS(mmap HAVE_MMAP)
+CHECK_FUNCTION_EXISTS(process_vm_readv HAVE_PROCESS_VM_READV)
 
 #Check if __thread is defined
 execute_process(
index 7d18a4f..abde103 100644 (file)
@@ -6,7 +6,7 @@ set(EXTRA_DIST
   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
@@ -130,6 +130,7 @@ set(EXTRA_DIST
   tools/tesh/tesh.h
   tools/tesh/generate_tesh
   examples/smpi/mc/only_send_deterministic.tesh
+  examples/smpi/mc/non_deterministic.tesh
   )
 
 set(SMPI_SRC
@@ -579,57 +580,86 @@ set(JEDULE_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
index 428db7c..53f9e09 100644 (file)
@@ -205,6 +205,7 @@ set(source_to_pack
   ${LUA_SRC}
   ${MC_SRC_BASE}
   ${MC_SRC}
+  ${MC_SIMGRID_MC_SRC}
   ${MSG_SRC}
   ${NS3_SRC}
   ${RNGSTREAM_SRC}
index d45e7f9..d179a16 100644 (file)
@@ -1,9 +1,23 @@
 set(warnCFLAGS "")
 set(optCFLAGS "")
 
+include(CheckCXXCompilerFlag)
+
+if(NOT __VISUALC__ AND NOT __BORLANDC__)
+  CHECK_CXX_COMPILER_FLAG("-std=c++11" HAVE_CXX11)
+  CHECK_CXX_COMPILER_FLAG("-std=c++0x" HAVE_CXX0X)
+  if(HAVE_CXX11)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+  elseif(HAVE_CXX0X)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+  else()
+    message(STATUS "Missing support for C++11.")
+  endif()
+endif()
+
 if(NOT __VISUALC__ AND NOT __BORLANDC__)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}-std=gnu99 -g3")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}-g3")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -g3")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
   set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g")
 else()
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}/Zi")
@@ -12,7 +26,7 @@ endif()
 
 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 ")
@@ -23,7 +37,10 @@ if(enable_compile_warnings)
     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
 
@@ -63,16 +80,19 @@ if(enable_model-checking AND enable_compile_optimizations)
   set(optCFLAGS "-O0 ")
   # But you can still optimize this:
   foreach(s
-      # src/xbt/mmalloc/mm.c
-      # src/xbt/snprintf.c src/xbt/log.c
-      # src/xbt/dynar.c
-      # src/xbt/set.c src/xbt/setset.c
-      # src/xbt/backtrace_linux.c
-      src/mc/mc_dwarf_expression.c src/mc/mc_dwarf.c src/mc/mc_member.c
-      src/mc/mc_snapshot.c src/mc/mc_page_store.cpp src/mc/mc_page_snapshot.cpp
-      src/mc/mc_compare.cpp src/mc/mc_diff.c
-      src/mc/mc_dwarf.c src/mc/mc_dwarf_attrnames.h src/mc/mc_dwarf_expression.c src/mc/mc_dwarf_tagnames.h
-      src/mc/mc_set.cpp)
+      src/xbt/mmalloc/mm.c
+      src/xbt/log.c src/xbt/xbt_log_appender_file.c
+      src/xbt/xbt_log_layout_format.c src/xbt/xbt_log_layout_simple.c
+      src/xbt/dict.c src/xbt/dict_elm.c src/xbt/dict_multi.c src/xbt/dict_cursor.c
+      src/xbt/set.c src/xbt/setset.c
+      src/xbt/dynar.c src/xbt/fifo.c src/xbt/heap.c src/xbt/swag.c
+      src/xbt/str.c src/xbt/strbuff.c src/xbt/snprintf.c
+      src/xbt/queue.c
+      src/xbt/xbt_os_time.c src/xbt/xbt_os_thread.c
+      src/xbt/sha.c
+      src/xbt/matrix.c
+      src/xbt/backtrace_linux.c
+      ${MC_SRC_BASE} ${MC_SRC})
       set (mcCFLAGS "-O3  -funroll-loops -fno-strict-aliasing")
        if(CMAKE_COMPILER_IS_GNUCC)
          set (mcCFLAGS "${mcCFLAGS} -finline-functions")
index 8fed0cc..6e1c009 100644 (file)
@@ -2,6 +2,11 @@
 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)
@@ -14,7 +19,7 @@ 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
@@ -95,7 +100,7 @@ if(enable_maintainer_mode AND NOT WIN32)
     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}")
@@ -107,17 +112,27 @@ if(enable_maintainer_mode AND NOT WIN32)
 
   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) /'")
index 9f15a91..3e3e538 100644 (file)
@@ -22,6 +22,14 @@ endif()
 
 add_dependencies(simgrid maintainer_files)
 
+if(enable_model-checking)
+  add_executable(simgrid-mc ${MC_SIMGRID_MC_SRC})
+  target_link_libraries(simgrid-mc simgrid)
+  set_target_properties(simgrid-mc
+    PROPERTIES
+      RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+endif()
+
 # Compute the dependencies of SimGrid
 #####################################
 set(SIMGRID_DEP "-lm")
@@ -30,7 +38,19 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
     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()
@@ -78,7 +98,7 @@ if(HAVE_GRAPHVIZ)
 endif()
 
 if(HAVE_LIBSIGC++)
-  SET(SIMGRID_DEP "${SIMGRID_DEP} -lsigc-2.0")   
+  SET(SIMGRID_DEP "${SIMGRID_DEP} -lsigc-2.0")
 endif()
 
 if(HAVE_GTNETS)
@@ -92,8 +112,8 @@ endif()
 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")
@@ -101,7 +121,7 @@ if(HAVE_MC)
   # 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()
index 5180926..9805a49 100644 (file)
@@ -62,6 +62,7 @@ if(enable_print_message)
   message("HAVE_ASPRINTF ...............: ${HAVE_ASPRINTF}")
   message("HAVE_VASPRINTF ..............: ${HAVE_VASPRINTF}")
   message("HAVE_MMAP ...................: ${HAVE_MMAP}")
+  message("HAVE_PROCESS_VM_READV .......: ${HAVE_PROCESS_VM_READV}")
   message("HAVE_THREAD_LOCAL_STORAGE ...: ${HAVE_THREAD_LOCAL_STORAGE}")
   message("HAVE_MMALLOC ................: ${HAVE_MMALLOC}")
   message("")
index 4cfedb0..2435bf6 100644 (file)
@@ -30,12 +30,12 @@ set(TEST_UNITS
 
 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()
 
index 3158937..71ffdbd 100644 (file)
 /* 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@
 
index 005aafa..c3d435b 100644 (file)
@@ -676,7 +676,6 @@ INPUT                  = doxygen/index.doc \
                          @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 \
index 477bc6e..c2b745f 100644 (file)
@@ -20,7 +20,7 @@ our work, so actually citing correctly the framework (see
 <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.
index e071f7f..b4ad556 100644 (file)
@@ -3,7 +3,7 @@
 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
index a581aff..d3606c9 100644 (file)
@@ -81,7 +81,6 @@ public class Master extends Process {
                
                for (int i = 0; i < vms.size(); i++) {
                        vms.get(i).shutdown();
-                       vms.get(i).destroy();
                }                               
                Msg.info("Master done.");
        }
index b6964d4..a76287c 100644 (file)
@@ -30,14 +30,8 @@ $ java -classpath ${classpath:=.} cloud/Cloud ${srcdir:=.}/../platforms/platform
 > [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.
index 7edd538..b697049 100644 (file)
@@ -144,8 +144,9 @@ public class Test extends Process{
         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();
+       
     }
 }
index 1f4278f..47467bd 100644 (file)
@@ -121,16 +121,15 @@ public class TestHostOnOff extends Process{
         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
@@ -156,10 +155,7 @@ public class TestHostOnOff extends Process{
         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,
@@ -179,8 +175,6 @@ public class TestHostOnOff extends Process{
                
         Process.sleep(5000);
         vm0.shutdown();
-        Process.sleep(5000);
-        vm0.destroy();
     }
 
 }
index e17cd4a..3f7bae7 100644 (file)
@@ -23,33 +23,12 @@ $ java -classpath ${classpath:=.} cloud/migration/Main ${srcdir:=.}/../platforms
 > [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] 
@@ -60,34 +39,13 @@ $ java -classpath ${classpath:=.} cloud/migration/Main ${srcdir:=.}/../platforms
 > [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...
index 2cf3234..ff34bf3 100644 (file)
@@ -10,6 +10,7 @@
 #include "xbt/asserts.h"
 #include "simgrid/modelchecker.h"
 #include <xbt/RngStream.h>
+#include "mc/mc_replay.h"
 
 /** @addtogroup MSG_examples
  *
index eda4522..7b9b38c 100644 (file)
@@ -46,25 +46,13 @@ $ $SG_TEST_EXENV ${bindir:=.}/master_worker_vm$EXEEXT --log=no_loc ${srcdir:=.}/
 > [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)
index 67f6155..e98f696 100644 (file)
@@ -67,14 +67,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/simple_vm$EXEEXT --log=no_loc ${srcdir:=.}/../../p
 > [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)
index 8059cd8..90efd13 100644 (file)
@@ -19,9 +19,16 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test_exception,
 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);
@@ -29,25 +36,42 @@ static int victim(int argc, char *argv[]) {
     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;
 }
 
@@ -58,15 +82,29 @@ static int terrorist(int argc, char *argv[])
 
   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;
index cf8cdb2..ab67769 100644 (file)
@@ -3,4 +3,34 @@
 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
index 62539cd..4a7aa9e 100644 (file)
@@ -9,7 +9,7 @@
 /* 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
index 85cd2ce..b8a1ca2 100644 (file)
@@ -2,11 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 20
-$ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
 > [  0.000000] (0:@) Check a safety property
-> [  0.000000] (0:@) Get debug information ...
-> [  0.000000] (0:@) Get debug information done !
 > [  0.000000] (2:client@HostB) Sent!
 > [  0.000000] (3:client@HostC) Sent!
 > [  0.000000] (1:server@HostA) OK
@@ -20,21 +17,20 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  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
index 50ad0ae..b463bf9 100644 (file)
@@ -26,14 +26,6 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(bugged1_liveness, "my log messages");
 int r=0; 
 int cs=0;
 
-int predR(){
-  return r;
-}
-
-int predCS(){
-  return cs;
-}
-
 #ifdef GARBAGE_STACK
 /** Do not use a clean stack */
 static void garbage_stack(void) {
@@ -47,7 +39,6 @@ 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);
@@ -159,22 +150,21 @@ static int raw_client(int argc, char *argv[])
 
 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;
index 5f72c22..5cb0cf0 100644 (file)
@@ -2,11 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 20
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256 --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
@@ -15,7 +12,7 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcd
 > [  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:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
@@ -40,8 +37,8 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcd
 > [  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
index bc934d9..72d4e72 100644 (file)
@@ -2,12 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 60
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [  0.000000] (0:@) Configuration change: Set 'model-check/sparse-checkpoint' to 'yes'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes --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
@@ -16,7 +12,7 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcd
 > [  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:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
@@ -41,7 +37,8 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcd
 > [  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
index d05858a..daaa02e 100644 (file)
@@ -2,12 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 90
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [  0.000000] (0:@) Configuration change: Set 'model-check/visited' to '100'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256  --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
@@ -132,4 +128,3 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcd
 > [  0.000000] (0:@) Visited pairs = 201
 > [  0.000000] (0:@) Executed transitions = 207
 > [  0.000000] (0:@) Counter-example depth : 51
-
index 9e987ea..77e64a4 100644 (file)
@@ -2,13 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 90
-$ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
-> [  0.000000] (0:@) Configuration change: Set 'model-check/visited' to '100'
-> [  0.000000] (0:@) Configuration change: Set 'model-check/sparse-checkpoint' to 'yes'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../../platforms/platform.xml ${srcdir:=.}/deploy_bugged1_liveness_visited.xml --log=xbt_cfg.thresh:warning --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/visited:100 --cfg=contexts/stack_size:256 --cfg=model-check/sparse-checkpoint:yes  --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
index 5d0e375..93bf21d 100644 (file)
@@ -9,7 +9,7 @@
 /* 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
 
index d3d7eec..cadf32f 100644 (file)
@@ -2,11 +2,8 @@
 
 ! expect signal SIGABRT
 ! timeout 20
-$ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/stack_size:256
-> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+$ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --log=xbt_cfg.thresh:warning --cfg=contexts/stack_size:256
 > [  0.000000] (0:@) Check a safety property
-> [  0.000000] (0:@) Get debug information ...
-> [  0.000000] (0:@) Get debug information done !
 > [  0.000000] (2:client@HostB) Send 1!
 > [  0.000000] (3:client@HostC) Send 2!
 > [  0.000000] (1:server@HostA) Received 1
@@ -885,18 +882,17 @@ $ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  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
index 3cdb50a..51e572f 100644 (file)
@@ -19,11 +19,6 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(bugged3, "my log messages");
  
 int cs = 0;
 
-int predCS(){
-  return cs;
-}
-
-
 int coordinator(int argc, char **argv);
 int client(int argc, char **argv);
 
@@ -102,8 +97,7 @@ int main(int argc, char *argv[])
   
   MSG_init(&argc, argv);
 
-  MSG_config("model-check/property","promela_bugged2_liveness");
-  MC_automaton_new_propositional_symbol("cs", &predCS);
+  MC_automaton_new_propositional_symbol_pointer("cs", &cs);
   
   MSG_create_environment("../msg_platform.xml");
   MSG_function_register("coordinator", coordinator);
index 5f949c0..f7c1d26 100644 (file)
@@ -13,7 +13,7 @@
 /* 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");
index 0e03141..a067724 100644 (file)
@@ -11,7 +11,7 @@
 /* --cfg=model-check/max_depth:) is reached.                                  */
 /******************************************************************************/
 
-#include <msg/msg.h>
+#include <simgrid/msg.h>
 #include <simgrid/modelchecker.h>
 
 #define N 2
index fefeb8e..c9b5c37 100644 (file)
@@ -1,10 +1,8 @@
 <?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>
index 39cdf4e..056979d 100644 (file)
@@ -1,10 +1,7 @@
 <?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>
index 203df2b..39af2ab 100644 (file)
@@ -1,10 +1,10 @@
 <?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>
index d4beac4..0a6d5ca 100644 (file)
@@ -1,10 +1,10 @@
 <?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>
index af50303..3ade8f0 100644 (file)
@@ -1,10 +1,10 @@
-/* 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,
@@ -36,8 +34,7 @@ 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();
index 4e98d61..b0cd29c 100644 (file)
@@ -3,57 +3,61 @@
 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
index 68a5ef4..b92f4e3 100644 (file)
 
 int r, cs;
 
-static int predR(){
-  return r;
-}
-
-static int predCS(){
-  return cs;
-}
-
-
 int main(int argc, char **argv){
 
   int err, size, rank;
@@ -47,8 +38,8 @@ int main(int argc, char **argv){
     exit(1);
   }
 
-  MC_automaton_new_propositional_symbol("r", &predR);
-  MC_automaton_new_propositional_symbol("cs", &predCS);
+  MC_automaton_new_propositional_symbol_pointer("r", &r);
+  MC_automaton_new_propositional_symbol_pointer("cs", &cs);
 
   MC_ignore(&(status.count), sizeof(status.count));
 
diff --git a/examples/smpi/mc/non_deterministic.tesh b/examples/smpi/mc/non_deterministic.tesh
new file mode 100644 (file)
index 0000000..494c917
--- /dev/null
@@ -0,0 +1,38 @@
+#! ./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
index ac21435..cc85d75 100644 (file)
@@ -1,18 +1,9 @@
 #! ./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] ******************************************************
@@ -22,5 +13,3 @@ $ ../../../smpi_script/bin/smpirun -hostfile ${srcdir:=.}/hostfile_only_send_det
 > [0.000000] [mc_global/INFO] Executed transitions = 3360
 > [0.000000] [mc_global/INFO] Send-deterministic : Yes
 > [0.000000] [mc_global/INFO] Recv-deterministic : No
-
-
diff --git a/include/msg/datatypes.h b/include/msg/datatypes.h
new file mode 100644 (file)
index 0000000..34c965a
--- /dev/null
@@ -0,0 +1,2 @@
+#warning You should now include directly simgrid/msg.h instead of msg/datatypes.h
+#include "simgrid/msg.h"
diff --git a/include/msg/msg.h b/include/msg/msg.h
new file mode 100644 (file)
index 0000000..e86d89b
--- /dev/null
@@ -0,0 +1,2 @@
+#warning You should now include directly simgrid/msg.h instead of msg/msg.h
+#include "simgrid/msg.h"
diff --git a/include/simdag/datatypes.h b/include/simdag/datatypes.h
new file mode 100644 (file)
index 0000000..571d1aa
--- /dev/null
@@ -0,0 +1,2 @@
+#warning You should now include directly simgrid/simdag.h instead of simdag/datatypes.h
+#include "simgrid/simdag.h"
diff --git a/include/simdag/simdag.h b/include/simdag/simdag.h
new file mode 100644 (file)
index 0000000..6306622
--- /dev/null
@@ -0,0 +1,2 @@
+#warning You should now include directly simgrid/simdag.h instead of simdag/simdag.h
+#include "simgrid/simdag.h"
index 0d41344..15b877d 100644 (file)
@@ -28,7 +28,11 @@ extern int _sg_mc_visited;
 #define MC_visited_reduction()          _sg_mc_visited
 
 XBT_PUBLIC(void) MC_assert(int);
-XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, void* fct);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol(const char* id, int(*fct)(void));
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_pointer(const char *id, int* value);
+XBT_PUBLIC(void) MC_automaton_new_propositional_symbol_callback(const char* id,
+  xbt_automaton_propositional_symbol_callback_type callback,
+  void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
 XBT_PUBLIC(void *) MC_snapshot(void);
 XBT_PUBLIC(int) MC_compare_snapshots(void *s1, void *s2);
 XBT_PUBLIC(void) MC_cut(void);
@@ -41,6 +45,9 @@ XBT_PUBLIC(void) MC_ignore(void *addr, size_t size);
 
 #define MC_assert(a)                    xbt_assert(a)
 #define MC_automaton_new_propositional_symbol(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_pointer(a, b) ((void)0)
+#define MC_automaton_new_propositional_symbol_callback(id,callback,data,free_function) \
+  if(free_function) free_function(data);
 #define MC_snapshot()                   ((void*)0)
 #define MC_compare_snapshots(a, b)      0
 #define MC_cut()                        ((void)0)
@@ -48,17 +55,6 @@ XBT_PUBLIC(void) MC_ignore(void *addr, size_t size);
 
 #endif
 
-/** Replay path (if any) in string representation
- *
- *  This is a path as generated by `MC_record_stack_to_string()`.
- */
-XBT_PUBLIC_DATA(char*) MC_record_path;
-
-/** Whether the replay mode is enabled */
-static inline bool MC_record_replay_is_active(void) {
-  return MC_record_path;
-}
-
 SG_END_DECL()
 
 #endif /* SIMGRID_MODELCHECKER_H */
index a79adf3..ba20c93 100644 (file)
@@ -52,8 +52,6 @@ typedef enum {
 } e_smx_state_t;
 /** @} */
 
-typedef struct s_smx_timer* smx_timer_t;
-
 /* ******************************** Synchro ************************************ */
 /**
  * \ingroup simix_synchro_management
@@ -235,8 +233,12 @@ XBT_PUBLIC(void) SIMIX_run(void);
 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);
 
index 0c07bbb..7f75138 100644 (file)
@@ -18,7 +18,6 @@
       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)
@@ -35,8 +34,6 @@
       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
@@ -51,9 +48,8 @@
       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)
index 0b8a267..97d02cc 100644 (file)
@@ -48,41 +48,100 @@ SG_BEGIN_DECL()
 #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
@@ -90,13 +149,10 @@ SG_BEGIN_DECL()
 #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
@@ -304,7 +360,6 @@ typedef struct s_smpi_mpi_communicator *MPI_Comm;
 
 #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;
index c24453f..e6267e2 100644 (file)
@@ -57,13 +57,11 @@ typedef struct xbt_automaton_transition {
 typedef struct xbt_automaton_transition* xbt_automaton_transition_t;
 
 
-typedef struct xbt_automaton_propositional_symbol{
-  char* pred;
-  void* function;
-} s_xbt_automaton_propositional_symbol;
-
+typedef struct xbt_automaton_propositional_symbol s_xbt_automaton_propositional_symbol;
 typedef struct xbt_automaton_propositional_symbol* xbt_automaton_propositional_symbol_t;
 
+typedef int (*xbt_automaton_propositional_symbol_callback_type)(void*);
+typedef void (*xbt_automaton_propositional_symbol_free_function_type)(void*);
 
 XBT_PUBLIC(xbt_automaton_t) xbt_automaton_new(void);
 
@@ -99,7 +97,21 @@ XBT_PUBLIC(void) xbt_automaton_display(xbt_automaton_t a);
 
 XBT_PUBLIC(void) xbt_automaton_exp_label_display(xbt_automaton_exp_label_t l);
 
-XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct);
+// xbt_automaton_propositional_symbol constructors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void));
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value);
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+  xbt_automaton_t a, const char* id,
+  xbt_automaton_propositional_symbol_callback_type callback,
+  void* data, xbt_automaton_propositional_symbol_free_function_type free_function);
+
+// xbt_automaton_propositional_symbol accessors:
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol);
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol);
+
+// xbt_automaton_propositional_symbol methods!
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol);
 
 XBT_PUBLIC(xbt_automaton_state_t) xbt_automaton_get_current_state(xbt_automaton_t a);
 
index 823dd41..1b34514 100644 (file)
@@ -284,6 +284,17 @@ xbt_dynar_foreach (dyn,cpt,str) {
       _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()
index a72f16b..ab26a72 100644 (file)
@@ -323,9 +323,8 @@ XBT_PUBLIC( void )__xbt_ex_terminate_default(xbt_ex_t * e);
     { \
         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)
index c57456b..b817ea9 100644 (file)
@@ -87,7 +87,7 @@ XBT_PUBLIC(xbt_fifo_item_t) xbt_fifo_get_prev_item(xbt_fifo_item_t i);
  */
 #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))
 
 /** @} */
index e0ddfb8..dda24d4 100644 (file)
@@ -27,6 +27,7 @@ XBT_PUBLIC(int) xbt_heap_size(xbt_heap_t H);
 
 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);
index a0620ab..9bd9b24 100644 (file)
 
 #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
@@ -236,7 +242,7 @@ SG_BEGIN_DECL()
 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);
 
index 191d3cc..6523a01 100644 (file)
@@ -32,6 +32,7 @@ SG_BEGIN_DECL()
  *
  * 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).  */
@@ -62,7 +63,7 @@ XBT_PUBLIC( void ) *xbt_mheap_destroy(xbt_mheap_t md);
 XBT_PUBLIC( xbt_mheap_t ) mmalloc_get_default_md(void);
 
 /* To change the heap used when using the legacy version malloc/free/realloc and such */
-void mmalloc_set_current_heap(xbt_mheap_t new_heap);
+xbt_mheap_t mmalloc_set_current_heap(xbt_mheap_t new_heap);
 xbt_mheap_t mmalloc_get_current_heap(void);
 
 struct s_mc_snapshot;
@@ -71,12 +72,14 @@ struct s_dw_type;
 int mmalloc_compare_heap(struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2);
 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2);
 int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t to_ignore1, xbt_dynar_t to_ignore2);
-int compare_heap_area(int process_index, void *area1, void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
+int compare_heap_area(int process_index, const void *area1, const void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
 void reset_heap_information(void);
 
 size_t mmalloc_get_bytes_used(xbt_mheap_t);
 ssize_t mmalloc_get_busy_size(xbt_mheap_t, void *ptr);
 
+void* malloc_no_memset(size_t n);
+
 SG_END_DECL()
 
 #endif
index be647e8..bd4f575 100644 (file)
@@ -68,14 +68,14 @@ static XBT_INLINE unsigned int xbt_str_hash_ext(const char *str, int str_len)
 #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 */
 
@@ -90,7 +90,7 @@ static XBT_INLINE unsigned int xbt_str_hash_ext(const char *str, int str_len)
   }
 
 # else
-  register unsigned int hash = 0;
+  unsigned int hash = 0;
 
   while (str_len--) {
     hash += (*str) * (*str);
@@ -109,14 +109,14 @@ static XBT_INLINE unsigned int xbt_str_hash(const char *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 */
@@ -129,7 +129,7 @@ static XBT_INLINE unsigned int xbt_str_hash(const char *str)
   }
 
 # else
-  register unsigned int hash = 0;
+  unsigned int hash = 0;
 
   while (*str) {
     hash += (*str) * (*str);
@@ -138,7 +138,7 @@ static XBT_INLINE unsigned int xbt_str_hash(const char *str)
 #endif
   return hash;
 }
-                                                      
+
 /**@}*/
 
 SG_END_DECL()
index df2bdfd..0017a38 100644 (file)
@@ -149,11 +149,17 @@ static XBT_INLINE void *xbt_swag_getFirst(xbt_swag_t swag)
   *  @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
index bf6a09b..2de313c 100644 (file)
@@ -62,7 +62,7 @@ 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) {
   msg_comm_t comm;
   msg_task_t *task_received;
 
index ec099e9..7849c6c 100644 (file)
@@ -20,7 +20,7 @@ JNIEXPORT void JNICALL
 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);
index 5bf195b..14afaae 100644 (file)
@@ -38,7 +38,7 @@ Java_org_simgrid_msg_RngStream_create(JNIEnv *env, jobject jrngstream, jstring j
   (*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);
index e50b218..69457d3 100644 (file)
@@ -20,7 +20,7 @@ JNIEXPORT void JNICALL
 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);
index 71ba2ef..feaeac1 100644 (file)
@@ -52,7 +52,7 @@ 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) {
   xbt_mutex_t mutex;
 
   mutex = (xbt_mutex_t) (long) (*env)->GetLongField(env, obj, jsyncro_field_Mutex_bind);
@@ -104,7 +104,7 @@ 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) {
   msg_sem_t sem;
 
   sem = (msg_sem_t) (long) (*env)->GetLongField(env, obj, jsyncro_field_Semaphore_bind);
index d89ebcf..87fd365 100644 (file)
@@ -26,7 +26,8 @@ JNIEXPORT void JNICALL
 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);
@@ -39,5 +40,5 @@ Java_org_simgrid_msg_Semaphore_release(JNIEnv * env, jobject obj);
 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 */
index 850a999..3530569 100644 (file)
@@ -651,7 +651,17 @@ MSG_task_set_data(task, (void *) (*env)->NewGlobalRef(env, jtask));
   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;
index 77daa9f..b79450a 100644 (file)
@@ -71,6 +71,8 @@ Java_org_simgrid_msg_Task_nativeInit(JNIEnv *env, jclass cls);
 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
index d16c3b0..9338bdc 100644 (file)
@@ -104,7 +104,7 @@ Java_org_simgrid_msg_VM_create(JNIEnv *env, jobject jvm, jobject jhost, jstring
 }
 
 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);
 }
index 5b97777..5aca833 100644 (file)
@@ -102,7 +102,7 @@ Java_org_simgrid_msg_VM_create(JNIEnv *env, jobject jvm, jobject jhost, jstring
  * 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
index ebe63fc..b4d2341 100644 (file)
@@ -40,32 +40,30 @@ public class Comm {
        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;
 
index fbcb634..503588b 100644 (file)
@@ -16,10 +16,15 @@ public class Mutex {
        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();
index 2e4eace..29a69ca 100644 (file)
@@ -299,7 +299,8 @@ public abstract class Process implements Runnable {
        /**
         * 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.
index c7d3a5d..49e7ac3 100644 (file)
@@ -41,16 +41,18 @@ public class RngStream {
         * 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
index d74a8bc..9be79f6 100644 (file)
@@ -65,14 +65,16 @@ public class Semaphore {
        }
 
 
-       /** 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
         */
index 95893ec..0ee65c4 100644 (file)
@@ -161,17 +161,19 @@ public class Task {
        /** 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 * *
         * *                       * */
index c6a5220..77cdaee 100644 (file)
@@ -73,9 +73,15 @@ public class VM extends Host{
                }
                return null; 
        }
-       protected void finalize() {
-               destroy();
+       @Override
+       public void finalize() {
+               try {
+                       nativeFinalize();
+               } catch (Throwable e) {
+                       e.printStackTrace();
+               }
        }
+       private native void nativeFinalize();
 
 
        /* JNI / Native code */
@@ -199,13 +205,6 @@ public class VM extends Host{
        public native void restore();
 
 
-       /**
-        * Destroy the VM
-        */
-       public native void destroy();
-
-
-
        /**
         * Class initializer, to initialize various JNI stuff
         */
index 20805a8..be00ce8 100644 (file)
@@ -7,14 +7,14 @@
 #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()
 
@@ -33,7 +33,6 @@ typedef struct s_mc_heap_ignore_region{
 
 typedef struct s_stack_region{
   void *address;
-  char *process_name;
   void *context;
   size_t size;
   int block;
index e3fcd97..a4d5c27 100644 (file)
@@ -40,7 +40,6 @@ extern int _sg_do_model_check;
 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;
@@ -51,21 +50,20 @@ extern int _sg_mc_comms_determinism;
 extern int _sg_mc_send_determinism;
 extern int _sg_mc_safety;
 extern int _sg_mc_liveness;
+extern int _sg_mc_snapshot_fds;
 extern 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);
@@ -73,7 +71,7 @@ void _mc_cfg_cb_comms_determinism(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);
@@ -85,11 +83,12 @@ XBT_PUBLIC(void) MC_ignore_heap(void *address, size_t size);
 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()
 
diff --git a/src/mc/ModelChecker.cpp b/src/mc/ModelChecker.cpp
new file mode 100644 (file)
index 0000000..2adb895
--- /dev/null
@@ -0,0 +1,43 @@
+/* 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;
+}
+
+}
+}
diff --git a/src/mc/ModelChecker.hpp b/src/mc/ModelChecker.hpp
new file mode 100644 (file)
index 0000000..4e3a565
--- /dev/null
@@ -0,0 +1,56 @@
+/* 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
similarity index 89%
rename from src/mc/mc_page_store.cpp
rename to src/mc/PageStore.cpp
index 11022f8..05df2a8 100644 (file)
@@ -1,4 +1,4 @@
-/* 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
@@ -13,7 +13,7 @@
 
 #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
  *
@@ -35,7 +38,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_page_snapshot, mc,
  *  @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;
@@ -59,7 +62,7 @@ s_mc_pages_store::hash_type mc_hash_page(const void* data)
 
 // ***** 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
@@ -76,12 +79,12 @@ s_mc_pages_store::s_mc_pages_store(size_t size) :
   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;
@@ -102,7 +105,7 @@ void s_mc_pages_store::resize(size_t size)
  *
  *  @return index of the free page
  */
-size_t s_mc_pages_store::alloc_page()
+size_t PageStore::alloc_page()
 {
   if (this->free_pages_.empty()) {
 
@@ -125,7 +128,7 @@ size_t s_mc_pages_store::alloc_page()
   }
 }
 
-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);
@@ -138,9 +141,8 @@ void s_mc_pages_store::remove_page(size_t pageno)
 }
 
 /** Store a page in memory */
-size_t s_mc_pages_store::store_page(void* page)
+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
@@ -191,20 +193,7 @@ size_t s_mc_pages_store::store_page(void* 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
@@ -217,7 +206,7 @@ void mc_pages_store_delete(mc_pages_store_t store)
 
 #include <memory>
 
-#include "mc/mc_page_store.h"
+#include "mc/PageStore.hpp"
 
 static int value = 0;
 
@@ -239,7 +228,8 @@ XBT_TEST_UNIT("base", test_mc_page_store, "Test adding/removing pages in the sto
 {
   xbt_test_add("Init");
   size_t pagesize = (size_t) getpagesize();
-  std::auto_ptr<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");
 
@@ -281,3 +271,5 @@ XBT_TEST_UNIT("base", test_mc_page_store, "Test adding/removing pages in the sto
 }
 
 #endif /* SIMGRID_TEST */
+
+}
similarity index 88%
rename from src/mc/mc_page_store.h
rename to src/mc/PageStore.hpp
index 2f79705..3491f58 100644 (file)
@@ -1,4 +1,4 @@
-/* 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
@@ -23,9 +23,8 @@
 #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
  *
@@ -79,7 +78,7 @@ struct s_mc_pages_store;
  *    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;
@@ -123,8 +122,10 @@ private: // Methods
   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
 
@@ -178,54 +179,38 @@ public: // Debug/test 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
diff --git a/src/mc/mc_address_space.cpp b/src/mc/mc_address_space.cpp
new file mode 100644 (file)
index 0000000..df738ec
--- /dev/null
@@ -0,0 +1,7 @@
+/* Copyright (c) 2008-2014. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "mc_address_space.h"
diff --git a/src/mc/mc_address_space.h b/src/mc/mc_address_space.h
new file mode 100644 (file)
index 0000000..a64b07c
--- /dev/null
@@ -0,0 +1,102 @@
+/* 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
diff --git a/src/mc/mc_base.c b/src/mc/mc_base.c
deleted file mode 100644 (file)
index 2a58722..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* 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;
-}
diff --git a/src/mc/mc_base.cpp b/src/mc/mc_base.cpp
new file mode 100644 (file)
index 0000000..3f609ab
--- /dev/null
@@ -0,0 +1,240 @@
+/* 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
+}
+
+}
index c462414..c3a63c1 100644 (file)
@@ -7,18 +7,39 @@
 #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()
 
similarity index 58%
rename from src/mc/mc_checkpoint.c
rename to src/mc/mc_checkpoint.cpp
index 38f6489..11d66fc 100644 (file)
@@ -4,9 +4,6 @@
 /* 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>
@@ -25,7 +22,6 @@
 
 #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 **************************************/
 /*****************************************************************************************/
 
@@ -49,13 +48,16 @@ static void MC_snapshot_stack_free(mc_snapshot_stack_t s)
   if (s) {
     xbt_dynar_free(&(s->local_variables));
     xbt_dynar_free(&(s->stack_frames));
+    mc_unw_destroy_context(s->context);
+    xbt_free(s->context);
     xbt_free(s);
   }
 }
 
 static void MC_snapshot_stack_free_voidp(void *s)
 {
-  MC_snapshot_stack_free((mc_snapshot_stack_t) * (void **) s);
+  mc_snapshot_stack_t stack = (mc_snapshot_stack_t) * (void **) s;
+  MC_snapshot_stack_free(stack);
 }
 
 static void local_variable_free(local_variable_t v)
@@ -69,59 +71,66 @@ static void local_variable_free_voidp(void *v)
   local_variable_free((local_variable_t) * (void **) v);
 }
 
-void MC_region_destroy(mc_mem_region_t reg)
+void MC_region_destroy(mc_mem_region_t region)
 {
-  if (!reg)
+  if (!region)
     return;
-
-  //munmap(reg->data, reg->size);
-  xbt_free(reg->data);
-  if (reg->page_numbers) {
-    mc_free_page_snapshot_region(reg->page_numbers, mc_page_count(reg->size));
+  switch(region->storage_type) {
+    case MC_REGION_STORAGE_TYPE_NONE:
+      break;
+    case MC_REGION_STORAGE_TYPE_FLAT:
+      xbt_free(region->flat.data);
+      break;
+    case MC_REGION_STORAGE_TYPE_CHUNKED:
+      mc_free_page_snapshot_region(region->chunked.page_numbers, mc_page_count(region->size));
+      xbt_free(region->chunked.page_numbers);
+      break;
+    case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+      {
+        size_t regions_count = region->privatized.regions_count;
+        for (size_t i=0; i!=regions_count; ++i) {
+          MC_region_destroy(region->privatized.regions[i]);
+        }
+        free(region->privatized.regions);
+        break;
+      }
   }
-  xbt_free(reg);
+  xbt_free(region);
 }
 
 void MC_free_snapshot(mc_snapshot_t snapshot)
 {
-  unsigned int i;
-  for (i = 0; i < NB_REGIONS; i++) {
-    MC_region_destroy(snapshot->regions[i]);
+  for (size_t i = 0; i < snapshot->snapshot_regions_count; i++) {
+    MC_region_destroy(snapshot->snapshot_regions[i]);
   }
-
+  xbt_free(snapshot->snapshot_regions);
   xbt_free(snapshot->stack_sizes);
   xbt_dynar_free(&(snapshot->stacks));
   xbt_dynar_free(&(snapshot->to_ignore));
   xbt_dynar_free(&snapshot->ignored_data);
-
-  if (snapshot->privatization_regions) {
-    size_t n = xbt_dynar_length(snapshot->enabled_processes);
-    for (i = 0; i != n; ++i) {
-      MC_region_destroy(snapshot->privatization_regions[i]);
-    }
-    xbt_free(snapshot->privatization_regions);
-  }
-
   xbt_free(snapshot);
 }
 
 /*******************************  Snapshot regions ********************************/
 /*********************************************************************************/
 
-static mc_mem_region_t mc_region_new_dense(int type, void *start_addr, void* permanent_addr, size_t size, mc_mem_region_t ref_reg)
+static mc_mem_region_t mc_region_new_dense(
+  mc_region_type_t region_type,
+  void *start_addr, void* permanent_addr, size_t size)
 {
-  mc_mem_region_t 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
@@ -130,135 +139,146 @@ static mc_mem_region_t mc_region_new_dense(int type, void *start_addr, void* per
  * @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) {
@@ -270,30 +290,42 @@ void MC_find_object_address(memory_map_t maps, mc_object_info_t result)
       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);
@@ -324,6 +356,8 @@ static bool mc_valid_variable(dw_variable_t var, dw_frame_t scope,
 static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
                                            dw_frame_t scope, int process_index, xbt_dynar_t result)
 {
+  mc_process_t process = &mc_model_checker->process();
+
   void *ip = (void *) stack_frame->ip;
   if (ip < scope->low_pc || ip >= scope->high_pc)
     return;
@@ -336,7 +370,8 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
       continue;
 
     int region_type;
-    if ((long) stack_frame->ip > (long) mc_libsimgrid_info->start_exec)
+    // FIXME, get rid of `region_type`
+    if ((long) stack_frame->ip > (long) process->libsimgrid_info->start_exec)
       region_type = 1;
     else
       region_type = 2;
@@ -352,11 +387,12 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
       new_var->address = current_variable->address;
     } else if (current_variable->locations.size != 0) {
       s_mc_location_t location;
-      mc_dwarf_resolve_locations(&location, &current_variable->locations,
-                                              current_variable->object_info,
-                                              &(stack_frame->unw_cursor),
-                                              (void *) stack_frame->frame_base,
-                                              NULL, process_index);
+      mc_dwarf_resolve_locations(
+        &location, &current_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:
@@ -405,15 +441,16 @@ static void MC_stack_frame_free_voipd(void *s)
   }
 }
 
-static xbt_dynar_t MC_unwind_stack_frames(void *stack_context)
+static xbt_dynar_t MC_unwind_stack_frames(mc_unw_context_t stack_context)
 {
+  mc_process_t process = &mc_model_checker->process();
   xbt_dynar_t result =
       xbt_dynar_new(sizeof(mc_stack_frame_t), MC_stack_frame_free_voipd);
 
   unw_cursor_t c;
 
   // TODO, check condition check (unw_init_local==0 means end of frame)
-  if (unw_init_local(&c, (unw_context_t *) stack_context) != 0) {
+  if (mc_unw_init_cursor(&c, stack_context) != 0) {
 
     xbt_die("Could not initialize stack unwinding");
 
@@ -435,7 +472,7 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context)
 
       // TODO, use real addresses in frame_t instead of fixing it here
 
-      dw_frame_t frame = MC_find_function_by_ip((void *) ip);
+      dw_frame_t frame = MC_process_find_function(process, (void *) ip);
       stack_frame->frame = frame;
 
       if (frame) {
@@ -452,11 +489,11 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context)
           && !strcmp(frame->name, "smx_ctx_sysv_wrapper"))
         break;
 
-      int ret = ret = unw_step(&c);
+      int ret = unw_step(&c);
       if (ret == 0) {
         xbt_die("Unexpected end of stack.");
       } else if (ret < 0) {
-        xbt_die("Error while unwinding stack.");
+        xbt_die("Error while unwinding stack");
       }
     }
 
@@ -478,16 +515,29 @@ static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t * snapshot)
   unsigned int cursor = 0;
   stack_region_t current_stack;
 
+  // FIXME, cross-process support (stack_areas)
   xbt_dynar_foreach(stacks_areas, cursor, current_stack) {
     mc_snapshot_stack_t st = xbt_new(s_mc_snapshot_stack_t, 1);
-    st->stack_frames = MC_unwind_stack_frames(current_stack->context);
+
+    // 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;
@@ -531,23 +581,27 @@ static void mc_free_snapshot_ignored_data_pvoid(void* data) {
 
 static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot)
 {
+  xbt_assert(snapshot->process);
   snapshot->ignored_data = xbt_dynar_new(sizeof(s_mc_snapshot_ignored_data_t), mc_free_snapshot_ignored_data_pvoid);
 
   // Copy the memory:
   unsigned int cursor = 0;
   mc_checkpoint_ignore_region_t region;
-  xbt_dynar_foreach (mc_checkpoint_ignore, cursor, region) {
+  xbt_dynar_foreach (mc_model_checker->process().checkpoint_ignore, cursor, region) {
     s_mc_snapshot_ignored_data_t ignored_data;
     ignored_data.start = region->addr;
     ignored_data.size = region->size;
     ignored_data.data = malloc(region->size);
-    memcpy(ignored_data.data, region->addr, region->size);
+    // TODO, we should do this once per privatization segment:
+    MC_process_read(snapshot->process,
+      MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+      ignored_data.data, region->addr, region->size, MC_PROCESS_INDEX_DISABLED);
     xbt_dynar_push(snapshot->ignored_data, &ignored_data);
   }
 
   // Zero the memory:
-  xbt_dynar_foreach (mc_checkpoint_ignore, cursor, region) {
-    memset(region->addr, 0, region->size);
+  xbt_dynar_foreach (mc_model_checker->process().checkpoint_ignore, cursor, region) {
+    MC_process_clear_memory(snapshot->process, region->addr, region->size);
   }
 
 }
@@ -557,40 +611,25 @@ static void MC_snapshot_ignore_restore(mc_snapshot_t snapshot)
   unsigned int cursor = 0;
   s_mc_snapshot_ignored_data_t ignored_data;
   xbt_dynar_foreach (snapshot->ignored_data, cursor, ignored_data) {
-    memcpy(ignored_data.start, ignored_data.data, ignored_data.size);
+    MC_process_write(snapshot->process,
+      ignored_data.data, ignored_data.start, ignored_data.size);
   }
 }
 
-/** @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");
 
@@ -605,12 +644,15 @@ static void MC_get_current_fd(mc_snapshot_t snapshot){
 
     const size_t source_size = 25;
     char source[25];
-    if (snprintf(source, source_size, "/proc/self/fd/%s", fd_number->d_name) > source_size)
+    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);
     }
@@ -646,7 +688,7 @@ static void MC_get_current_fd(mc_snapshot_t snapshot){
     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++;
   }
@@ -655,25 +697,34 @@ static void MC_get_current_fd(mc_snapshot_t snapshot){
   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();
 
@@ -690,36 +741,21 @@ mc_snapshot_t MC_take_snapshot(int num_state)
   }
 
   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
@@ -730,8 +766,16 @@ void MC_restore_snapshot(mc_snapshot_t snapshot)
     smpi_really_switch_data_segment(snapshot->privatization_index);
   }
 #endif
+}
+
+static inline
+void MC_restore_snapshot_fds(mc_snapshot_t snapshot)
+{
+  if (mc_mode == MC_MODE_SERVER)
+    xbt_die("FD snapshot not implemented in client/server mode.");
 
-  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) {
@@ -745,16 +789,16 @@ void MC_restore_snapshot(mc_snapshot_t snapshot)
     };
     lseek(snapshot->current_fd[i]->number, snapshot->current_fd[i]->current_position, SEEK_SET);
   }
+}
 
-  if (_sg_mc_sparse_checkpoint && _sg_mc_soft_dirty) {
-    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)
@@ -762,7 +806,4 @@ mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)
   return MC_take_snapshot(1);
 }
 
-void *MC_snapshot(void)
-{
-  return simcall_mc_snapshot();
 }
diff --git a/src/mc/mc_client.cpp b/src/mc/mc_client.cpp
new file mode 100644 (file)
index 0000000..6109240
--- /dev/null
@@ -0,0 +1,141 @@
+/* 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();
+  }
+}
+
+}
diff --git a/src/mc/mc_client.h b/src/mc/mc_client.h
new file mode 100644 (file)
index 0000000..c919dc8
--- /dev/null
@@ -0,0 +1,36 @@
+/* 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
diff --git a/src/mc/mc_client_api.cpp b/src/mc/mc_client_api.cpp
new file mode 100644 (file)
index 0000000..f4bed1b
--- /dev/null
@@ -0,0 +1,67 @@
+/* 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));
+  }
+}
+
+}
similarity index 62%
rename from src/mc/mc_comm_determinism.c
rename to src/mc/mc_comm_determinism.cpp
index 0636fa4..eb87892 100644 (file)
 #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");
@@ -21,21 +25,6 @@ xbt_dynar_t incomplete_communications_pattern;
 
 /********** 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;
@@ -50,15 +39,15 @@ static e_mc_comm_pattern_difference_t compare_comm_pattern(mc_comm_pattern_t com
   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) {
@@ -99,43 +88,51 @@ static char* print_determinism_result(e_mc_comm_pattern_difference_t diff, int p
   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("*********************************************************");
@@ -162,87 +159,120 @@ static void deterministic_comm_pattern(int process, mc_comm_pattern_t comm, int
     }
   }
     
-  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;
     }
@@ -250,71 +280,68 @@ void complete_comm_pattern(xbt_dynar_t list, smx_synchro_t comm, unsigned int is
   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;
@@ -341,14 +368,12 @@ void MC_modelcheck_comm_determinism(void)
         && (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);
@@ -357,35 +382,31 @@ void MC_modelcheck_comm_determinism(void)
       /* 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);
@@ -402,8 +423,6 @@ void MC_modelcheck_comm_determinism(void)
       if (dot_output != NULL)
         xbt_free(req_str);
 
-      MC_SET_STD_HEAP;
-
     } else {
 
       if (xbt_fifo_size(mc_stack) > _sg_mc_max_depth) {
@@ -414,8 +433,6 @@ void MC_modelcheck_comm_determinism(void)
         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;
 
@@ -424,8 +441,6 @@ void MC_modelcheck_comm_determinism(void)
       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 */
@@ -434,14 +449,11 @@ void MC_modelcheck_comm_determinism(void)
         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);
 
@@ -453,13 +465,38 @@ void MC_modelcheck_comm_determinism(void)
           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;
 }
diff --git a/src/mc/mc_comm_pattern.cpp b/src/mc/mc_comm_pattern.cpp
new file mode 100644 (file)
index 0000000..a5b6e49
--- /dev/null
@@ -0,0 +1,165 @@
+/* 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, &copy_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, &copy_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, &copy);
+  }
+}
+
+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);
+}
+
+}
index 2bb40d2..0f50392 100644 (file)
@@ -13,6 +13,8 @@
 #include "../smpi/private.h"
 #include <smpi/smpi.h>
 
+#include "mc_state.h"
+
 #ifndef MC_COMM_PATTERN_H
 #define MC_COMM_PATTERN_H
 
@@ -20,7 +22,7 @@ SG_BEGIN_DECL()
 
 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;
@@ -38,8 +40,15 @@ typedef struct s_mc_list_comm_pattern{
   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,
@@ -60,7 +69,7 @@ typedef enum {
   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:
@@ -76,14 +85,23 @@ static inline e_mc_call_type_t mc_get_call_type(smx_simcall_t req)
   }
 }
 
-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
index 2eb1d25..d6204d4 100644 (file)
@@ -5,14 +5,17 @@
  * 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"
@@ -23,9 +26,6 @@
 
 #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;
@@ -54,13 +54,15 @@ struct mc_compare_state {
 
 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);
   }
 }
@@ -102,6 +104,8 @@ static int compare_areas_with_type(struct mc_compare_state& state,
                                    void* real_area2, mc_snapshot_t snapshot2, mc_mem_region_t region2,
                                    dw_type_t type, int pointer_level)
 {
+  mc_process_t process = &mc_model_checker->process();
+
   unsigned int cursor = 0;
   dw_type_t member, subtype, subsubtype;
   int elm_size, i, res;
@@ -115,7 +119,7 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_enumeration_type:
   case DW_TAG_union_type:
   {
-    return mc_snapshot_region_memcmp(
+    return MC_snapshot_region_memcmp(
       real_area1, region1, real_area2, region2,
       type->byte_size) != 0;
   }
@@ -169,8 +173,8 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_reference_type:
   case DW_TAG_rvalue_reference_type:
   {
-    void* addr_pointed1 = mc_snapshot_read_pointer_region(real_area1, region1);
-    void* addr_pointed2 = mc_snapshot_read_pointer_region(real_area2, region2);
+    void* addr_pointed1 = MC_region_read_pointer(region1, real_area1);
+    void* addr_pointed2 = MC_region_read_pointer(region2, real_area2);
 
     if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
       return (addr_pointed1 != addr_pointed2);
@@ -190,10 +194,10 @@ static int compare_areas_with_type(struct mc_compare_state& state,
       // * a pointer leads to the read-only segment of the current object;
       // * a pointer lead to a different ELF object.
 
-      if (addr_pointed1 > std_heap
+      if (addr_pointed1 > process->heap_address
           && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)) {
         if (!
-            (addr_pointed2 > std_heap
+            (addr_pointed2 > process->heap_address
              && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
           return 1;
         // The pointers are both in the heap:
@@ -228,9 +232,9 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_class_type:
     xbt_dynar_foreach(type->members, cursor, member) {
       void *member1 =
-        mc_member_resolve(real_area1, type, member, snapshot1, process_index);
+        mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
       void *member2 =
-        mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+        mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
       mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, process_index, region1);
       mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, process_index, region2);
       res =
@@ -260,6 +264,32 @@ static int compare_global_variables(mc_object_info_t object_info,
                                     mc_snapshot_t snapshot2)
 {
   xbt_assert(r1 && r2, "Missing region.");
+
+#ifdef HAVE_SMPI
+  if (r1->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+    xbt_assert(process_index >= 0);
+    if (r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+      return 1;
+    }
+
+    size_t process_count = 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;
@@ -357,6 +387,7 @@ static int compare_local_variables(int process_index,
 
 int snapshot_compare(void *state1, void *state2)
 {
+  mc_process_t process = &mc_model_checker->process();
 
   mc_snapshot_t s1, s2;
   int num1, num2;
@@ -461,10 +492,14 @@ int snapshot_compare(void *state1, void *state2)
 #endif
 
   /* Init heap information used in heap comparison algorithm */
-  xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(std_heap, s1, MC_NO_PROCESS_INDEX,
-    alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
-  xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(std_heap, s2, MC_NO_PROCESS_INDEX,
-    alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
+  xbt_mheap_t heap1 = (xbt_mheap_t) MC_snapshot_read(
+    s1, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+    alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+    MC_PROCESS_INDEX_MISSING);
+  xbt_mheap_t heap2 = (xbt_mheap_t) MC_snapshot_read(
+    s2, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+    alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+    MC_PROCESS_INDEX_MISSING);
   res_init = init_heap_information(heap1, heap2, s1->to_ignore, s2->to_ignore);
   if (res_init == -1) {
 #ifdef MC_DEBUG
@@ -540,21 +575,27 @@ int snapshot_compare(void *state1, void *state2)
     cursor++;
   }
 
+  size_t regions_count = s1->snapshot_regions_count;
+  // TODO, raise a difference instead?
+  xbt_assert(regions_count == s2->snapshot_regions_count);
 
+  mc_comp_times->global_variables_comparison_time = 0;
 
-  const char *names[3] = { "?", "libsimgrid", "binary" };
-#ifdef MC_DEBUG
-  double *times[3] = {
-    NULL,
-    &mc_comp_times->libsimgrid_global_variables_comparison_time,
-    &mc_comp_times->binary_global_variables_comparison_time
-  };
-#endif
+  for (size_t k = 0; k != regions_count; ++k) {
+    mc_mem_region_t region1 = s1->snapshot_regions[k];
+    mc_mem_region_t region2 = s2->snapshot_regions[k];
+
+    // 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);
@@ -562,33 +603,24 @@ int snapshot_compare(void *state1, void *state2)
 #endif
 
     /* Compare global variables */
-#ifdef HAVE_SMPI
-    if (object_infos[k] == mc_binary_info && smpi_privatize_global_variables) {
-      // Compare the global variables separately for each simulates process:
-      for (int process_index = 0; process_index < smpi_process_count(); process_index++) {
-        is_diff =
-          compare_global_variables(object_infos[k], process_index,
-            s1->privatization_regions[process_index], s2->privatization_regions[process_index], s1, s2);
-        if (is_diff) break;
-      }
-    }
-    else
-#endif
-      is_diff =
-        compare_global_variables(object_infos[k], MC_NO_PROCESS_INDEX, s1->regions[k], s2->regions[k], s1, s2);
+    is_diff =
+      compare_global_variables(region1->object_info, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+        region1, region2,
+        s1, s2);
 
     if (is_diff != 0) {
       XBT_TRACE3(mc, state_diff, num1, num2, "Different global variables");
 #ifdef MC_DEBUG
       xbt_os_walltimer_stop(timer);
-      *times[k] = xbt_os_timer_elapsed(timer);
+      mc_comp_times->global_variables_comparison_time
+        += xbt_os_timer_elapsed(timer);
       XBT_DEBUG("(%d - %d) Different global variables in %s", num1, num2,
-                names[k]);
+                name);
       errors++;
 #else
 #ifdef MC_VERBOSE
       XBT_VERB("(%d - %d) Different global variables in %s", num1, num2,
-               names[k]);
+               name);
 #endif
 
       reset_heap_information();
@@ -684,28 +716,9 @@ void print_comparison_times()
   XBT_DEBUG("- Nb processes : %f", mc_comp_times->nb_processes_comparison_time);
   XBT_DEBUG("- Nb bytes used : %f", mc_comp_times->bytes_used_comparison_time);
   XBT_DEBUG("- Stacks sizes : %f", mc_comp_times->stacks_sizes_comparison_time);
-  XBT_DEBUG("- Binary global variables : %f",
-            mc_comp_times->binary_global_variables_comparison_time);
-  XBT_DEBUG("- Libsimgrid global variables : %f",
-            mc_comp_times->libsimgrid_global_variables_comparison_time);
+  XBT_DEBUG("- GLobal variables : %f", mc_comp_times->global_variables_comparison_time);
   XBT_DEBUG("- Heap : %f", mc_comp_times->heap_comparison_time);
   XBT_DEBUG("- Stacks : %f", mc_comp_times->stacks_comparison_time);
 }
 
-/**************************** MC snapshot compare simcall **************************/
-/***********************************************************************************/
-
-int simcall_HANDLER_mc_compare_snapshots(smx_simcall_t simcall,
-                                   mc_snapshot_t s1, mc_snapshot_t s2)
-{
-  return snapshot_compare(s1, s2);
-}
-
-int MC_compare_snapshots(void *s1, void *s2)
-{
-
-  return simcall_mc_compare_snapshots(s1, s2);
-
-}
-
 }
similarity index 94%
rename from src/mc/mc_config.c
rename to src/mc/mc_config.cpp
index d52c95a..bf9eae8 100644 (file)
@@ -10,6 +10,7 @@
 #include <xbt/config.h>
 
 #include <mc/mc.h>
+#include "mc/mc_replay.h"
 
 #include <simgrid/sg_config.h>
 
@@ -20,6 +21,8 @@
 
 #include "mc_record.h"
 
+extern "C" {
+
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_config, mc,
                                 "Configuration of MC");
 
@@ -48,7 +51,6 @@ int _sg_do_model_check = 0;
 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;
@@ -58,9 +60,9 @@ int _sg_mc_comms_determinism = 0;
 int _sg_mc_send_determinism = 0;
 int _sg_mc_safety = 0;
 int _sg_mc_liveness = 0;
+int _sg_mc_snapshot_fds = 0;
 int _sg_mc_termination = 0;
 
-
 void _mc_cfg_cb_reduce(const char *name, int pos)
 {
   if (_sg_cfg_init_status && !_sg_do_model_check) {
@@ -94,13 +96,6 @@ void _mc_cfg_cb_sparse_checkpoint(const char *name, int pos) {
   _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) {
@@ -119,6 +114,15 @@ void _mc_cfg_cb_hash(const char *name, int pos)
   _sg_mc_hash = xbt_cfg_get_boolean(_sg_cfg_set, name);
 }
 
+void _mc_cfg_cb_snapshot_fds(const char *name, int pos)
+{
+  if (_sg_cfg_init_status && !_sg_do_model_check) {
+    xbt_die
+        ("You are specifying a value to enable/disable the use of FD snapshoting, but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
+  }
+  _sg_mc_snapshot_fds = xbt_cfg_get_boolean(_sg_cfg_set, name);
+}
+
 void _mc_cfg_cb_max_depth(const char *name, int pos)
 {
   if (_sg_cfg_init_status && !_sg_do_model_check) {
@@ -174,3 +178,5 @@ void _mc_cfg_cb_termination(const char *name, int pos)
 }
 
 #endif
+
+}
similarity index 85%
rename from src/mc/mc_diff.c
rename to src/mc/mc_diff.cpp
index 03dfb36..abeaf9c 100644 (file)
 #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 ***********************************/
@@ -85,8 +87,6 @@ static void mmalloc_backtrace_display(void *addr)
   /* 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; */
@@ -142,8 +142,7 @@ static int compare_backtrace(int b1, int f1, int b2, int f2)
 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;
@@ -229,7 +228,7 @@ static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1,
 }
 
 static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
-                                           void *address)
+                                           const void *address)
 {
 
   unsigned int cursor = 0;
@@ -253,7 +252,7 @@ static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
   return -1;
 }
 
-static int is_stack(void *address)
+static int is_stack(const void *address)
 {
   unsigned int cursor = 0;
   stack_region_t stack;
@@ -366,10 +365,8 @@ int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1,
     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;
@@ -378,19 +375,19 @@ int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1,
   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 *));
@@ -415,9 +412,22 @@ void reset_heap_information()
 
 }
 
-int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+// TODO, have a robust way to find it in O(1)
+static inline
+mc_mem_region_t MC_get_heap_region(mc_snapshot_t snapshot)
 {
+  size_t n = snapshot->snapshot_regions_count;
+  for (size_t i=0; i!=n; ++i) {
+    mc_mem_region_t region = snapshot->snapshot_regions[i];
+    if (region->region_type == MC_REGION_TYPE_HEAP)
+      return region;
+  }
+  xbt_die("No heap region");
+}
 
+int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
+{
+  mc_process_t process = &mc_model_checker->process();
   struct s_mc_diff *state = mc_diff_info;
 
   /* Start comparison */
@@ -434,17 +444,20 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
   malloc_info heapinfo_temp1, heapinfo_temp2;
   malloc_info heapinfo_temp2b;
 
-  mc_mem_region_t heap_region1 = snapshot1->regions[0];
-  mc_mem_region_t heap_region2 = snapshot2->regions[0];
+  mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+  mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
+
+  // This is the address of std_heap->heapinfo in the application process:
+  void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
 
   // This is in snapshot do not use them directly:
-  malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, MC_NO_PROCESS_INDEX);
-  malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, MC_NO_PROCESS_INDEX);
+  const malloc_info* heapinfos1 = (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 ++;
@@ -458,7 +471,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
 
     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 */
 
@@ -485,12 +498,11 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
 
         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) {
@@ -508,16 +520,15 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
 
       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++;
@@ -530,7 +541,7 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
         }
 
         res_compare =
-            compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+            compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
                               NULL, NULL, 0);
 
         if (res_compare != 1) {
@@ -575,15 +586,14 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
 
           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)
@@ -595,7 +605,9 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
 
         while (i2 <= state->heaplimit && !equal) {
 
-          malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+          const malloc_info* heapinfo2b = (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 ++;
@@ -622,15 +634,14 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
             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) {
@@ -667,7 +678,8 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
   size_t i = 1, j = 0;
 
   for(i = 1; i <= state->heaplimit; i++) {
-    malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
+    const malloc_info* heapinfo1 = (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) {
@@ -708,7 +720,8 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
     XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
 
   for (i=1; i <= state->heaplimit; i++) {
-    malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+    const malloc_info* heapinfo2 = (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) {
@@ -763,20 +776,21 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2)
  * @param check_ignore
  */
 static int compare_heap_area_without_type(struct s_mc_diff *state, int process_index,
-                                          void *real_area1, void *real_area2,
+                                          const void *real_area1, const void *real_area2,
                                           mc_snapshot_t snapshot1,
                                           mc_snapshot_t snapshot2,
                                           xbt_dynar_t previous, int size,
                                           int check_ignore)
 {
+  mc_process_t process = &mc_model_checker->process();
 
   int i = 0;
-  void *addr_pointed1, *addr_pointed2;
+  const void *addr_pointed1, *addr_pointed2;
   int pointer_align, res_compare;
   ssize_t ignore1, ignore2;
 
-  mc_mem_region_t heap_region1 = snapshot1->regions[0];
-  mc_mem_region_t heap_region2 = snapshot2->regions[0];
+  mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+  mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
 
   while (i < size) {
 
@@ -799,21 +813,21 @@ static int compare_heap_area_without_type(struct s_mc_diff *state, int process_i
       }
     }
 
-    if (mc_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
+    if (MC_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
 
       pointer_align = (i / sizeof(void *)) * sizeof(void *);
-      addr_pointed1 = mc_snapshot_read_pointer((char *) real_area1 + pointer_align, snapshot1, process_index);
-      addr_pointed2 = mc_snapshot_read_pointer((char *) real_area2 + pointer_align, snapshot2, process_index);
+      addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char *) real_area1 + pointer_align, process_index);
+      addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char *) real_area2 + pointer_align, process_index);
 
-      if (addr_pointed1 > maestro_stack_start
-          && addr_pointed1 < maestro_stack_end
-          && addr_pointed2 > maestro_stack_start
-          && addr_pointed2 < maestro_stack_end) {
+      if (addr_pointed1 > process->maestro_stack_start
+          && addr_pointed1 < process->maestro_stack_end
+          && addr_pointed2 > process->maestro_stack_start
+          && addr_pointed2 < process->maestro_stack_end) {
         i = pointer_align + sizeof(void *);
         continue;
-      } else if (addr_pointed1 > state->s_heap
+      } 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 =
@@ -853,7 +867,7 @@ static int compare_heap_area_without_type(struct s_mc_diff *state, int process_i
  * @return               0 (same), 1 (different), -1 (unknown)
  */
 static int compare_heap_area_with_type(struct s_mc_diff *state, int process_index,
-                                       void *real_area1, void *real_area2,
+                                       const void *real_area1, const void *real_area2,
                                        mc_snapshot_t snapshot1,
                                        mc_snapshot_t snapshot2,
                                        xbt_dynar_t previous, dw_type_t type,
@@ -875,13 +889,13 @@ top:
   }
 
   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:
@@ -892,12 +906,12 @@ top:
       if (real_area1 == real_area2)
         return -1;
       else
-        return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
+        return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
     } else {
       if (area_size != -1 && type->byte_size != area_size)
         return -1;
       else {
-        return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+        return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
       }
     }
     break;
@@ -905,7 +919,7 @@ top:
     if (area_size != -1 && type->byte_size != area_size)
       return -1;
     else
-      return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
+      return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
     break;
   case DW_TAG_typedef:
   case DW_TAG_const_type:
@@ -945,7 +959,7 @@ top:
       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,
@@ -962,18 +976,18 @@ top:
   case DW_TAG_rvalue_reference_type:
   case DW_TAG_pointer_type:
     if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
-      addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
-      addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
+      addr_pointed1 = MC_snapshot_read_pointer(snapshot1, real_area1, process_index);
+      addr_pointed2 = MC_snapshot_read_pointer(snapshot2, real_area2, process_index);
       return (addr_pointed1 != addr_pointed2);;
     } else {
       pointer_level++;
       if (pointer_level > 1) {  /* Array of pointers */
-        for (i = 0; i < (area_size / sizeof(void *)); i++) {
-          addr_pointed1 = mc_snapshot_read_pointer((char*) real_area1 + i * sizeof(void *), snapshot1, process_index);
-          addr_pointed2 = mc_snapshot_read_pointer((char*) real_area2 + i * sizeof(void *), snapshot2, process_index);
-          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,
@@ -985,11 +999,11 @@ top:
             return res;
         }
       } else {
-        addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
-        addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
-        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,
@@ -1005,7 +1019,7 @@ top:
       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,
@@ -1022,10 +1036,10 @@ top:
       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,
@@ -1090,9 +1104,10 @@ static dw_type_t get_offset_type(void *real_base_address, dw_type_t type,
           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;
         }
 
@@ -1118,10 +1133,11 @@ static dw_type_t get_offset_type(void *real_base_address, dw_type_t type,
  * @param pointer_level
  * @return 0 (same), 1 (different), -1
  */
-int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t snapshot1,
+int compare_heap_area(int process_index, const void *area1, const void *area2, mc_snapshot_t snapshot1,
                       mc_snapshot_t snapshot2, xbt_dynar_t previous,
                       dw_type_t type, int pointer_level)
 {
+  mc_process_t process = &mc_model_checker->process();
 
   struct s_mc_diff *state = mc_diff_info;
 
@@ -1138,8 +1154,13 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
 
   int match_pairs = 0;
 
-  malloc_info* heapinfos1 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot1, process_index);
-  malloc_info* heapinfos2 = mc_snapshot_read_pointer(&std_heap->heapinfo, snapshot2, process_index);
+  // This is the address of std_heap->heapinfo in the application process:
+  void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
+
+  const malloc_info* heapinfos1 = (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;
 
@@ -1151,10 +1172,10 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
   // 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)) {
@@ -1166,10 +1187,10 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
     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);
     }
@@ -1177,12 +1198,10 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
   }
 
   // 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) {
 
@@ -1203,11 +1222,13 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
 
   }
 
-  mc_mem_region_t heap_region1 = snapshot1->regions[0];
-  mc_mem_region_t heap_region2 = snapshot2->regions[0];
+  mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
+  mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
 
-  malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[block1], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
-  malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[block2], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+  const malloc_info* heapinfo1 = (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)) {
@@ -1240,8 +1261,8 @@ int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t
     }
 
     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);
@@ -1526,9 +1547,9 @@ static int get_pointed_area_size(void *area, int heap)
 
   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;
 
@@ -1587,10 +1608,7 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2)
   /* 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;
@@ -1723,3 +1741,5 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2)
 
 }
 #endif
+
+}
similarity index 91%
rename from src/mc/mc_dwarf.c
rename to src/mc/mc_dwarf.cpp
index 2b2c2a0..7c1bcd4 100644 (file)
@@ -4,11 +4,12 @@
 /* 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>
@@ -17,6 +18,8 @@
 #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);
@@ -61,13 +64,13 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit);
  */
 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
  *
@@ -78,7 +81,7 @@ static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die * 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)
  *
@@ -89,7 +92,7 @@ static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die * die,
  */
 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
  *
@@ -117,6 +120,7 @@ const char *MC_dwarf_attrname(int attr)
  *  \param tag tag code (see the DWARF specification)
  *  \return name of the tag
  */
+XBT_INTERNAL
 const char *MC_dwarf_tagname(int tag)
 {
   switch (tag) {
@@ -632,7 +636,7 @@ static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die * die,
  */
 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);
@@ -669,12 +673,18 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die * die,
   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);
@@ -703,10 +713,10 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die * die,
   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;
   }
 
@@ -715,9 +725,9 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die * 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)
 {
-  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);
@@ -732,7 +742,7 @@ static int mc_anonymous_variable_index = 0;
 
 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))
@@ -821,9 +831,9 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die * die,
     }
   }
 
-  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,
@@ -837,10 +847,10 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die * die,
 
 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);
@@ -854,7 +864,7 @@ static void mc_frame_free_voipd(dw_frame_t * p)
 
 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);
@@ -877,7 +887,7 @@ static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die * 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 =
@@ -947,39 +957,39 @@ static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die * die,
     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);
@@ -987,22 +997,22 @@ static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die * die,
 
     // 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:
@@ -1024,7 +1034,7 @@ void MC_dwarf_get_variables(mc_object_info_t info)
   }
   Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
   if (dwarf == NULL) {
-    xbt_die("Your program must be compiled with -g");
+    xbt_die("Your program must be compiled with -g (%s)", info->file_name);
   }
   // For each compilation unit:
   Dwarf_Off offset = 0;
@@ -1105,12 +1115,12 @@ mc_object_info_t MC_new_object_info(void)
 
 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;
 }
@@ -1172,55 +1182,13 @@ static void MC_make_functions_index(mc_object_info_t info)
   info->functions_index = index;
 }
 
-mc_object_info_t MC_ip_find_object_info(void *ip)
-{
-  size_t i;
-  for (i = 0; i != mc_object_infos_size; ++i) {
-    if (ip >= (void *) mc_object_infos[i]->start_exec
-        && ip <= (void *) mc_object_infos[i]->end_exec) {
-      return mc_object_infos[i];
-    }
-  }
-  return NULL;
-}
-
-static dw_frame_t MC_find_function_by_ip_and_object(void *ip,
-                                                    mc_object_info_t info)
-{
-  xbt_dynar_t dynar = info->functions_index;
-  mc_function_index_item_t base =
-      (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
-  int i = 0;
-  int j = xbt_dynar_length(dynar) - 1;
-  while (j >= i) {
-    int k = i + ((j - i) / 2);
-    if (ip < base[k].low_pc) {
-      j = k - 1;
-    } else if (ip >= base[k].high_pc) {
-      i = k + 1;
-    } else {
-      return base[k].function;
-    }
-  }
-  return NULL;
-}
-
-dw_frame_t MC_find_function_by_ip(void *ip)
-{
-  mc_object_info_t info = MC_ip_find_object_info(ip);
-  if (info == NULL)
-    return NULL;
-  else
-    return MC_find_function_by_ip_and_object(ip, info);
-}
-
 static void MC_post_process_variables(mc_object_info_t info)
 {
   unsigned cursor = 0;
   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);
     }
   }
 }
@@ -1232,7 +1200,7 @@ static void mc_post_process_scope(mc_object_info_t info, dw_frame_t scope)
 
     // 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);
@@ -1243,7 +1211,7 @@ static void mc_post_process_scope(mc_object_info_t info, dw_frame_t scope)
   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);
     }
   }
 
@@ -1272,7 +1240,7 @@ static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type)
 
   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)
@@ -1283,7 +1251,7 @@ static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type)
   // 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;
   }
@@ -1310,7 +1278,7 @@ static void MC_post_process_types(mc_object_info_t info)
 }
 
 /** \brief Finds informations about a given shared object/executable */
-mc_object_info_t MC_find_object_info(memory_map_t maps, char *name,
+mc_object_info_t MC_find_object_info(memory_map_t maps, const char *name,
                                      int executable)
 {
   mc_object_info_t result = MC_new_object_info();
@@ -1408,25 +1376,36 @@ void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame,
     MC_dwarf_register_non_global_variable(info, frame, variable);
 }
 
-void MC_post_process_object_info(mc_object_info_t info)
+void MC_post_process_object_info(mc_process_t process, mc_object_info_t info)
 {
   xbt_dict_cursor_t cursor = NULL;
   char *key = NULL;
   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;
 
   }
 }
+
+}
similarity index 87%
rename from src/mc/mc_dwarf_expression.c
rename to src/mc/mc_dwarf_expression.cpp
index 7653210..3d2bc36 100644 (file)
 #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)
@@ -23,6 +24,12 @@ static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
   return 0;
 }
 
+/** Convert a DWARF register into a libunwind register
+ *
+ *  DWARF and libunwind does not use the same convention for numbering the
+ *  registers on some architectures. The function makes the necessary
+ *  convertion.
+ */
 static int mc_dwarf_register_to_libunwind(int dwarf_register)
 {
 #if defined(UNW_TARGET_X86_64)
@@ -84,14 +91,14 @@ static int mc_dwarf_register_to_libunwind(int dwarf_register)
     xbt_die("Bad/unknown register number.");
   }
 #else
-#error This architecture is not supported yet.
+#error This architecture is not supported yet for DWARF expression evaluation.
 #endif
 }
 
 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;
@@ -168,15 +175,16 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       {
         if (!state->frame_base)
           return MC_EXPRESSION_E_MISSING_FRAME_BASE;
-        error =
-            mc_dwarf_push_value(state,
-                                ((uintptr_t) state->frame_base) + op->number);
+        uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
+        error = mc_dwarf_push_value(state, fb);
         break;
       }
 
 
-      // Constants:
+      // ***** Constants:
 
+      // Short constant literals:
+      // DW_OP_lit15 pushed the 15 on the stack.
     case DW_OP_lit0:
     case DW_OP_lit1:
     case DW_OP_lit2:
@@ -212,17 +220,21 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       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:
@@ -238,9 +250,9 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       error = mc_dwarf_push_value(state, op->number);
       break;
 
-      // Stack manipulation:
+      // ***** Stack manipulation:
 
-      // Push the value at the top of the stack:
+      // Push another copy/duplicate the value at the top of the stack:
     case DW_OP_dup:
       if (state->stack_size == 0)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -248,6 +260,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
         error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
       break;
 
+      // Pop/drop the top of the stack:
     case DW_OP_drop:
       if (state->stack_size == 0)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -255,6 +268,7 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
         state->stack_size--;
       break;
 
+      // Swap the two top-most value of the stack:
     case DW_OP_swap:
       if (state->stack_size < 2)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
@@ -266,13 +280,17 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       }
       break;
 
+      // Duplicate the value under the top of the stack:
     case DW_OP_over:
       if (state->stack_size < 2)
         return MC_EXPRESSION_E_STACK_UNDERFLOW;
       error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
       break;
 
-      // Operations:
+      // ***** Operations:
+      // Those usually take the top of the stack and the next value as argument
+      // and replace the top of the stack with the computed value
+      // (stack.top() += stack.before_top()).
 
     case DW_OP_plus:
       if (state->stack_size < 2)
@@ -373,7 +391,8 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
     case DW_OP_nop:
       break;
 
-      // Dereference:
+      // ***** Deference (memory fetch)
+
     case DW_OP_deref_size:
       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
 
@@ -383,9 +402,12 @@ int mc_dwarf_execute_expression(size_t n, const Dwarf_Op * ops,
       {
         // Computed address:
         uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
-        uintptr_t temp;
-        uintptr_t* res = (uintptr_t*) mc_snapshot_read((void*) address, state->snapshot, state->process_index, &temp, sizeof(uintptr_t));
-        state->stack[state->stack_size - 1] = *res;
+        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;
 
@@ -410,13 +432,13 @@ void mc_dwarf_resolve_location(mc_location_t location,
                                mc_object_info_t object_info,
                                unw_cursor_t * c,
                                void *frame_pointer_address,
-                               mc_snapshot_t snapshot, int process_index)
+                               mc_address_space_t address_space, int process_index)
 {
   s_mc_expression_state_t state;
   memset(&state, 0, sizeof(s_mc_expression_state_t));
   state.frame_base = frame_pointer_address;
   state.cursor = c;
-  state.snapshot = snapshot;
+  state.address_space = address_space;
   state.object_info = object_info;
   state.process_index = process_index;
 
@@ -459,7 +481,7 @@ void mc_dwarf_resolve_locations(mc_location_t location,
                                      mc_object_info_t object_info,
                                      unw_cursor_t * c,
                                      void *frame_pointer_address,
-                                     mc_snapshot_t snapshot, int process_index)
+                                     mc_address_space_t address_space, int process_index)
 {
 
   unw_word_t ip = 0;
@@ -472,7 +494,7 @@ void mc_dwarf_resolve_locations(mc_location_t location,
   if (expression) {
     mc_dwarf_resolve_location(location,
                               expression, object_info, c,
-                              frame_pointer_address, snapshot, process_index);
+                              frame_pointer_address, address_space, process_index);
   } else {
     xbt_die("Could not resolve location");
   }
@@ -536,7 +558,7 @@ void mc_dwarf_expression_init(mc_expression_t expression, size_t len,
   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));
 }
 
@@ -587,3 +609,5 @@ void mc_dwarf_location_list_init(mc_location_list_t list, mc_object_info_t info,
   }
 
 }
+
+}
index 267f82c..2152fe8 100644 (file)
@@ -7,16 +7,40 @@
 #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
similarity index 53%
rename from src/mc/mc_global.c
rename to src/mc/mc_global.cpp
index 790d1e9..337b1ba 100644 (file)
@@ -4,15 +4,18 @@
 /* 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
@@ -59,14 +72,6 @@ xbt_fifo_t mc_stack = NULL;
 /* Liveness */
 xbt_automaton_t _mc_property_automaton = NULL;
 
-/* Variables */
-mc_object_info_t mc_libsimgrid_info = NULL;
-mc_object_info_t mc_binary_info = NULL;
-
-mc_object_info_t mc_object_infos[2] = { NULL, NULL };
-
-size_t mc_object_infos_size = 2;
-
 /* Dot output */
 FILE *dot_output = NULL;
 const char *colors[13];
@@ -104,57 +109,27 @@ static void MC_init_dot_output()
 
 }
 
-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);
 
@@ -162,196 +137,48 @@ void MC_init()
   mc_stats = xbt_new0(s_mc_stats_t, 1);
   mc_stats->state_size = 1;
 
-  MC_init_memory_map_info();
-  MC_init_debug_info();         /* FIXME : get debug information only if liveness verification or visited state reduction */
-
   if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0'))
     MC_init_dot_output();
 
   /* 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);
@@ -360,14 +187,36 @@ void MC_exit(void)
   //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;
       }
@@ -375,70 +224,7 @@ int MC_deadlock_check()
   }
   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, &copy_comm);
-    }
-  }
-}
+#endif
 
 /**
  * \brief Re-executes from the state at position start all the transitions indicated by
@@ -448,9 +234,7 @@ static void MC_restore_communications_pattern(mc_state_t state) {
  */
 void MC_replay(xbt_fifo_t stack)
 {
-  int raw_mem = (mmalloc_get_current_heap() == mc_heap);
-
-  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;
@@ -466,7 +250,6 @@ void MC_replay(xbt_fifo_t stack)
       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;
     }
   }
@@ -476,21 +259,20 @@ void MC_replay(xbt_fifo_t stack)
   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);
@@ -502,11 +284,13 @@ void MC_replay(xbt_fifo_t 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);
       }
@@ -514,15 +298,13 @@ void MC_replay(xbt_fifo_t stack)
       /* 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++;
@@ -535,20 +317,10 @@ void MC_replay(xbt_fifo_t stack)
   }
 
   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;
@@ -564,7 +336,6 @@ void MC_replay_liveness(xbt_fifo_t stack)
     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;
     }
   }
@@ -572,11 +343,6 @@ void MC_replay_liveness(xbt_fifo_t stack)
   /* 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);
@@ -593,18 +359,19 @@ void MC_replay_liveness(xbt_fifo_t 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();
       }
 
@@ -617,12 +384,6 @@ void MC_replay_liveness(xbt_fifo_t stack)
     }
 
   XBT_DEBUG("**** End Replay ****");
-
-  if (initial_global_state->raw_mem_set)
-    MC_SET_MC_HEAP;
-  else
-    MC_SET_STD_HEAP;
-
 }
 
 /**
@@ -632,33 +393,17 @@ void MC_replay_liveness(xbt_fifo_t stack)
  */
 void MC_dump_stack_safety(xbt_fifo_t stack)
 {
-
-  int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
   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;
@@ -666,18 +411,15 @@ void MC_show_stack_safety(xbt_fifo_t stack)
   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)
@@ -714,11 +456,11 @@ void MC_show_stack_liveness(xbt_fifo_t stack)
   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);
     }
@@ -728,25 +470,13 @@ void MC_show_stack_liveness(xbt_fifo_t stack)
 
 void MC_dump_stack_liveness(xbt_fifo_t stack)
 {
-
-  int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
   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("******************************************************");
@@ -760,6 +490,7 @@ void MC_print_statistics(mc_stats_t stats)
       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);
@@ -768,7 +499,6 @@ void MC_print_statistics(mc_stats_t stats)
     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
   }
   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
-  MC_SET_MC_HEAP;
   if ((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0] != '\0')) {
     fprintf(dot_output, "}\n");
     fclose(dot_output);
@@ -778,71 +508,62 @@ void MC_print_statistics(mc_stats_t stats)
     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;
@@ -857,15 +578,21 @@ void MC_dump_stacks(FILE* file)
     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
 
@@ -885,3 +612,24 @@ void MC_process_clock_add(smx_process_t process, double amount)
 {
   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
+
+}
similarity index 84%
rename from src/mc/mc_hash.c
rename to src/mc/mc_hash.cpp
index cc78c3d..4164c53 100644 (file)
@@ -4,6 +4,8 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include <cinttypes>
+
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -11,6 +13,8 @@
 #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:
@@ -20,10 +24,11 @@ typedef uint64_t mc_hash_t;
 // #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;
@@ -62,14 +67,12 @@ static bool mc_ignored(const void *address, size_t size)
 
 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).
@@ -81,6 +84,7 @@ static void mc_hash_value(mc_hash_t * hash, mc_hashing_state * state,
                           mc_object_info_t info, const void *address,
                           dw_type_t type)
 {
+  mc_process_t process = &mc_model_checker->process();
 top:
 
   switch (type->type) {
@@ -171,12 +175,12 @@ top:
       mc_address_add(state->handled_addresses, pointed);
 
       // Anything outside the R/W segments and the heap is not hashed:
-      bool valid_pointer = (pointed >= (void *) mc_binary_info->start_rw
-                            && pointed <= (void *) mc_binary_info->end_rw)
-          || (pointed >= (void *) mc_libsimgrid_info->start_rw
-              && pointed <= (void *) mc_libsimgrid_info->end_rw)
-          || (pointed >= std_heap
-              && pointed < (void *) ((const char *) std_heap + STD_HEAP_SIZE));
+      bool valid_pointer = (pointed >= (void *) binary_info->start_rw
+                            && pointed <= (void *) binary_info->end_rw)
+          || (pointed >= (void *) libsimgrid_info->start_rw
+              && pointed <= (void *) libsimgrid_info->end_rw)
+          || (pointed >= process->heap_address
+              && pointed < (void *) ((const char *) process->heap_address + STD_HEAP_SIZE));
       if (!valid_pointer) {
         XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed);
         return;
@@ -220,12 +224,12 @@ static void mc_hash_object_globals(mc_hash_t * hash, mc_hashing_state * state,
     }
 
     const char *address = variable->address;
-    bool valid_pointer = (address >= mc_binary_info->start_rw
-                          && address <= mc_binary_info->end_rw)
-        || (address >= mc_libsimgrid_info->start_rw
-            && address <= mc_libsimgrid_info->end_rw)
-        || (address >= (const char *) std_heap
-            && address < (const char *) std_heap + STD_HEAP_SIZE);
+    bool valid_pointer = (address >= binary_info->start_rw
+                          && address <= binary_info->end_rw)
+        || (address >= libsimgrid_info->start_rw
+            && address <= libsimgrid_info->end_rw)
+        || (address >= (const char *) process->heap_address
+            && address < (const char *) process->heap_address + STD_HEAP_SIZE);
     if (!valid_pointer)
       continue;
 
@@ -285,12 +289,12 @@ static void mc_hash_stack(mc_hash_t * hash, mc_snapshot_stack_t stack,
     MC_HASH(*hash, stack_frame->ip);
 
     mc_object_info_t info;
-    if (stack_frame->ip >= (unw_word_t) mc_libsimgrid_info->start_exec
-        && stack_frame->ip < (unw_word_t) mc_libsimgrid_info->end_exec)
-      info = mc_libsimgrid_info;
-    else if (stack_frame->ip >= (unw_word_t) mc_binary_info->start_exec
-             && stack_frame->ip < (unw_word_t) mc_binary_info->end_exec)
-      info = mc_binary_info;
+    if (stack_frame->ip >= (unw_word_t) libsimgrid_info->start_exec
+        && stack_frame->ip < (unw_word_t) libsimgrid_info->end_exec)
+      info = libsimgrid_info;
+    else if (stack_frame->ip >= (unw_word_t) binary_info->start_exec
+             && stack_frame->ip < (unw_word_t) binary_info->end_exec)
+      info = binary_info;
     else
       continue;
 
@@ -322,18 +326,23 @@ uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks)
 {
   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;
 }
+
+}
diff --git a/src/mc/mc_ignore.cpp b/src/mc/mc_ignore.cpp
new file mode 100644 (file)
index 0000000..f1ac12e
--- /dev/null
@@ -0,0 +1,111 @@
+/* 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(&region, 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(&region, 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));
+}
+
+}
diff --git a/src/mc/mc_ignore.h b/src/mc/mc_ignore.h
new file mode 100644 (file)
index 0000000..b5ac593
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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();
diff --git a/src/mc/mc_interface.h b/src/mc/mc_interface.h
deleted file mode 100644 (file)
index 0bf35d0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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
similarity index 89%
rename from src/mc/mc_liveness.c
rename to src/mc/mc_liveness.cpp
index 6a21a60..0a46c4a 100644 (file)
 #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");
@@ -27,28 +33,19 @@ xbt_parmap_t parmap;
 
 static xbt_dynar_t get_atomic_propositions_values()
 {
-  int res;
-  int_f_void_t f;
   unsigned int cursor = 0;
   xbt_automaton_propositional_symbol_t ps = NULL;
   xbt_dynar_t values = xbt_dynar_new(sizeof(int), NULL);
-
   xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, ps) {
-    f = (int_f_void_t) ps->function;
-    res = f();
+    int res = xbt_automaton_propositional_symbol_evaluate(ps);
     xbt_dynar_push_as(values, int, res);
   }
 
   return values;
 }
 
-
-static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){
-
-  int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
-  MC_SET_MC_HEAP;
-
+static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair)
+{
   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;
@@ -71,8 +68,6 @@ static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){
       // 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;
          } */
 
@@ -87,10 +82,6 @@ static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){
                 xbt_fifo_shift(mc_stack);
                 if (dot_output != NULL)
                   fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", initial_global_state->prev_pair, pair_test->num, initial_global_state->prev_req);
-
-                if (!raw_mem_set)
-                  MC_SET_STD_HEAP;
-
                 return NULL;
               }
             }
@@ -110,22 +101,12 @@ static mc_visited_pair_t is_reached_acceptance_pair(mc_pair_t pair){
           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;
@@ -146,9 +127,6 @@ static void remove_acceptance_pair(int pair_num) {
       MC_visited_pair_delete(pair_test);
 
   }
-
-  if (!raw_mem_set)
-    MC_SET_STD_HEAP;
 }
 
 
@@ -175,7 +153,7 @@ static int MC_automaton_evaluate_label(xbt_automaton_exp_label_t l,
       unsigned int cursor = 0;
       xbt_automaton_propositional_symbol_t p = NULL;
       xbt_dynar_foreach(_mc_property_automaton->propositional_symbols, cursor, p) {
-        if (strcmp(p->pred, l->u.predicat) == 0)
+        if (strcmp(xbt_automaton_propositional_symbol_get_name(p), l->u.predicat) == 0)
           return (int) xbt_dynar_get_as(atomic_propositions_values, cursor, int);
       }
       return -1;
@@ -188,17 +166,15 @@ static int MC_automaton_evaluate_label(xbt_automaton_exp_label_t l,
   }
 }
 
-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);
@@ -219,11 +195,11 @@ void MC_pre_modelcheck_liveness(void) {
       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;
@@ -232,18 +208,11 @@ void MC_pre_modelcheck_liveness(void) {
     }
   }
 
-  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;
@@ -262,9 +231,10 @@ void MC_modelcheck_liveness() {
     /* 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) {
 
@@ -288,16 +258,12 @@ void MC_modelcheck_liveness() {
       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{
@@ -305,7 +271,6 @@ void MC_modelcheck_liveness() {
         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);
@@ -315,11 +280,10 @@ void MC_modelcheck_liveness() {
            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 */
@@ -331,13 +295,11 @@ void MC_modelcheck_liveness() {
            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;
 
@@ -356,11 +318,11 @@ void MC_modelcheck_liveness() {
               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);
 
@@ -374,9 +336,7 @@ void MC_modelcheck_liveness() {
            }
            cursor--;
          }
-         
-         MC_SET_STD_HEAP;
-        
+
       } /* End of visited_pair test */
       
     } else {
@@ -385,18 +345,15 @@ void MC_modelcheck_liveness() {
       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;
@@ -408,10 +365,35 @@ void MC_modelcheck_liveness() {
           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);
+}
+
+}
index e0f102f..f7edd2e 100644 (file)
@@ -17,7 +17,7 @@
 
 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;
@@ -44,19 +44,18 @@ typedef struct s_mc_visited_pair{
   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()
 
index 45657f4..88841f2 100644 (file)
@@ -9,15 +9,16 @@
 
 #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()
 
@@ -76,16 +77,16 @@ enum mc_location_type mc_get_location_type(mc_location_t location) {
   }
 }
 
-void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
-void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
+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
 
@@ -103,14 +104,16 @@ typedef struct s_mc_expression_state {
 
   unw_cursor_t* cursor;
   void* frame_base;
-  mc_snapshot_t snapshot;
+  mc_address_space_t address_space;
   mc_object_info_t object_info;
   int process_index;
 } s_mc_expression_state_t, *mc_expression_state_t;
 
-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()
 
similarity index 89%
rename from src/mc/mc_member.c
rename to src/mc/mc_member.cpp
index b5ee069..a75a9af 100644 (file)
@@ -4,9 +4,13 @@
 /* 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
@@ -16,7 +20,7 @@
  * @return Process address of the given member of the 'object' struct/class
  */
 void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member,
-                        mc_snapshot_t snapshot, int process_index)
+                        mc_address_space_t address_space, int process_index)
 {
   if (!member->location.size) {
     return ((char *) base) + member->offset;
@@ -26,7 +30,7 @@ void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member,
   memset(&state, 0, sizeof(s_mc_expression_state_t));
   state.frame_base = NULL;
   state.cursor = NULL;
-  state.snapshot = snapshot;
+  state.address_space = address_space;
   state.stack_size = 1;
   state.stack[0] = (uintptr_t) base;
   state.process_index = process_index;
@@ -39,3 +43,5 @@ void *mc_member_resolve(const void *base, dw_type_t type, dw_type_t member,
   else
     return (void *) state.stack[state.stack_size - 1];
 }
+
+}
diff --git a/src/mc/mc_memory.c b/src/mc/mc_memory.c
deleted file mode 100644 (file)
index b474b0c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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);
-}
diff --git a/src/mc/mc_memory.cpp b/src/mc/mc_memory.cpp
new file mode 100644 (file)
index 0000000..fde3cd6
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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)
+{
+}
+
+}
index afa2b58..425d6d6 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef MC_MEMORY_MAP_H
 #define MC_MEMORY_MAP_H
 
+#include <sys/types.h>
+
 #include <simgrid_config.h>
 #include "mc_forward.h"
 
@@ -39,9 +41,8 @@ struct s_memory_map {
 
 };
 
-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()
 
index 4ceecbd..987bf89 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef MC_MMALLOC_H
 #define MC_MMALLOC_H
 
+#include <xbt/misc.h>
 #include <xbt/mmalloc.h>
 
 /** file
@@ -16,9 +17,8 @@
  *  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 */
@@ -32,7 +32,6 @@ extern xbt_mheap_t mc_heap;
 /*   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
index 6740829..71870e7 100644 (file)
 #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
@@ -38,7 +37,7 @@ size_t mc_page_count(size_t size)
  *  @return Virtual memory page number of the given address
  */
 static inline __attribute__ ((always_inline))
-size_t mc_page_number(void* base, void* address)
+size_t mc_page_number(const void* base, const void* address)
 {
   xbt_assert(address>=base, "The address is not in the range");
   return ((uintptr_t) address - (uintptr_t) base) >> xbt_pagebits;
@@ -50,7 +49,7 @@ size_t mc_page_number(void* base, void* address)
  *  @return Offset within the memory page
  */
 static inline __attribute__ ((always_inline))
-size_t mc_page_offset(void* address)
+size_t mc_page_offset(const void* address)
 {
   return ((uintptr_t) address) & (xbt_pagesize-1);
 }
@@ -61,13 +60,13 @@ size_t mc_page_offset(void* address)
  *  @param page Index of the page
  */
 static inline __attribute__ ((always_inline))
-void* mc_page_from_number(void* base, size_t page)
+void* mc_page_from_number(const void* base, size_t page)
 {
   return (void*) ((char*)base + (page << xbt_pagebits));
 }
 
 static inline __attribute__ ((always_inline))
-bool mc_same_page(void* a, void* b)
+bool mc_same_page(const void* a, const void* b)
 {
   return ((uintptr_t) a >> xbt_pagebits) == ((uintptr_t) b >> xbt_pagebits);
 }
diff --git a/src/mc/mc_model_checker.h b/src/mc/mc_model_checker.h
deleted file mode 100644 (file)
index 9ab2813..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
diff --git a/src/mc/mc_object_info.cpp b/src/mc/mc_object_info.cpp
new file mode 100644 (file)
index 0000000..95f9e2a
--- /dev/null
@@ -0,0 +1,48 @@
+/* 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;
+}
+
+}
index 2e0b68f..749c3e8 100644 (file)
@@ -12,6 +12,7 @@
 #define MC_OBJECT_INFO_H
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <simgrid_config.h>
 #include <xbt/dict.h>
@@ -19,6 +20,8 @@
 
 #include "mc_forward.h"
 #include "mc_location.h"
+#include "mc_process.h"
+#include "../smpi/private.h"
 
 SG_BEGIN_DECL();
 
@@ -44,20 +47,21 @@ struct s_dw_type {
   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
@@ -72,6 +76,18 @@ struct s_mc_object_info {
   xbt_dynar_t functions_index;
 };
 
+static inline __attribute__ ((always_inline))
+bool MC_object_info_executable(mc_object_info_t info)
+{
+  return info->flags & MC_OBJECT_INFO_EXECUTABLE;
+}
+
+static inline __attribute__ ((always_inline))
+bool MC_object_info_is_privatized(mc_object_info_t info)
+{
+  return info && MC_object_info_executable(info) && smpi_privatize_global_variables;
+}
+
 /** Find the DWARF offset for this ELF object
  *
  *  An offset is applied to address found in DWARF:
@@ -86,28 +102,26 @@ struct s_mc_object_info {
  *             + \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. */
@@ -143,7 +157,7 @@ struct s_mc_function_index_item {
   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()
 
index 5f0e601..72d71c1 100644 (file)
@@ -5,16 +5,15 @@
 /* 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:
@@ -23,35 +22,52 @@ extern "C" {
  *
  *  @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]);
   }
 }
 
@@ -63,118 +79,31 @@ void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count)
  *  @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");
@@ -182,43 +111,21 @@ mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* permanent
     "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);
 }
 
 }
similarity index 98%
rename from src/mc/mc_pair.c
rename to src/mc/mc_pair.cpp
index ee3ad5d..7f754cd 100644 (file)
@@ -8,6 +8,8 @@
 #include "mc_liveness.h"
 #include "mc_private.h"
 
+extern "C" {
+
 mc_pair_t MC_pair_new()
 {
   mc_pair_t p = NULL;
@@ -33,3 +35,5 @@ void mc_pair_free_voidp(void *p)
 {
   MC_pair_delete((mc_pair_t) * (void **) p);
 }
+
+}
index 997aca0..b5e564b 100644 (file)
@@ -7,6 +7,8 @@
 #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 ************************************/
@@ -79,11 +85,9 @@ typedef struct mc_stats {
   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 **********************************/
 
@@ -91,27 +95,23 @@ typedef struct s_mc_comparison_times{
   double nb_processes_comparison_time;
   double bytes_used_comparison_time;
   double stacks_sizes_comparison_time;
-  double binary_global_variables_comparison_time;
-  double libsimgrid_global_variables_comparison_time;
+  double global_variables_comparison_time;
   double heap_comparison_time;
   double stacks_comparison_time;
 }s_mc_comparison_times_t, *mc_comparison_times_t;
 
-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 **********************************/
 
@@ -122,16 +122,7 @@ typedef struct s_local_variable{
   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 *********** */
 
@@ -140,7 +131,7 @@ bool mc_address_test(mc_address_set_t p, const void* value);
  *  \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
  *
@@ -149,7 +140,11 @@ uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks);
  *
  *   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()
 
diff --git a/src/mc/mc_process.cpp b/src/mc/mc_process.cpp
new file mode 100644 (file)
index 0000000..1ebc9a7
--- /dev/null
@@ -0,0 +1,623 @@
+/* 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;
+    }
+  }
+}
+
+}
diff --git a/src/mc/mc_process.h b/src/mc/mc_process.h
new file mode 100644 (file)
index 0000000..666d5f3
--- /dev/null
@@ -0,0 +1,219 @@
+/* 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
diff --git a/src/mc/mc_protocol.cpp b/src/mc/mc_protocol.cpp
new file mode 100644 (file)
index 0000000..01c4f9d
--- /dev/null
@@ -0,0 +1,131 @@
+/* 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 "?";
+  }
+}
+
+}
diff --git a/src/mc/mc_protocol.h b/src/mc/mc_protocol.h
new file mode 100644 (file)
index 0000000..38c053c
--- /dev/null
@@ -0,0 +1,116 @@
+/* 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
similarity index 94%
rename from src/mc/mc_record.c
rename to src/mc/mc_record.cpp
index d9d79e1..6734597 100644 (file)
 
 #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");
 
@@ -72,7 +74,7 @@ xbt_dynar_t MC_record_from_string(const char* data)
     xbt_dynar_push(dynar, &item);
 
     // Find next chunk:
-    char* end = strchr(current, ';');
+    const char* end = strchr(current, ';');
     if(end==NULL)
       break;
     else
@@ -108,7 +110,8 @@ char* MC_record_stack_to_string(xbt_fifo_t stack)
     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) ? ";" : "";
@@ -144,3 +147,5 @@ void MC_record_replay_init()
 {
   mc_time = xbt_new0(double, simix_process_maxpid);
 }
+
+}
index 3ea2d77..1f7a677 100644 (file)
@@ -47,7 +47,7 @@ typedef struct s_mc_record_item {
 
 /** 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
 *
@@ -55,11 +55,11 @@ xbt_dynar_t MC_record_from_string(const char* data);
 * "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
 
@@ -68,15 +68,15 @@ void MC_record_dump_path(xbt_fifo_t stack);
  *  \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()
 
diff --git a/src/mc/mc_replay.h b/src/mc/mc_replay.h
new file mode 100644 (file)
index 0000000..2918305
--- /dev/null
@@ -0,0 +1,29 @@
+/* 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
diff --git a/src/mc/mc_request.c b/src/mc/mc_request.c
deleted file mode 100644 (file)
index 5c7d573..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/* 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;
-
-}
diff --git a/src/mc/mc_request.cpp b/src/mc/mc_request.cpp
new file mode 100644 (file)
index 0000000..4d0ebf4
--- /dev/null
@@ -0,0 +1,690 @@
+/* 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;
+
+}
+
+}
index 1bc9eb8..33642d4 100644 (file)
 
 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.
  *
@@ -26,16 +32,16 @@ int MC_request_is_visible(smx_simcall_t req);
  *  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()
 
similarity index 79%
rename from src/mc/mc_safety.c
rename to src/mc/mc_safety.cpp
index 38e0999..2e89053 100644 (file)
@@ -4,14 +4,20 @@
 /* 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 ");
 
@@ -32,24 +38,12 @@ static int is_exploration_stack_state(mc_state_t current_state){
 /**
  *  \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");
@@ -57,35 +51,29 @@ void MC_pre_modelcheck_safety()
   /* 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;
 
@@ -108,28 +96,25 @@ void MC_modelcheck_safety(void)
     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)){
@@ -140,13 +125,14 @@ void MC_modelcheck_safety(void)
       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);
@@ -163,8 +149,6 @@ void MC_modelcheck_safety(void)
       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 */
@@ -185,14 +169,10 @@ void MC_modelcheck_safety(void)
 
       }
 
-      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;
 
@@ -202,7 +182,6 @@ void MC_modelcheck_safety(void)
         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 
@@ -210,25 +189,26 @@ void MC_modelcheck_safety(void)
          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);
 
@@ -241,10 +221,11 @@ void MC_modelcheck_safety(void)
 
             } 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);
 
             }
@@ -263,11 +244,42 @@ void MC_modelcheck_safety(void)
           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();
+}
+
+}
index 183ebac..00e4a0f 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <simgrid_config.h>
 #include <xbt/dict.h>
-#include "mc_interface.h"
+#include "mc_forward.h"
 #include "mc_state.h"
 
 SG_BEGIN_DECL()
@@ -22,9 +22,8 @@ typedef enum {
   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{
@@ -35,10 +34,10 @@ 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()
 
diff --git a/src/mc/mc_server.cpp b/src/mc/mc_server.cpp
new file mode 100644 (file)
index 0000000..cf45be1
--- /dev/null
@@ -0,0 +1,367 @@
+/* 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();
+}
+
+}
diff --git a/src/mc/mc_server.h b/src/mc/mc_server.h
new file mode 100644 (file)
index 0000000..a6fc2f8
--- /dev/null
@@ -0,0 +1,60 @@
+/* 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
diff --git a/src/mc/mc_set.cpp b/src/mc/mc_set.cpp
deleted file mode 100644 (file)
index 03613c4..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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();
-}
-
-};
diff --git a/src/mc/mc_smx.cpp b/src/mc/mc_smx.cpp
new file mode 100644 (file)
index 0000000..ab32689
--- /dev/null
@@ -0,0 +1,235 @@
+/* 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;
+}
+
+}
diff --git a/src/mc/mc_smx.h b/src/mc/mc_smx.h
new file mode 100644 (file)
index 0000000..510bd2a
--- /dev/null
@@ -0,0 +1,103 @@
+/* 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
similarity index 63%
rename from src/mc/mc_snapshot.c
rename to src/mc/mc_snapshot.cpp
index 97c4017..7c587f9 100644 (file)
@@ -12,7 +12,9 @@
 #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;
@@ -65,7 +65,7 @@ mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int p
  *  @param size    Size of the data to read in bytes
  *  @return Pointer where the data is located (target buffer of original location)
  */
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size)
 {
   // Last byte of the memory area:
   void* end = (char*) addr + size - 1;
@@ -105,14 +105,15 @@ void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* targ
  *  @param size     Size of the data to read in bytes
  *  @return Pointer where the data is located (target buffer or original location)
  */
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size)
+const void* MC_snapshot_read(
+  mc_snapshot_t snapshot, adress_space_read_flags_t flags,
+  void* target, const void* addr, size_t size, int process_index)
 {
-  if (snapshot) {
-    mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
-    return mc_snapshot_read_region(addr, region, target, size);
-  } else {
-    return addr;
-  }
+  mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
+  if (region)
+    return MC_region_read(region, target, addr, size);
+  else
+    return MC_process_read(snapshot->process, flags, target, addr, size, process_index);
 }
 
 /** Compare memory between snapshots (with known regions)
@@ -123,18 +124,20 @@ void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, vo
  * @param snapshot2 Region of the address in the second snapshot
  * @return same as memcmp
  * */
-int mc_snapshot_region_memcmp(
-  void* addr1, mc_mem_region_t region1,
-  void* addr2, mc_mem_region_t region2,
+int MC_snapshot_region_memcmp(
+  const void* addr1, mc_mem_region_t region1,
+  const void* addr2, mc_mem_region_t region2,
   size_t size)
 {
   // Using alloca() for large allocations may trigger stack overflow:
   // use malloc if the buffer is too big.
   bool stack_alloc = size < 64;
-  void* buffer1a = (region1==NULL || region1->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
-  void* buffer2a = (region2==NULL || region2->data) ? NULL : stack_alloc ? alloca(size) : malloc(size);
-  void* buffer1 = mc_snapshot_read_region(addr1, region1, buffer1a, size);
-  void* buffer2 = mc_snapshot_read_region(addr2, region2, buffer2a, size);
+  const bool region1_need_buffer = region1==NULL || region1->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+  const bool region2_need_buffer = region2==NULL || region2->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
+  void* buffer1a = region1_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+  void* buffer2a = region2_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
+  const void* buffer1 = MC_region_read(region1, buffer1a, addr1, size);
+  const void* buffer2 = MC_region_read(region2, buffer2a, addr2, size);
   int res;
   if (buffer1 == buffer2) {
     res = 0;
@@ -156,13 +159,13 @@ int mc_snapshot_region_memcmp(
  * @param snapshot2 Second snapshot
  * @return same as memcmp
  * */
-int mc_snapshot_memcmp(
-  void* addr1, mc_snapshot_t snapshot1,
-  void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
+int MC_snapshot_memcmp(
+  const void* addr1, mc_snapshot_t snapshot1,
+  const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
 {
   mc_mem_region_t region1 = mc_get_snapshot_region(addr1, snapshot1, process_index);
   mc_mem_region_t region2 = mc_get_snapshot_region(addr2, snapshot2, process_index);
-  return mc_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
+  return MC_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
 }
 
 #ifdef SIMGRID_TEST
@@ -176,39 +179,37 @@ int mc_snapshot_memcmp(
 #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) {
 
@@ -219,56 +220,59 @@ static void test_snapshot(bool sparse_checkpoint) {
 
     // Init memory and take snapshots:
     init_memory(source, byte_size);
-    mc_mem_region_t region0 = mc_region_new_sparse(0, source, source, byte_size, NULL);
+    mc_mem_region_t region0 = mc_region_new_sparse(
+      MC_REGION_TYPE_UNKNOWN, source, source, byte_size);
     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);
     }
 
@@ -278,9 +282,12 @@ static void test_snapshot(bool sparse_checkpoint) {
     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 */
+
+}
index d393116..4d93f1c 100644 (file)
 #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.
@@ -52,23 +80,30 @@ typedef struct s_mc_mem_region{
    * */
   void *permanent_addr;
 
-  /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
-  void *data;
+  union {
+    struct {
+      /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
+      void *data;
+    } flat;
+    struct {
+      /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
+      size_t* page_numbers;
+    } chunked;
+    struct {
+      size_t regions_count;
+      mc_mem_region_t* regions;
+    } privatized;
+  };
 
-  /** @brief Size of the data region in bytes */
-  size_t size;
-
-  /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
-  size_t* page_numbers;
-
-} s_mc_mem_region_t, *mc_mem_region_t;
+};
 
-mc_mem_region_t mc_region_new_sparse(int type, void *start_addr, void* data_addr, size_t size, mc_mem_region_t ref_reg);
-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);
@@ -77,13 +112,15 @@ bool mc_region_contain(mc_mem_region_t region, void* p)
 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
  *
@@ -115,19 +152,30 @@ void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot, int process_i
     return (void *) addr;
   }
 
-  // Flat snapshot:
-  else if (region->data) {
-    uintptr_t offset = addr - (uintptr_t) region->start_addr;
-    return (void *) ((uintptr_t) region->data + offset);
-  }
+  switch (region->storage_type) {
+  case MC_REGION_STORAGE_TYPE_NONE:
+  default:
+    xbt_die("Storage type not supported");
+
+  case MC_REGION_STORAGE_TYPE_FLAT:
+    {
+      uintptr_t offset = addr - (uintptr_t) region->start_addr;
+      return (void *) ((uintptr_t) region->flat.data + offset);
+    }
 
-  // Per-page snapshot:
-  else if (region->page_numbers) {
+  case MC_REGION_STORAGE_TYPE_CHUNKED:
     return mc_translate_address_region(addr, region);
-  }
 
-  else {
-    xbt_die("No data for this memory region");
+  case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+    {
+      xbt_assert(process_index >=0,
+        "Missing process index for privatized region");
+      xbt_assert((size_t) process_index < region->privatized.regions_count,
+        "Out of range process index");
+      mc_mem_region_t subregion = region->privatized.regions[process_index];
+      xbt_assert(subregion, "Missing memory region for process %i", process_index);
+      return mc_translate_address(addr, snapshot, process_index);
+    }
   }
 }
 
@@ -151,11 +199,14 @@ typedef struct s_fd_infos{
   int flags;
 }s_fd_infos_t, *fd_infos_t;
 
-struct s_mc_snapshot{
+struct s_mc_snapshot {
+  mc_process_t process;
+  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;
@@ -166,18 +217,6 @@ struct s_mc_snapshot{
   fd_infos_t *current_fd;
 };
 
-/** @brief Process index used when no process is available
- *
- *  The expected behaviour is that if a process index is needed it will fail.
- * */
-#define MC_NO_PROCESS_INDEX -1
-
-/** @brief Process index when any process is suitable
- *
- * We could use a special negative value in the future.
- */
-#define MC_ANY_PROCESS_INDEX 0
-
 static inline __attribute__ ((always_inline))
 mc_mem_region_t mc_get_region_hinted(void* addr, mc_snapshot_t snapshot, int process_index, mc_mem_region_t region)
 {
@@ -203,13 +242,13 @@ typedef struct s_mc_stack_frame {
 
 typedef struct s_mc_snapshot_stack{
   xbt_dynar_t local_variables;
+  mc_unw_context_t context;
   xbt_dynar_t stack_frames; // mc_stack_frame_t
   int process_index;
 }s_mc_snapshot_stack_t, *mc_snapshot_stack_t;
 
-typedef struct s_mc_global_t{
+typedef struct s_mc_global_t {
   mc_snapshot_t snapshot;
-  int raw_mem_set;
   int prev_pair;
   char *prev_req;
   int initial_communications_pattern_done;
@@ -224,48 +263,46 @@ typedef struct s_mc_checkpoint_ignore_region{
   size_t size;
 }s_mc_checkpoint_ignore_region_t, *mc_checkpoint_ignore_region_t;
 
-static void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
+static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
 
-mc_snapshot_t MC_take_snapshot(int num_state);
-void MC_restore_snapshot(mc_snapshot_t);
-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
@@ -277,9 +314,10 @@ static inline __attribute__ ((always_inline))
  *  @return Pointer where the data is located (target buffer of original location)
  */
 static inline __attribute__((always_inline))
-void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read(mc_mem_region_t region, void* target, const void* addr, size_t size)
 {
   if (region==NULL)
+    // Should be deprecated:
     return addr;
 
   uintptr_t offset = (char*) addr - (char*) region->start_addr;
@@ -287,34 +325,39 @@ void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target,
   xbt_assert(mc_region_contain(region, addr),
     "Trying to read out of the region boundary.");
 
-  // Linear memory region:
-  if (region->data) {
-    return (char*) region->data + offset;
-  }
-
-  // Fragmented memory region:
-  else if (region->page_numbers) {
-    // Last byte of the region:
-    void* end = (char*) addr + size - 1;
-    if( mc_same_page(addr, end) ) {
-      // The memory is contained in a single page:
-      return mc_translate_address_region((uintptr_t) addr, region);
-    } else {
-      // The memory spans several pages:
-      return mc_snapshot_read_fragmented(addr, region, target, size);
+  switch (region->storage_type) {
+  case MC_REGION_STORAGE_TYPE_NONE:
+  default:
+    xbt_die("Storage type not supported");
+
+  case MC_REGION_STORAGE_TYPE_FLAT:
+    return (char*) region->flat.data + offset;
+
+  case MC_REGION_STORAGE_TYPE_CHUNKED:
+    {
+      // Last byte of the region:
+      void* end = (char*) addr + size - 1;
+      if (mc_same_page(addr, end) ) {
+        // The memory is contained in a single page:
+        return mc_translate_address_region((uintptr_t) addr, region);
+      } else {
+        // The memory spans several pages:
+        return MC_region_read_fragmented(region, target, addr, size);
+      }
     }
-  }
 
-  else {
-    xbt_die("No data available for this region");
+  // We currently do not pass the process_index to this function so we assume
+  // that the privatized region has been resolved in the callers:
+  case MC_REGION_STORAGE_TYPE_PRIVATIZED:
+    xbt_die("Storage type not supported");
   }
 }
 
 static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer_region(void* addr, mc_mem_region_t region)
+void* MC_region_read_pointer(mc_mem_region_t region, const void* addr)
 {
   void* res;
-  return *(void**) mc_snapshot_read_region(addr, region, &res, sizeof(void*));
+  return *(void**) MC_region_read(region, &res, addr, sizeof(void*));
 }
 
 SG_END_DECL()
diff --git a/src/mc/mc_state.c b/src/mc/mc_state.c
deleted file mode 100644 (file)
index 5830913..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/* 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, &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;
-}
diff --git a/src/mc/mc_state.cpp b/src/mc/mc_state.cpp
new file mode 100644 (file)
index 0000000..0ebde42
--- /dev/null
@@ -0,0 +1,284 @@
+/* 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;
+}
+
+}
index 863a21a..f44ac48 100644 (file)
@@ -13,7 +13,7 @@
 
 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 {
@@ -47,20 +47,21 @@ typedef struct mc_state {
   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()
 
diff --git a/src/mc/mc_unw.cpp b/src/mc/mc_unw.cpp
new file mode 100644 (file)
index 0000000..aa6eaea
--- /dev/null
@@ -0,0 +1,242 @@
+/* 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);
+}
+
+}
diff --git a/src/mc/mc_unw.h b/src/mc/mc_unw.h
new file mode 100644 (file)
index 0000000..8e87c84
--- /dev/null
@@ -0,0 +1,82 @@
+/* Copyright (c) 2015. The SimGrid Team.
+
+/ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef MC_UNW_H
+#define MC_UNW_H
+
+/** \file
+ *  Libunwind implementation for the model-checker
+ *
+ *  Libunwind provides an pluggable stack unwinding API: the way the current
+ *  registers and memory is accessed, the way unwinding informations is found
+ *  is pluggable.
+ *
+ *  This component implements the libunwind API for he model-checker:
+ *
+ *    * reading memory from a mc_address_space_t;
+ *
+ *    * reading stack registers from a saved snapshot (context).
+ *
+ *  Parts of the libunwind information fetching is currently handled by the
+ *  standard `libunwind` implementations (either the local one or the ptrace one)
+ *  because parsing `.eh_frame` section is not fun and `libdw` does not help
+ *  much here.
+ */
+
+#include "mc_process.h"
+
+SG_BEGIN_DECL()
+
+// ***** Libunwind namespace
+
+/** Virtual table for our `libunwind-process_vm_readv` implementation.
+ *
+ *  This implementation reuse most the code of `libunwind-ptrace` but
+ *  does not use ptrace() to read the target process memory by
+ *  `process_vm_readv()` or `/dev/${pid}/mem` if possible.
+ *
+ *  Does not support any MC-specific behaviour (privatisation, snapshots)
+ *  and `ucontext_t`.
+ *
+ *  It works with `void*` contexts allocated with `_UPT_create(pid)`.
+ */
+extern unw_accessors_t mc_unw_vmread_accessors;
+
+/** Virtual table for our `libunwind` implementation
+ *
+ *  Stack unwinding on a `mc_process_t` (for memory, unwinding information)
+ *  and `ucontext_t` (for processor registers).
+ *
+ *  It works with the `s_mc_unw_context_t` context.
+ */
+extern 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
diff --git a/src/mc/mc_unw_vmread.cpp b/src/mc/mc_unw_vmread.cpp
new file mode 100644 (file)
index 0000000..fa1c2d2
--- /dev/null
@@ -0,0 +1,115 @@
+/* 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
+  };
+
+}
similarity index 91%
rename from src/mc/mc_visited.c
rename to src/mc/mc_visited.cpp
index f792c80..bd6cb0a 100644 (file)
 #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");
@@ -51,10 +55,20 @@ void visited_state_free_voidp(void *s)
  */
 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;
@@ -63,13 +77,22 @@ static mc_visited_state_t visited_state_new()
 
 mc_visited_pair_t MC_visited_pair_new(int pair_num, xbt_automaton_state_t automaton_state, xbt_dynar_t atomic_propositions, mc_state_t graph_state)
 {
+  mc_process_t process = &(mc_model_checker->process());
   mc_visited_pair_t pair = NULL;
   pair = xbt_new0(s_mc_visited_pair_t, 1);
   pair->graph_state = graph_state;
   if(pair->graph_state->system_state == NULL)
     pair->graph_state->system_state = MC_take_snapshot(pair_num);
-  pair->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
-  pair->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;
@@ -124,12 +147,7 @@ void MC_visited_pair_delete(mc_visited_pair_t p)
  */
 int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max)
 {
-
-  int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
-  MC_SET_MC_HEAP;
-
-  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;
 
@@ -182,7 +200,7 @@ int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max)
           *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);
@@ -198,16 +216,10 @@ int get_search_interval(xbt_dynar_t list, void *ref, int *min, int *max)
           *max = next_cursor;
           next_cursor++;
         }
-        if (!mc_mem_set)
-          MC_SET_STD_HEAP;
         return -1;
       }
     }
   }
-
-  if (!mc_mem_set)
-    MC_SET_STD_HEAP;
-
   return cursor;
 }
 
@@ -228,8 +240,8 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
      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;
@@ -239,10 +251,6 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
     }
   }
 
-  int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
-  MC_SET_MC_HEAP;
-
   mc_visited_state_t new_state = visited_state_new();
   graph_state->system_state = new_state->system_state;
   graph_state->in_visited_states = 1;
@@ -251,10 +259,6 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
   if (xbt_dynar_is_empty(visited_states)) {
 
     xbt_dynar_push(visited_states, &new_state);
-
-    if (!mc_mem_set)
-      MC_SET_STD_HEAP;
-
     return NULL;
 
   } else {
@@ -282,12 +286,11 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
          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) {
@@ -311,8 +314,6 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
             xbt_dynar_insert_at(visited_states, cursor, &new_state);
             XBT_DEBUG("Replace visited state %d with the new visited state %d", state_test->num, new_state->num);
 
-            if (!mc_mem_set)
-              MC_SET_STD_HEAP;
             return state_test;
           }
           cursor++;
@@ -340,7 +341,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
     }
 
     // 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)");
 
@@ -349,7 +350,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
       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;
         }
@@ -360,11 +361,7 @@ mc_visited_state_t is_visited_state(mc_state_t graph_state)
       XBT_DEBUG("Remove visited state (maximum number of stored states reached)");
     }
 
-    if (!mc_mem_set)
-      MC_SET_STD_HEAP;
-
     return NULL;
-
   }
 }
 
@@ -376,10 +373,6 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) {
   if (_sg_mc_visited == 0)
     return -1;
 
-  int mc_mem_set = (mmalloc_get_current_heap() == mc_heap);
-
-  MC_SET_MC_HEAP;
-
   mc_visited_pair_t new_visited_pair = NULL;
 
   if (visited_pair == NULL) {
@@ -425,8 +418,6 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) {
          MC_pair_delete(pair_test);
          }
          }
-         if(!raw_mem_set)
-         MC_SET_STD_HEAP;
          return pair->other_num;
          } */
       cursor = min;
@@ -452,8 +443,6 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) {
               } else {
                 MC_visited_pair_delete(pair_test);
               }
-              if (!mc_mem_set)
-                MC_SET_STD_HEAP;
               return new_visited_pair->other_num;
             }
           }
@@ -473,12 +462,12 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) {
       }
     }
 
-    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;
         }
@@ -494,9 +483,7 @@ int is_visited_pair(mc_visited_pair_t visited_pair, mc_pair_t pair) {
     }
 
   }
-
-  if (!mc_mem_set)
-    MC_SET_STD_HEAP;
-
   return -1;
 }
+
+}
similarity index 56%
rename from src/mc/mc_ignore.c
rename to src/mc/mcer_ignore.cpp
index 13cab5e..54d2da2 100644 (file)
@@ -1,4 +1,4 @@
-/* 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
@@ -6,38 +6,21 @@
 
 #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)
 {
@@ -49,51 +32,14 @@ void heap_ignore_region_free_voidp(void *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, &region);
-    if (!raw_mem_set)
-      MC_SET_STD_HEAP;
     return;
   }
 
@@ -102,40 +48,32 @@ void MC_ignore_heap(void *address, size_t size)
   int start = 0;
   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
 
+  // Find the position where we want to insert the mc_heap_ignore_region_t:
   while (start <= end) {
     cursor = (start + end) / 2;
     current_region =
         (mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
                                                    cursor,
                                                    mc_heap_ignore_region_t);
-    if (current_region->address == address) {
+    if (current_region->address == region->address) {
       heap_ignore_region_free(region);
-      if (!raw_mem_set)
-        MC_SET_STD_HEAP;
       return;
-    } else if (current_region->address < address) {
+    } else if (current_region->address < region->address) {
       start = cursor + 1;
     } else {
       end = cursor - 1;
     }
   }
 
-  if (current_region->address < address)
+  // Insert it mc_heap_ignore_region_t:
+  if (current_region->address < region->address)
     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
   else
     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
-
-  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;
@@ -167,44 +105,73 @@ void MC_remove_ignore_heap(void *address, size_t size)
     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
     MC_remove_ignore_heap(address, size);
   }
-
-  if (!raw_mem_set)
-    MC_SET_STD_HEAP;
-
 }
 
-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
@@ -225,7 +192,7 @@ static void mc_ignore_local_variable_in_scope(const char *var_name,
 {
   // Processing of direct variables:
 
-  // If the current subprogram matche the given name:
+  // If the current subprogram matches the given name:
   if (!subprogram_name ||
       (subprogram->name && strcmp(subprogram_name, subprogram->name) == 0)) {
 
@@ -271,117 +238,52 @@ static void mc_ignore_local_variable_in_scope(const char *var_name,
   }
 }
 
-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, &region);
-
-  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, &region);
+  if (xbt_dynar_is_empty(checkpoint_ignore)) {
+    xbt_dynar_push(checkpoint_ignore, &region);
   } else {
 
     unsigned int cursor = 0;
     int start = 0;
-    int end = xbt_dynar_length(mc_checkpoint_ignore) - 1;
+    int end = xbt_dynar_length(checkpoint_ignore) - 1;
     mc_checkpoint_ignore_region_t current_region = NULL;
 
     while (start <= end) {
       cursor = (start + end) / 2;
       current_region =
-          (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(mc_checkpoint_ignore,
+          (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(checkpoint_ignore,
                                                            cursor,
                                                            mc_checkpoint_ignore_region_t);
       if (current_region->addr == addr) {
         if (current_region->size == size) {
           checkpoint_ignore_region_free(region);
-          if (!raw_mem_set)
-            MC_SET_STD_HEAP;
           return;
         } else if (current_region->size < size) {
           start = cursor + 1;
@@ -397,17 +299,25 @@ void MC_ignore(void *addr, size_t size)
 
     if (current_region->addr == addr) {
       if (current_region->size < size) {
-        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
+        xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, &region);
       } else {
-        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
+        xbt_dynar_insert_at(checkpoint_ignore, cursor, &region);
       }
     } else if (current_region->addr < addr) {
-      xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
+      xbt_dynar_insert_at(checkpoint_ignore, cursor + 1, &region);
     } else {
-      xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
+      xbt_dynar_insert_at(checkpoint_ignore, cursor, &region);
     }
   }
+}
+
+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;
 }
diff --git a/src/mc/mcer_ignore.h b/src/mc/mcer_ignore.h
new file mode 100644 (file)
index 0000000..1c56b62
--- /dev/null
@@ -0,0 +1,20 @@
+/* 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();
similarity index 80%
rename from src/mc/memory_map.c
rename to src/mc/memory_map.cpp
index b867a86..db0fcce 100644 (file)
@@ -4,41 +4,37 @@
 /* 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);
@@ -48,8 +44,10 @@ memory_map_t MC_get_memory_map(void)
 
     /* Tokenize the line using spaces as delimiters and store each token */
     /* in lfields array. We expect 5 tokens/fields */
+    char* lfields[6];
     lfields[0] = strtok(line, " ");
 
+    int i;
     for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
       lfields[i] = strtok(NULL, " ");
     }
@@ -60,10 +58,12 @@ memory_map_t MC_get_memory_map(void)
 
     /* Ok we are good enough to try to get the info we need */
     /* First get the start and the end address of the map   */
-    tok = strtok(lfields[0], "-");
+    char *tok = strtok(lfields[0], "-");
     if (tok == NULL)
       xbt_abort();
 
+    s_map_region_t memreg;          /* temporal map region used for creating the map */
+    char *endptr;
     memreg.start_addr = (void *) strtoul(tok, &endptr, 16);
     /* Make sure that the entire string was an hex number */
     if (*endptr != '\0')
@@ -143,7 +143,9 @@ memory_map_t MC_get_memory_map(void)
 
     /* Create space for a new map region in the region's array and copy the */
     /* parsed stuff from the temporal memreg variable */
-    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++;
@@ -151,9 +153,7 @@ memory_map_t MC_get_memory_map(void)
   }
 
   free(line);
-
   fclose(fp);
-
   return ret;
 }
 
@@ -166,3 +166,5 @@ void MC_free_memory_map(memory_map_t map){
   xbt_free(map->regions);
   xbt_free(map);
 }
+
+}
diff --git a/src/mc/simgrid_mc.cpp b/src/mc/simgrid_mc.cpp
new file mode 100644 (file)
index 0000000..1d517f1
--- /dev/null
@@ -0,0 +1,171 @@
+  /* 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;
+}
index b9351e8..6deb895 100644 (file)
@@ -122,7 +122,7 @@ msg_error_t MSG_main(void)
   fflush(stderr);
 
   if (MC_is_active()) {
-    MC_do_the_modelcheck_for_real();
+    MC_run();
   } else {
     SIMIX_run();
   }
index cffff60..4a3f158 100644 (file)
@@ -163,7 +163,6 @@ msg_error_t
 MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
                              double timeout)
 {
-  xbt_ex_t e;
   msg_error_t ret = MSG_OK;
   simdata_task_t t_simdata = NULL;
   msg_process_t process = MSG_process_self();
@@ -198,6 +197,7 @@ MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
 
   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  */
index 3a38913..d78beb5 100644 (file)
@@ -153,7 +153,7 @@ msg_process_t MSG_process_create_with_environment(const char *name,
                                                 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;
 
@@ -237,7 +237,7 @@ msg_error_t MSG_process_migrate(msg_process_t process, msg_host_t host)
  */
 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);
@@ -252,7 +252,7 @@ void* MSG_process_get_data(msg_process_t 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;
@@ -350,7 +350,7 @@ int MSG_process_get_PID(msg_process_t process)
  */
 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);
 }
@@ -363,7 +363,7 @@ int MSG_process_get_PPID(msg_process_t 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);
 }
@@ -388,7 +388,7 @@ const char *MSG_process_get_property_value(msg_process_t 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);
 
@@ -433,7 +433,7 @@ msg_process_t MSG_process_self(void)
  */
 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);
@@ -448,7 +448,7 @@ msg_error_t MSG_process_suspend(msg_process_t 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);
@@ -463,7 +463,7 @@ msg_error_t MSG_process_resume(msg_process_t 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);
 }
 
index 24afd32..be3fcb8 100644 (file)
@@ -52,7 +52,7 @@
 #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
@@ -69,7 +69,7 @@ typedef uint32_t flex_uint32_t;
 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;
 
@@ -195,7 +195,7 @@ extern FILE *dax_in, *dax_out;
 
     /* 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.
@@ -214,7 +214,7 @@ extern FILE *dax_in, *dax_out;
                     if ( *p == '\n' )\
                         --dax_lineno;\
             }while(0)
-    
+
 /* Return all but the first "n" matched characters back to the input stream. */
 #define yyless(n) \
        do \
@@ -271,7 +271,7 @@ struct yy_buffer_state
 
     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.
         */
@@ -1239,13 +1239,13 @@ static yyconst flex_int16_t yy_chk[2224] =
 /* 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;
@@ -1268,13 +1268,13 @@ char *dax_text;
  * 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.
  *
@@ -1292,20 +1292,20 @@ char *dax_text;
  * 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. */
@@ -1318,7 +1318,7 @@ const char dax__flexml_version[] = "1.9.6";
 #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>
@@ -1327,7 +1327,7 @@ const char dax__flexml_version[] = "1.9.6";
 #else
 # include <unistd.h>
 #endif
-     
+
 #ifndef FLEXML_INDEXSTACKSIZE
 #define FLEXML_INDEXSTACKSIZE 1000
 #endif
@@ -1527,7 +1527,7 @@ static void pushbuffer(int p)
 {
     ck_ilimit();
     indexstack[inext++] = p;
-    indexstack[inext++] = bnext;    
+    indexstack[inext++] = bnext;
 }
 
 static int popbuffer(void)
@@ -1685,11 +1685,11 @@ static int input (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__
@@ -1794,10 +1794,10 @@ extern int dax_lex (void);
  */
 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;
@@ -1904,7 +1904,7 @@ YY_DECL
 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;
@@ -1937,7 +1937,7 @@ yy_find_action:
                        yy_size_t yyl;
                        for ( yyl = 0; yyl < dax_leng; ++yyl )
                                if ( dax_text[yyl] == '\n' )
-                                          
+
     dax_lineno++;
 ;
                        }
@@ -2002,7 +2002,7 @@ SKIP;
 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 */
@@ -2961,9 +2961,9 @@ case YY_STATE_EOF(IMPOSSIBLE):
  */
 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] )
@@ -3095,14 +3095,14 @@ static int yy_get_next_buffer (void)
 
     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;
@@ -3127,10 +3127,10 @@ static int yy_get_next_buffer (void)
  */
     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;
@@ -3157,7 +3157,7 @@ static int yy_get_next_buffer (void)
 
 {
        int c;
-    
+
        *(yy_c_buf_p) = (yy_hold_char);
 
        if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
@@ -3219,7 +3219,7 @@ static int yy_get_next_buffer (void)
        (yy_hold_char) = *++(yy_c_buf_p);
 
        if ( c == '\n' )
-                  
+
     dax_lineno++;
 ;
 
@@ -3229,12 +3229,12 @@ static int yy_get_next_buffer (void)
 
 /** 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 =
@@ -3247,11 +3247,11 @@ static int yy_get_next_buffer (void)
 
 /** 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();
@@ -3291,13 +3291,13 @@ static void dax__load_buffer_state  (void)
 /** 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()" );
@@ -3320,11 +3320,11 @@ static void dax__load_buffer_state  (void)
 
 /** Destroy the buffer.
  * @param b a buffer created with dax__create_buffer()
- * 
+ *
  */
     void dax__delete_buffer (YY_BUFFER_STATE  b )
 {
-    
+
        if ( ! b )
                return;
 
@@ -3345,7 +3345,7 @@ static void dax__load_buffer_state  (void)
 
 {
        int oerrno = errno;
-    
+
        dax__flush_buffer(b );
 
        b->yy_input_file = file;
@@ -3361,13 +3361,13 @@ static void dax__load_buffer_state  (void)
     }
 
         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 )
 {
@@ -3396,7 +3396,7 @@ static void dax__load_buffer_state  (void)
  *  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 )
 {
@@ -3426,7 +3426,7 @@ 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)
 {
@@ -3450,7 +3450,7 @@ 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
@@ -3463,9 +3463,9 @@ static void dax_ensure_buffer_stack (void)
                                                                );
                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;
@@ -3493,13 +3493,13 @@ static void dax_ensure_buffer_stack (void)
 /** 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 )
@@ -3528,14 +3528,14 @@ YY_BUFFER_STATE dax__scan_buffer  (char * base, yy_size_t  size )
 /** 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) );
 }
 
@@ -3543,7 +3543,7 @@ YY_BUFFER_STATE dax__scan_string (yyconst char * 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 )
@@ -3552,7 +3552,7 @@ YY_BUFFER_STATE dax__scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_le
        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  );
@@ -3638,16 +3638,16 @@ static void yy_fatal_error (yyconst char* msg )
 /* 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)
 {
@@ -3655,7 +3655,7 @@ FILE *dax_get_in  (void)
 }
 
 /** Get the output stream.
- * 
+ *
  */
 FILE *dax_get_out  (void)
 {
@@ -3663,7 +3663,7 @@ FILE *dax_get_out  (void)
 }
 
 /** Get the length of the current token.
- * 
+ *
  */
 yy_size_t dax_get_leng  (void)
 {
@@ -3671,7 +3671,7 @@ yy_size_t dax_get_leng  (void)
 }
 
 /** Get the current token.
- * 
+ *
  */
 
 char *dax_get_text  (void)
@@ -3681,18 +3681,18 @@ 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 )
@@ -3723,7 +3723,7 @@ static int yy_init_globals (void)
 
     /* 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;
@@ -3753,7 +3753,7 @@ static int yy_init_globals (void)
 /* 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  );
@@ -3783,7 +3783,7 @@ int dax_lex_destroy  (void)
 #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];
 }
@@ -3792,7 +3792,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s )
 {
-       register int n;
+       int n;
        for ( n = 0; s[n]; ++n )
                ;
 
index ac0f9bb..763192e 100644 (file)
@@ -22,6 +22,7 @@
 #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");
@@ -649,12 +650,6 @@ void sg_config_init(int *argc, char **argv)
                      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.",
@@ -691,6 +686,12 @@ void sg_config_init(int *argc, char **argv)
                      xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_hash, NULL);
     xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/hash", "no");
 
+    /* Set max depth exploration */
+    xbt_cfg_register(&_sg_cfg_set, "model-check/snapshot_fds",
+                     "Whether file descriptors must be snapshoted",
+                     xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_snapshot_fds, NULL);
+    xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/snapshot_fds", "no");
+
     /* Set max depth exploration */
     xbt_cfg_register(&_sg_cfg_set, "model-check/max_depth",
                      "Specify the max depth of exploration (default : 1000)",
@@ -955,6 +956,11 @@ void sg_config_init(int *argc, char **argv)
                      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);
@@ -964,7 +970,7 @@ void sg_config_init(int *argc, char **argv)
       /* 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);
index d5a78fa..0ff35b7 100644 (file)
 /* 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);
 
@@ -755,7 +757,7 @@ void simcall_process_set_kill_time(smx_process_t process, double kill_time)
     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);
     }
   }
 }
index 7b4a39c..a5fa70d 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 #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) {
index 46e54ef..452379c 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "smx_private.h"
 #ifdef HAVE_MC
+#include "mc/mc_process.h"
 #endif
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);
index 8eefe72..dc8c59d 100644 (file)
@@ -13,7 +13,7 @@ SG_BEGIN_DECL()
 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);
index 41bd69d..15d7c99 100755 (executable)
@@ -281,7 +281,7 @@ if __name__=='__main__':
   
   fd.write('#include "smx_private.h"\n');
   fd.write('#ifdef HAVE_MC\n');
-  # fd.write('#include "mc/mc_private.h"\n');
+  fd.write('#include "mc/mc_process.h"\n');
   fd.write('#endif\n');
   fd.write('\n');
   fd.write('XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_popping);\n\n');
@@ -328,7 +328,7 @@ if __name__=='__main__':
   ###
   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()
index e074c52..cedbd51 100644 (file)
@@ -152,10 +152,12 @@ smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
       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;
 }
index fbde818..1995a3f 100644 (file)
@@ -188,6 +188,7 @@ static void smx_ctx_thread_runall_serial(void)
   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);
   }
index cb99d35..afbc67c 100644 (file)
@@ -4,6 +4,8 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include <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"
 
@@ -206,6 +211,19 @@ void SIMIX_global_init(int *argc, char **argv)
   if (sg_cfg_get_boolean("clean_atexit"))
     atexit(SIMIX_clean);
 
+#ifdef HAVE_MC
+  // The communication initialisation is done ASAP.
+  // We need to commuicate  initialisation of the different layers to the model-checker.
+  if (mc_mode == MC_MODE_NONE) {
+    if (getenv(MC_ENV_SOCKET_FD)) {
+      mc_mode = MC_MODE_CLIENT;
+      MC_client_init();
+      MC_client_hello();
+      MC_client_handle_messages();
+    }
+  }
+#endif
+
   if (_sg_cfg_exit_asap)
     exit(0);
 }
@@ -404,12 +422,30 @@ void SIMIX_run(void)
           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 */
@@ -426,14 +462,19 @@ void SIMIX_run(void)
 
     /* 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 */
@@ -473,7 +514,7 @@ void SIMIX_run(void)
  *   \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);
 
@@ -481,6 +522,16 @@ XBT_INLINE void SIMIX_timer_set(double date, void *function, void *arg)
   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;
 }
 
 /**
index be58fe5..20e7abb 100644 (file)
@@ -9,6 +9,7 @@
 #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");
index 942deb5..fbeb548 100644 (file)
@@ -7,10 +7,10 @@
 #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");
 
index b0c51cd..21a4ef8 100644 (file)
@@ -9,6 +9,8 @@
 #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)");
@@ -48,6 +50,10 @@ void SIMIX_process_cleanup(smx_process_t 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))) {
@@ -86,6 +92,7 @@ void SIMIX_process_cleanup(smx_process_t process)
     }
   }
 
+  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);
@@ -103,6 +110,8 @@ void SIMIX_process_empty_trash(void)
   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 */
@@ -153,7 +162,7 @@ void SIMIX_process_stop(smx_process_t arg) {
   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);
   }
@@ -256,7 +265,6 @@ void SIMIX_process_create(smx_process_t *process,
     (*process)->code = code;
     (*process)->argc = argc;
     (*process)->argv = argv;
-    (*process)->kill_time = kill_time;
 
 
     XBT_VERB("Create context %s", (*process)->name);
@@ -286,7 +294,7 @@ void SIMIX_process_create(smx_process_t *process,
     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);
     }
   }
 }
@@ -367,6 +375,7 @@ void SIMIX_process_kill(smx_process_t process, smx_process_t issuer) {
     }
   }
   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);
   }
 
@@ -400,11 +409,12 @@ void SIMIX_process_throw(smx_process_t process, xbt_errcat_t cat, int value, con
       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:
@@ -419,8 +429,6 @@ void SIMIX_process_throw(smx_process_t process, xbt_errcat_t cat, int value, con
   }
   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) {
@@ -948,18 +956,15 @@ void SIMIX_process_auto_restart_set(smx_process_t process, int auto_restart) {
 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;
index 8b4f8ed..b3cd4bc 100644 (file)
@@ -58,8 +58,7 @@ typedef struct s_smx_process {
   xbt_main_func_t code;
   int argc;
   char **argv;
-  double kill_time;
-
+  smx_timer_t kill_timer;
 } s_smx_process_t;
 
 
index 921eaf0..e293606 100644 (file)
@@ -3,11 +3,11 @@
 
 /* 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>
@@ -301,7 +301,7 @@ Benchmark results on CRAY T3E
    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
@@ -413,8 +413,8 @@ typedef enum {MPIM_SHORT, MPIM_INT, MPIM_LONG, MPIM_UNSIGNED_SHORT,
               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)\
@@ -505,8 +505,8 @@ static int MPI_I_anyReduce(void* Sendbuf, void* Recvbuf, int count, MPI_Datatype
   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;
@@ -516,7 +516,7 @@ static int MPI_I_anyReduce(void* Sendbuf, void* Recvbuf, int count, MPI_Datatype
   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;
@@ -531,10 +531,10 @@ static int MPI_I_anyReduce(void* Sendbuf, void* Recvbuf, int count, MPI_Datatype
   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) {
index a981757..a6d4189 100644 (file)
@@ -447,8 +447,8 @@ int smpi_type_keyval_free(int* keyval);
 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);
@@ -766,11 +766,11 @@ const char* encode_datatype(MPI_Datatype datatype, int* known);
 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);
 
index bc7ac71..af7deeb 100644 (file)
@@ -7,6 +7,7 @@
 #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"
@@ -456,11 +457,11 @@ void smpi_mpi_start(MPI_Request request)
         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);
@@ -694,8 +695,8 @@ static void finish_wait(MPI_Request * request, MPI_Status * status)
     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());
index 79179a7..b6b56e8 100644 (file)
@@ -13,6 +13,7 @@
 #include "surf/surf.h"
 #include "simgrid/sg_config.h"
 #include "simgrid/modelchecker.h"
+#include "mc/mc_replay.h"
 
 #ifndef WIN32
 #include <sys/mman.h>
@@ -75,12 +76,10 @@ double smpi_cpu_threshold;
 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 {
@@ -619,23 +618,26 @@ void smpi_switch_data_segment(int dest){
  */
 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
 }
 
@@ -697,12 +699,12 @@ void smpi_get_executable_global_size(){
     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++;
        }
@@ -711,7 +713,9 @@ void smpi_get_executable_global_size(){
 
   }
 
-  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);
@@ -728,9 +732,10 @@ void smpi_initialize_global_memory_segments(){
   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;
   }
@@ -769,17 +774,17 @@ Ask the Internet about tutorials on how to increase the files limit such as: htt
       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;
@@ -791,12 +796,12 @@ Ask the Internet about tutorials on how to increase the files limit such as: htt
 }
 
 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));
     }
index c06b16d..e2df67d 100644 (file)
@@ -18,7 +18,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_comm, smpi,
                                 "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
@@ -617,4 +617,3 @@ int smpi_comm_keyval_free(int* keyval){
   xbt_free(elem);
   return MPI_SUCCESS;
 }
-
index 4e8202c..ebddf58 100644 (file)
@@ -12,6 +12,7 @@
 #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>
@@ -43,11 +44,11 @@ typedef struct s_smpi_process_data {
 
 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;
@@ -350,8 +351,8 @@ void smpi_comm_copy_buffer_callback(smx_synchro_t comm,
   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);
@@ -361,8 +362,8 @@ void smpi_comm_copy_buffer_callback(smx_synchro_t comm,
 
 
   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);
@@ -425,6 +426,7 @@ void smpi_global_init(void)
     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);
@@ -452,9 +454,9 @@ void smpi_global_init(void)
   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;
@@ -666,7 +668,7 @@ int smpi_main(int (*realmain) (int argc, char *argv[]), int argc, char *argv[])
   fflush(stderr);
 
   if (MC_is_active()) {
-    MC_do_the_modelcheck_for_real();
+    MC_run();
   } else {
   
     SIMIX_run();
index 75e2edd..cc3bdb9 100644 (file)
@@ -3094,20 +3094,47 @@ int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
 }
 
 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) {
@@ -3635,4 +3662,3 @@ int PMPI_Win_test(MPI_Win win, int *flag){
 int PMPI_Win_unlock(int rank, MPI_Win win){
   NOT_YET_IMPLEMENTED
 }
-
index de303c9..9c9854c 100644 (file)
@@ -51,7 +51,7 @@ static void IB_action_init_callback(NetworkActionPtr action,RoutingEdgePtr src,
     xbt_die("could not find dst node active comms !");  
  // act_dst->rate=rate;
   
-  ((NetworkIBModel*)surf_network_model)->active_comms[action]=make_pair<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);
 
index c110244..6f257cc 100644 (file)
@@ -52,7 +52,7 @@
 #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
@@ -69,7 +69,7 @@ typedef uint32_t flex_uint32_t;
 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;
 
@@ -195,7 +195,7 @@ extern FILE *surf_parse_in, *surf_parse_out;
 
     /* 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.
@@ -214,7 +214,7 @@ extern FILE *surf_parse_in, *surf_parse_out;
                     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 \
@@ -271,7 +271,7 @@ struct yy_buffer_state
 
     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.
         */
@@ -4554,35 +4554,35 @@ static yyconst flex_int16_t yy_chk[12714] =
 /* 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;
@@ -4605,13 +4605,13 @@ char *surf_parse_text;
  * 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.
  *
@@ -4629,20 +4629,20 @@ char *surf_parse_text;
  * 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. */
@@ -4655,7 +4655,7 @@ const char surfxml_flexml_version[] = "1.9.6";
 #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>
@@ -4664,7 +4664,7 @@ const char surfxml_flexml_version[] = "1.9.6";
 #else
 # include <unistd.h>
 #endif
-     
+
 #ifndef FLEXML_INDEXSTACKSIZE
 #define FLEXML_INDEXSTACKSIZE 1000
 #endif
@@ -5149,7 +5149,7 @@ static void pushbuffer(int p)
 {
     ck_ilimit();
     indexstack[inext++] = p;
-    indexstack[inext++] = bnext;    
+    indexstack[inext++] = bnext;
 }
 
 static int popbuffer(void)
@@ -5405,11 +5405,11 @@ static int input (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__
@@ -5514,10 +5514,10 @@ extern int surf_parse_lex (void);
  */
 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;
@@ -5727,7 +5727,7 @@ YY_DECL
 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;
@@ -5760,7 +5760,7 @@ yy_find_action:
                        yy_size_t yyl;
                        for ( yyl = 0; yyl < surf_parse_leng; ++yyl )
                                if ( surf_parse_text[yyl] == '\n' )
-                                          
+
     surf_parse_lineno++;
 ;
                        }
@@ -5825,7 +5825,7 @@ SKIP;
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-SET(DOCTYPE); 
+SET(DOCTYPE);
        YY_BREAK
 case 12:
 /* rule 12 can match eol */
@@ -9890,9 +9890,9 @@ case YY_STATE_EOF(IMPOSSIBLE):
  */
 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] )
@@ -10024,14 +10024,14 @@ static int yy_get_next_buffer (void)
 
     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;
@@ -10056,10 +10056,10 @@ static int yy_get_next_buffer (void)
  */
     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;
@@ -10086,7 +10086,7 @@ static int yy_get_next_buffer (void)
 
 {
        int c;
-    
+
        *(yy_c_buf_p) = (yy_hold_char);
 
        if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
@@ -10148,7 +10148,7 @@ static int yy_get_next_buffer (void)
        (yy_hold_char) = *++(yy_c_buf_p);
 
        if ( c == '\n' )
-                  
+
     surf_parse_lineno++;
 ;
 
@@ -10158,12 +10158,12 @@ static int yy_get_next_buffer (void)
 
 /** 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 =
@@ -10176,11 +10176,11 @@ static int yy_get_next_buffer (void)
 
 /** 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();
@@ -10220,13 +10220,13 @@ static void surf_parse__load_buffer_state  (void)
 /** 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()" );
@@ -10249,11 +10249,11 @@ static void surf_parse__load_buffer_state  (void)
 
 /** 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;
 
@@ -10274,7 +10274,7 @@ static void surf_parse__load_buffer_state  (void)
 
 {
        int oerrno = errno;
-    
+
        surf_parse__flush_buffer(b );
 
        b->yy_input_file = file;
@@ -10290,13 +10290,13 @@ static void surf_parse__load_buffer_state  (void)
     }
 
         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 )
 {
@@ -10325,7 +10325,7 @@ static void surf_parse__load_buffer_state  (void)
  *  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 )
 {
@@ -10355,7 +10355,7 @@ 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)
 {
@@ -10379,7 +10379,7 @@ 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
@@ -10392,9 +10392,9 @@ static void surf_parse_ensure_buffer_stack (void)
                                                                );
                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;
@@ -10422,13 +10422,13 @@ static void surf_parse_ensure_buffer_stack (void)
 /** 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 )
@@ -10457,14 +10457,14 @@ YY_BUFFER_STATE surf_parse__scan_buffer  (char * base, yy_size_t  size )
 /** 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) );
 }
 
@@ -10472,7 +10472,7 @@ YY_BUFFER_STATE surf_parse__scan_string (yyconst char * 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 )
@@ -10481,7 +10481,7 @@ YY_BUFFER_STATE surf_parse__scan_bytes  (yyconst char * yybytes, yy_size_t  _yyb
        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  );
@@ -10567,16 +10567,16 @@ static void yy_fatal_error (yyconst char* msg )
 /* 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)
 {
@@ -10584,7 +10584,7 @@ FILE *surf_parse_get_in  (void)
 }
 
 /** Get the output stream.
- * 
+ *
  */
 FILE *surf_parse_get_out  (void)
 {
@@ -10592,7 +10592,7 @@ FILE *surf_parse_get_out  (void)
 }
 
 /** Get the length of the current token.
- * 
+ *
  */
 yy_size_t surf_parse_get_leng  (void)
 {
@@ -10600,7 +10600,7 @@ yy_size_t surf_parse_get_leng  (void)
 }
 
 /** Get the current token.
- * 
+ *
  */
 
 char *surf_parse_get_text  (void)
@@ -10610,18 +10610,18 @@ 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 )
@@ -10652,7 +10652,7 @@ static int yy_init_globals (void)
 
     /* 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;
@@ -10682,7 +10682,7 @@ static int yy_init_globals (void)
 /* 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  );
@@ -10712,7 +10712,7 @@ int surf_parse_lex_destroy  (void)
 #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];
 }
@@ -10721,7 +10721,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s )
 {
-       register int n;
+       int n;
        for ( n = 0; s[n]; ++n )
                ;
 
index db8618d..71e9355 100644 (file)
@@ -1085,4 +1085,3 @@ void Action::updateRemainingLazy(double now)
   m_lastUpdate = now;
   m_lastValue = lmm_variable_getvalue(getVariable());
 }
-
index 5c63609..a961720 100644 (file)
@@ -9,6 +9,17 @@
 #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);
@@ -197,15 +208,72 @@ xbt_automaton_state_t xbt_automaton_get_current_state(xbt_automaton_t a){
   return a->current_state;
 }
 
-xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, void* fct){
+static int call_simple_function(void* function)
+{
+  return ((int (*)(void)) function)();
+}
+
+xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id, int(*fct)(void)){
   xbt_automaton_propositional_symbol_t prop_symb = NULL;
   prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
   prop_symb->pred = strdup(id);
-  prop_symb->function = fct;
+  prop_symb->callback = call_simple_function;
+  prop_symb->data = fct;
+  prop_symb->free_function = NULL;
   xbt_dynar_push(a->propositional_symbols, &prop_symb);
   return prop_symb;
 }
 
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a, const char* id, int* value)
+{
+  xbt_automaton_propositional_symbol_t prop_symb = NULL;
+  prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+  prop_symb->pred = strdup(id);
+  prop_symb->callback = NULL;
+  prop_symb->data = value;
+  prop_symb->free_function = NULL;
+  xbt_dynar_push(a->propositional_symbols, &prop_symb);
+  return prop_symb;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_t) xbt_automaton_propositional_symbol_new_callback(
+  xbt_automaton_t a, const char* id,
+  xbt_automaton_propositional_symbol_callback_type callback,
+  void* data, xbt_automaton_propositional_symbol_free_function_type free_function)
+{
+  xbt_automaton_propositional_symbol_t prop_symb = NULL;
+  prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
+  prop_symb->pred = strdup(id);
+  prop_symb->callback = callback;
+  prop_symb->data = data;
+  prop_symb->free_function = free_function;
+  xbt_dynar_push(a->propositional_symbols, &prop_symb);
+  return prop_symb;
+}
+
+XBT_PUBLIC(int) xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol)
+{
+  if (symbol->callback)
+    return (symbol->callback)(symbol->data);
+  else
+    return *(int*) symbol->data;
+}
+
+XBT_PUBLIC(xbt_automaton_propositional_symbol_callback_type) xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol)
+{
+  return symbol->callback;
+}
+
+XBT_PUBLIC(void*) xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol)
+{
+  return symbol->data;
+}
+
+XBT_PUBLIC(const char*) xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol)
+{
+  return symbol->pred;
+}
+
 int xbt_automaton_state_compare(xbt_automaton_state_t s1, xbt_automaton_state_t s2){
 
   /* single id for each state, id and type sufficient for comparison*/
@@ -354,7 +422,11 @@ static void xbt_automaton_propositional_symbol_free(xbt_automaton_propositional_
 }
 
 void xbt_automaton_propositional_symbol_free_voidp(void *ps){
-  xbt_automaton_propositional_symbol_free((xbt_automaton_propositional_symbol_t) * (void **) ps);
+  xbt_automaton_propositional_symbol_t symbol = (xbt_automaton_propositional_symbol_t) * (void **) ps;
+  if (symbol->free_function)
+    symbol->free_function(symbol->data);
+  xbt_free(symbol->pred);
+  xbt_automaton_propositional_symbol_free(symbol);
 }
 
 void xbt_automaton_free(xbt_automaton_t a){
index e5f85d8..d0d4d02 100644 (file)
@@ -53,7 +53,7 @@
 #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
@@ -70,7 +70,7 @@ typedef uint32_t flex_uint32_t;
 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;
 
@@ -196,7 +196,7 @@ extern FILE *xbt_automaton_parser_in, *xbt_automaton_parser_out;
 
     #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 \
@@ -253,7 +253,7 @@ struct yy_buffer_state
 
     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.
         */
@@ -531,9 +531,9 @@ char *xbt_automaton_parser_text;
 
 #include <stdio.h>
 #include "parserPromela.tab.hacc"
-  
+
   extern YYSTYPE yylval;
+
 #line 538 "automaton_lexer.yy.c"
 
 #define INITIAL 0
@@ -594,7 +594,7 @@ extern int xbt_automaton_parser_wrap (void );
 #endif
 
     static void yyunput (int c,char *buf_ptr  );
-    
+
 #ifndef yytext_ptr
 static void yy_flex_strncpy (char *,yyconst char *,int );
 #endif
@@ -717,10 +717,10 @@ extern int xbt_automaton_parser_lex (void);
  */
 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;
@@ -769,7 +769,7 @@ YY_DECL
 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;
@@ -902,13 +902,13 @@ YY_RULE_SETUP
 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:
@@ -916,7 +916,7 @@ 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:
@@ -1085,9 +1085,9 @@ case YY_STATE_EOF(INITIAL):
  */
 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] )
@@ -1219,14 +1219,14 @@ static int yy_get_next_buffer (void)
 
     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;
@@ -1251,10 +1251,10 @@ static int yy_get_next_buffer (void)
  */
     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;
@@ -1272,10 +1272,10 @@ static int yy_get_next_buffer (void)
                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 */
@@ -1284,10 +1284,10 @@ static int yy_get_next_buffer (void)
        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 )
@@ -1318,7 +1318,7 @@ static int yy_get_next_buffer (void)
 
 {
        int c;
-    
+
        *(yy_c_buf_p) = (yy_hold_char);
 
        if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
@@ -1385,12 +1385,12 @@ static int yy_get_next_buffer (void)
 
 /** 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 =
@@ -1403,11 +1403,11 @@ static int yy_get_next_buffer (void)
 
 /** 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();
@@ -1447,13 +1447,13 @@ static void xbt_automaton_parser__load_buffer_state  (void)
 /** 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()" );
@@ -1476,11 +1476,11 @@ static void xbt_automaton_parser__load_buffer_state  (void)
 
 /** 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;
 
@@ -1501,7 +1501,7 @@ static void xbt_automaton_parser__load_buffer_state  (void)
 
 {
        int oerrno = errno;
-    
+
        xbt_automaton_parser__flush_buffer(b );
 
        b->yy_input_file = file;
@@ -1517,13 +1517,13 @@ static void xbt_automaton_parser__load_buffer_state  (void)
     }
 
         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 )
 {
@@ -1552,7 +1552,7 @@ static void xbt_automaton_parser__load_buffer_state  (void)
  *  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 )
 {
@@ -1582,7 +1582,7 @@ 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)
 {
@@ -1606,7 +1606,7 @@ 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
@@ -1619,9 +1619,9 @@ static void xbt_automaton_parser_ensure_buffer_stack (void)
                                                                );
                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;
@@ -1649,13 +1649,13 @@ static void xbt_automaton_parser_ensure_buffer_stack (void)
 /** 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 )
@@ -1684,14 +1684,14 @@ YY_BUFFER_STATE xbt_automaton_parser__scan_buffer  (char * base, yy_size_t  size
 /** 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) );
 }
 
@@ -1699,7 +1699,7 @@ YY_BUFFER_STATE xbt_automaton_parser__scan_string (yyconst char * 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 )
@@ -1708,7 +1708,7 @@ YY_BUFFER_STATE xbt_automaton_parser__scan_bytes  (yyconst char * yybytes, yy_si
        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  );
@@ -1762,16 +1762,16 @@ static void yy_fatal_error (yyconst char* msg )
 /* 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)
 {
@@ -1779,7 +1779,7 @@ FILE *xbt_automaton_parser_get_in  (void)
 }
 
 /** Get the output stream.
- * 
+ *
  */
 FILE *xbt_automaton_parser_get_out  (void)
 {
@@ -1787,7 +1787,7 @@ FILE *xbt_automaton_parser_get_out  (void)
 }
 
 /** Get the length of the current token.
- * 
+ *
  */
 yy_size_t xbt_automaton_parser_get_leng  (void)
 {
@@ -1795,7 +1795,7 @@ yy_size_t xbt_automaton_parser_get_leng  (void)
 }
 
 /** Get the current token.
- * 
+ *
  */
 
 char *xbt_automaton_parser_get_text  (void)
@@ -1805,18 +1805,18 @@ 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 )
@@ -1870,7 +1870,7 @@ static int yy_init_globals (void)
 /* 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  );
@@ -1896,7 +1896,7 @@ int xbt_automaton_parser_lex_destroy  (void)
 #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];
 }
@@ -1905,7 +1905,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s )
 {
-       register int n;
+       int n;
        for ( n = 0; s[n]; ++n )
                ;
 
index f632631..7259a19 100644 (file)
@@ -107,12 +107,12 @@ XBT_INLINE unsigned int xbt_dict_size(xbt_dict_t dict)
 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,
@@ -1172,4 +1172,27 @@ XBT_TEST_UNIT("crash", test_dict_crash, "Crash test")
   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 */
index 26c9196..e591967 100644 (file)
@@ -827,6 +827,20 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
     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 */
index a543fb8..1e48d4c 100644 (file)
@@ -52,6 +52,8 @@
 #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)
@@ -155,8 +157,27 @@ void xbt_ex_display(xbt_ex_t * e)
     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
index 9391589..0df74b0 100644 (file)
@@ -52,7 +52,7 @@
 #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
@@ -69,7 +69,7 @@ typedef uint32_t flex_uint32_t;
 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;
 
@@ -195,7 +195,7 @@ extern FILE *xbt_graph_parse_in, *xbt_graph_parse_out;
 
     /* 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.
@@ -214,7 +214,7 @@ extern FILE *xbt_graph_parse_in, *xbt_graph_parse_out;
                     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 \
@@ -271,7 +271,7 @@ struct yy_buffer_state
 
     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.
         */
@@ -1040,10 +1040,10 @@ static yyconst flex_int16_t yy_chk[1642] =
 /* 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;
@@ -1066,13 +1066,13 @@ char *xbt_graph_parse_text;
  * 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.
  *
@@ -1090,20 +1090,20 @@ char *xbt_graph_parse_text;
  * 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. */
@@ -1116,7 +1116,7 @@ const char graphxml_flexml_version[] = "1.9.6";
 #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>
@@ -1125,7 +1125,7 @@ const char graphxml_flexml_version[] = "1.9.6";
 #else
 # include <unistd.h>
 #endif
-     
+
 #ifndef FLEXML_INDEXSTACKSIZE
 #define FLEXML_INDEXSTACKSIZE 1000
 #endif
@@ -1286,7 +1286,7 @@ static void pushbuffer(int p)
 {
     ck_ilimit();
     indexstack[inext++] = p;
-    indexstack[inext++] = bnext;    
+    indexstack[inext++] = bnext;
 }
 
 static int popbuffer(void)
@@ -1436,11 +1436,11 @@ static int input (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__
@@ -1545,10 +1545,10 @@ extern int xbt_graph_parse_lex (void);
  */
 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;
@@ -1644,7 +1644,7 @@ YY_DECL
 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;
@@ -1677,7 +1677,7 @@ yy_find_action:
                        yy_size_t yyl;
                        for ( yyl = 0; yyl < xbt_graph_parse_leng; ++yyl )
                                if ( xbt_graph_parse_text[yyl] == '\n' )
-                                          
+
     xbt_graph_parse_lineno++;
 ;
                        }
@@ -1742,7 +1742,7 @@ SKIP;
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-SET(DOCTYPE); 
+SET(DOCTYPE);
        YY_BREAK
 case 12:
 /* rule 12 can match eol */
@@ -2418,9 +2418,9 @@ case YY_STATE_EOF(IMPOSSIBLE):
  */
 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] )
@@ -2552,14 +2552,14 @@ static int yy_get_next_buffer (void)
 
     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;
@@ -2584,10 +2584,10 @@ static int yy_get_next_buffer (void)
  */
     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;
@@ -2614,7 +2614,7 @@ static int yy_get_next_buffer (void)
 
 {
        int c;
-    
+
        *(yy_c_buf_p) = (yy_hold_char);
 
        if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
@@ -2676,7 +2676,7 @@ static int yy_get_next_buffer (void)
        (yy_hold_char) = *++(yy_c_buf_p);
 
        if ( c == '\n' )
-                  
+
     xbt_graph_parse_lineno++;
 ;
 
@@ -2686,12 +2686,12 @@ static int yy_get_next_buffer (void)
 
 /** 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 =
@@ -2704,11 +2704,11 @@ static int yy_get_next_buffer (void)
 
 /** 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();
@@ -2748,13 +2748,13 @@ static void xbt_graph_parse__load_buffer_state  (void)
 /** 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()" );
@@ -2777,11 +2777,11 @@ static void xbt_graph_parse__load_buffer_state  (void)
 
 /** 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;
 
@@ -2802,7 +2802,7 @@ static void xbt_graph_parse__load_buffer_state  (void)
 
 {
        int oerrno = errno;
-    
+
        xbt_graph_parse__flush_buffer(b );
 
        b->yy_input_file = file;
@@ -2818,13 +2818,13 @@ static void xbt_graph_parse__load_buffer_state  (void)
     }
 
         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 )
 {
@@ -2853,7 +2853,7 @@ static void xbt_graph_parse__load_buffer_state  (void)
  *  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 )
 {
@@ -2883,7 +2883,7 @@ 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)
 {
@@ -2907,7 +2907,7 @@ 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
@@ -2920,9 +2920,9 @@ static void xbt_graph_parse_ensure_buffer_stack (void)
                                                                );
                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;
@@ -2950,13 +2950,13 @@ static void xbt_graph_parse_ensure_buffer_stack (void)
 /** 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 )
@@ -2985,14 +2985,14 @@ YY_BUFFER_STATE xbt_graph_parse__scan_buffer  (char * base, yy_size_t  size )
 /** 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) );
 }
 
@@ -3000,7 +3000,7 @@ YY_BUFFER_STATE xbt_graph_parse__scan_string (yyconst char * 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 )
@@ -3009,7 +3009,7 @@ YY_BUFFER_STATE xbt_graph_parse__scan_bytes  (yyconst char * yybytes, yy_size_t
        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  );
@@ -3095,16 +3095,16 @@ static void yy_fatal_error (yyconst char* msg )
 /* 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)
 {
@@ -3112,7 +3112,7 @@ FILE *xbt_graph_parse_get_in  (void)
 }
 
 /** Get the output stream.
- * 
+ *
  */
 FILE *xbt_graph_parse_get_out  (void)
 {
@@ -3120,7 +3120,7 @@ FILE *xbt_graph_parse_get_out  (void)
 }
 
 /** Get the length of the current token.
- * 
+ *
  */
 yy_size_t xbt_graph_parse_get_leng  (void)
 {
@@ -3128,7 +3128,7 @@ yy_size_t xbt_graph_parse_get_leng  (void)
 }
 
 /** Get the current token.
- * 
+ *
  */
 
 char *xbt_graph_parse_get_text  (void)
@@ -3138,18 +3138,18 @@ 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 )
@@ -3180,7 +3180,7 @@ static int yy_init_globals (void)
 
     /* 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;
@@ -3210,7 +3210,7 @@ static int yy_init_globals (void)
 /* 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  );
@@ -3240,7 +3240,7 @@ int xbt_graph_parse_lex_destroy  (void)
 #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];
 }
@@ -3249,7 +3249,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s )
 {
-       register int n;
+       int n;
        for ( n = 0; s[n]; ++n )
                ;
 
index 34b12cc..f2f75ba 100644 (file)
@@ -108,7 +108,6 @@ void xbt_heap_push(xbt_heap_t H, void *content, double key)
   return;
 }
 
-
 /**
  * @brief Extracts from the heap and returns the element with the smallest key.
  * \param H the heap we're working on
@@ -169,6 +168,19 @@ void *xbt_heap_remove(xbt_heap_t H, int i)
 
   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.
index 2af7c98..7cde20d 100644 (file)
@@ -639,9 +639,9 @@ static void xbt_log_connect_categories(void)
   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);
@@ -649,7 +649,17 @@ static void xbt_log_connect_categories(void)
   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);
index 373c114..a67b995 100644 (file)
@@ -23,7 +23,7 @@ void mfree(struct mdesc *mdp, void *ptr)
 {
   int type;
   size_t block, frag_nb;
-  register size_t i;
+  size_t i;
   int it;
 
   mmalloc_paranoia(mdp);
@@ -51,7 +51,7 @@ void mfree(struct mdesc *mdp, void *ptr)
     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--;
@@ -147,8 +147,8 @@ void mfree(struct mdesc *mdp, void *ptr)
           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;
@@ -191,13 +191,13 @@ void mfree(struct mdesc *mdp, void *ptr)
       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. */
index 3d58ba5..2c1a0d5 100644 (file)
@@ -5,13 +5,29 @@
  * 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 */
index 86c3421..8490906 100644 (file)
@@ -343,10 +343,6 @@ void *mmalloc_preinit(void)
   }
   xbt_assert(__mmalloc_default_mdp != NULL);
 
-#if 0 && defined(HAVE_GNU_LD) && defined(MMALLOC_WANT_OVERRIDE_LEGACY)
-  mm_gnuld_legacy_init();
-#endif
-
   return __mmalloc_default_mdp;
 }
 
@@ -357,27 +353,31 @@ void mmalloc_postexit(void)
   // xbt_mheap_destroy_no_free(__mmalloc_default_mdp);
 }
 
-size_t mmalloc_get_bytes_used(xbt_mheap_t heap){
-  int i = 0, j = 0;
+// This is the underlying implementation of mmalloc_get_bytes_used_remote.
+// Is it used directly in order to evaluate the bytes used from a different
+// process.
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo)
+{
   int bytes = 0;
-  
-  while(i<=((struct mdesc *)heap)->heaplimit){
-    if(((struct mdesc *)heap)->heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
-      if(((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size > 0)
-        bytes += ((struct mdesc *)heap)->heapinfo[i].busy_block.busy_size;
-     
-    } else if(((struct mdesc *)heap)->heapinfo[i].type > 0){
-      for(j=0; j < (size_t) (BLOCKSIZE >> ((struct mdesc *)heap)->heapinfo[i].type); j++){
-        if(((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j] > 0)
-          bytes += ((struct mdesc *)heap)->heapinfo[i].busy_frag.frag_size[j];
+  for (size_t i=0; i<=heaplimit; ++i){
+    if (heapinfo[i].type == MMALLOC_TYPE_UNFRAGMENTED){
+      if (heapinfo[i].busy_block.busy_size > 0)
+        bytes += heapinfo[i].busy_block.busy_size;
+    } else if (heapinfo[i].type > 0) {
+      for (size_t j=0; j < (size_t) (BLOCKSIZE >> heapinfo[i].type); j++){
+        if(heapinfo[i].busy_frag.frag_size[j] > 0)
+          bytes += heapinfo[i].busy_frag.frag_size[j];
       }
     }
-    i++; 
   }
-
   return bytes;
 }
 
+size_t mmalloc_get_bytes_used(const xbt_mheap_t heap){
+  const struct mdesc* heap_data = (const struct mdesc *) heap;
+  return mmalloc_get_bytes_used_remote(heap_data->heaplimit, heap_data->heapinfo);
+}
+
 ssize_t mmalloc_get_busy_size(xbt_mheap_t heap, void *ptr){
 
   ssize_t block = ((char*)ptr - (char*)(heap->heapbase)) / BLOCKSIZE + 1;
index 4c32238..b47f136 100644 (file)
@@ -177,8 +177,8 @@ void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size)
 {
   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
@@ -266,7 +266,7 @@ void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size)
       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);
@@ -359,7 +359,7 @@ void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size)
     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;
index c652e41..07ef47d 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __MMPRIVATE_H
 #define __MMPRIVATE_H 1
 
+#include <xbt/misc.h>
+
 #include "portable.h"
 #include "xbt/xbt_os_thread.h"
 #include "xbt/mmalloc.h"
@@ -94,6 +96,8 @@
 
 #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;
@@ -321,4 +325,13 @@ static inline int mmalloc_get_increment(malloc_info* heapinfo) {
 
 void mmcheck(xbt_mheap_t heap);
 
+int malloc_use_mmalloc(void);
+
+int mmalloc_exec_using_mm(int argc, const char** argv);
+void mmalloc_ensure_using_mm(int argc, const char** argv);
+
+size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo);
+
+SG_END_DECL()
+
 #endif                          /* __MMPRIVATE_H */
index c1a4983..e4d51ca 100644 (file)
 #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 */
index c355f49..d07d4a3 100644 (file)
@@ -103,9 +103,6 @@ static void xbt_preinit(void) {
     ++xbt_pagebits;
   }
 
-#ifdef MMALLOC_WANT_OVERRIDE_LEGACY
-  mmalloc_preinit();
-#endif
 #ifdef _TWO_DIGIT_EXPONENT
   /* Even printf behaves differently on Windows... */
   _set_output_format(_TWO_DIGIT_EXPONENT);
index 079e050..ed497cc 100644 (file)
@@ -10,6 +10,8 @@
 #define XBT_MODINTER_H
 #include "xbt/misc.h"
 
+SG_BEGIN_DECL()
+
 /* Modules definitions */
 void xbt_backtrace_preinit(void);
 void xbt_backtrace_postexit(void);
@@ -29,5 +31,6 @@ void xbt_os_thread_mod_postexit(void);
 void *mmalloc_preinit(void);
 void mmalloc_postexit(void);
 
+SG_END_DECL()
 
 #endif                          /* XBT_MODINTER_H */
index 89dd9ea..00e46e9 100644 (file)
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.6)
 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()
 
@@ -14,6 +14,6 @@ set(tesh_files
   )
 set(testsuite_src
   ${testsuite_src}
-  ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.cpp
   PARENT_SCOPE
   )
similarity index 70%
rename from teshsuite/mc/dwarf/dwarf.c
rename to teshsuite/mc/dwarf/dwarf.cpp
index 8b22d4b..adbe05d 100644 (file)
@@ -33,17 +33,6 @@ static dw_type_t find_type_by_name(mc_object_info_t info, const char* name) {
   return NULL;
 }
 
-static dw_variable_t find_global_variable_by_name(mc_object_info_t info, const char* name) {
-  unsigned int cursor = 0;
-  dw_variable_t variable;
-  xbt_dynar_foreach(info->global_variables, cursor, variable){
-    if(!strcmp(name, variable->name))
-      return variable;
-  }
-
-  return NULL;
-}
-
 static dw_frame_t find_function_by_name(mc_object_info_t info, const char* name) {
   xbt_dict_cursor_t cursor = 0;
   dw_frame_t subprogram;
@@ -96,15 +85,16 @@ static void test_local_variable(mc_object_info_t info, const char* function, con
 
 }
 
-static dw_variable_t test_global_variable(mc_object_info_t info, const char* name, void* address, long byte_size) {
-  dw_variable_t variable = find_global_variable_by_name(info, name);
+static dw_variable_t test_global_variable(mc_process_t process, mc_object_info_t info, const char* name, void* address, long byte_size) {
+
+  dw_variable_t variable = MC_file_object_info_find_variable_by_name(info, name);
   xbt_assert(variable, "Global variable %s was not found", name);
   xbt_assert(!strcmp(variable->name, name), "Name mismatch for %s", name);
   xbt_assert(variable->global, "Variable %s is not global", name);
   xbt_assert(variable->address == address,
       "Address mismatch for %s : %p expected but %p found", name, address, variable->address);
 
-  dw_type_t type = xbt_dict_get_or_null(mc_binary_info->types, variable->type_origin);
+  dw_type_t type = (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;
@@ -124,30 +114,31 @@ int some_local_variable = 0;
 
 typedef struct foo {int i;} s_foo;
 
-static void test_type_by_name(s_foo my_foo) {
-  assert(xbt_dict_get_or_null(mc_binary_info->full_types_by_name, "struct foo"));
+static void test_type_by_name(mc_process_t process, s_foo my_foo) {
+  assert(xbt_dict_get_or_null(process->binary_info->full_types_by_name, "struct foo"));
 }
 
-int main(int argc, char** argv) {
-
-  // xbt_init(&argc, argv);
+int main(int argc, char** argv)
+{
   SIMIX_global_init(&argc, argv);
-  MC_memory_init();
-  MC_init();
 
   dw_variable_t var;
   dw_type_t type;
 
-  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;
@@ -155,15 +146,15 @@ int main(int argc, char** argv) {
   unw_getcontext(&context);
   unw_init_local(&cursor, &context);
 
-  test_local_variable(mc_binary_info, "main", "argc", &argc, &cursor);
+  test_local_variable(process->binary_info, "main", "argc", &argc, &cursor);
 
   {
     int lexical_block_variable = 50;
-    test_local_variable(mc_binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
+    test_local_variable(process->binary_info, "main", "lexical_block_variable", &lexical_block_variable, &cursor);
   }
 
   s_foo my_foo;
-  test_type_by_name(my_foo);
+  test_type_by_name(process, my_foo);
 
   _exit(0);
 }
index 93e284b..0491dad 100644 (file)
@@ -1,5 +1,3 @@
 #! ./tesh
 
 $ $SG_TEST_EXENV ${bindir:=.}/dwarf
-> [0.000000] [mc_global/INFO] Get debug information ...
-> [0.000000] [mc_global/INFO] Get debug information done !
index 998b779..a4dbb9a 100644 (file)
@@ -15,6 +15,8 @@
 #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;
@@ -113,8 +115,11 @@ void test_deref(mc_expression_state_t state) {
 }
 
 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);
 
index fea8c27..fba41c7 100644 (file)
@@ -6,9 +6,12 @@
 
 #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[])
@@ -33,5 +36,5 @@ int main(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();
 }
index 63b5b8f..59e995b 100644 (file)
@@ -1,18 +1,14 @@
 #!/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
index 4f60925..977f595 100644 (file)
@@ -1,5 +1,4 @@
 #!/usr/bin/env tesh
-$ ${bindir:=.}/random_bug  ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" "--cfg=model-check/replay:1/3;1/4"
-> [  0.000000] (0:@) Configuration change: Set 'model-check/replay' to '1/3;1/4'
+$ ${bindir:=.}/random_bug  ${srcdir:=.}/../../../examples/platforms/small_platform.xml ${srcdir:=.}/random_bug.xml --log=xbt_cfg.thresh:warning "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" "--cfg=model-check/replay:1/3;1/4"
 > [  0.000000] (0:@) path=1/3;1/4
 > Error reached
index f940ec9..959bf5e 100644 (file)
@@ -104,6 +104,8 @@ int test_launcher(int argc, char *argv[])
   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);
@@ -116,7 +118,7 @@ int test_launcher(int argc, char *argv[])
     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;
index eb10b87..5881f4d 100644 (file)
@@ -54,13 +54,14 @@ $ ./host_on_off_processes ${srcdir:=.}/../../../examples/platforms/small_platfor
 > [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
index 4064899..9687b08 100644 (file)
@@ -10,7 +10,7 @@ $ ./task_destroy_cancel ${srcdir:=.}/../../../examples/platforms/small_platform.
 > [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"
index f004859..51468dc 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock10
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 26
 > [0.000000] [mc_global/INFO] Executed transitions = 25
 > Aborted
-
index cf03096..c42b93a 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock4
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
index bae9bc7..66eb095 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock5
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 26
 > [0.000000] [mc_global/INFO] Executed transitions = 25
 > Aborted
-
index 3f32b3c..6a9902b 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-can-deadlock6
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 26
 > [0.000000] [mc_global/INFO] Executed transitions = 25
 > Aborted
-
index 1567e6b..ead069f 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-wait-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 23
 > [0.000000] [mc_global/INFO] Executed transitions = 22
 > Aborted
-
index 9ae4cbe..b1ddbd1 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 26
 > [0.000000] [mc_global/INFO] Executed transitions = 25
 > Aborted
-
index 173b558..d3dbf5e 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitall-deadlock3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -52,4 +44,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 29
 > [0.000000] [mc_global/INFO] Executed transitions = 28
 > Aborted
-
index 5a912d8..04bf19a 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -47,4 +39,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 24
 > [0.000000] [mc_global/INFO] Executed transitions = 23
 > Aborted
-
index fa30aa0..e65b72d 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/any_src-waitany-deadlock2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -52,4 +44,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 29
 > [0.000000] [mc_global/INFO] Executed transitions = 28
 > Aborted
-
index 6e0bd50..928a237 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_create
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -47,4 +39,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Executed transitions = 22
 > (1) Got MPI_COMM_NULL
 > Aborted
-
index 585b2cf..68040ca 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_dup
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 23
 > [0.000000] [mc_global/INFO] Executed transitions = 22
 > Aborted
-
index 13b94e3..2626045 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock-comm_split
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -59,4 +51,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Executed transitions = 34
 > (1) Derived communicator too small (size = 1)
 > Aborted
-
index 9f1e0ce..a3b8f77 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/basic-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 23
 > [0.000000] [mc_global/INFO] Executed transitions = 22
 > Aborted
-
index b3908f9..cb1047e 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/bcast-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 4
 > [0.000000] [mc_global/INFO] Executed transitions = 3
 > Aborted
-
index 779979a..4ff6bcc 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder-allreduce
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -46,4 +38,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 23
 > [0.000000] [mc_global/INFO] Executed transitions = 22
 > Aborted
-
index 9401a31..1fbee62 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/collective-misorder
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -68,4 +60,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 45
 > [0.000000] [mc_global/INFO] Executed transitions = 44
 > Aborted
-
index a094d85..3b65516 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/complex-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -49,4 +41,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 26
 > [0.000000] [mc_global/INFO] Executed transitions = 25
 > Aborted
-
index 5c9869e..0072667 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/deadlock-config
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -31,4 +23,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 4
 > [0.000000] [mc_global/INFO] Executed transitions = 3
 > Aborted
-
index d4476a3..65b39ff 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/finalize-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -45,4 +37,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > (1) Finished normally
 > (2) Finished normally
 > Aborted
-
index 3bc6c86..8bd4c68 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/irecv-deadlock
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -45,4 +37,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > [0.000000] [mc_global/INFO] Visited states = 22
 > [0.000000] [mc_global/INFO] Executed transitions = 21
 > Aborted
-
index 9cb94eb..7a09217 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -22,4 +14,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > (0) Finished normally
 > (1) Finished normally
 > Aborted
-
index 9bb6deb..4d9856b 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error2
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > (2) Finished normally
 > (0) Finished normally
 > Aborted
-
index 5cecb65..1c30ed3 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3-any_src
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > (2) Finished normally
 > (0) Finished normally
 > Aborted
-
index 1512434..fec8ed5 100644 (file)
@@ -1,17 +1,9 @@
 #! ./tesh
 
 ! expect return 134
-$ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../../../examples/platforms/small_platform.xml -np 3 --cfg=model-check:1 --cfg=smpi/running_power:1e9 --cfg=smpi/coll_selector:mpich ${bindir:=.}/no-error3
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'surf/precision' to '1e-9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/model' to 'SMPI'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'network/TCP_gamma' to '4194304'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/running_power' to '1e9'
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'smpi/coll_selector' to 'mpich'
+$ ${bindir:=.}/../../../../bin/smpirun -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
@@ -27,4 +19,3 @@ $ ${bindir:=.}/../../../../bin/smpirun -hostfile ../../hostfile -platform ../../
 > (2) Finished normally
 > (0) Finished normally
 > Aborted
-