Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of framagit.org:simgrid/simgrid
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 24 Jun 2022 21:03:35 +0000 (23:03 +0200)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 24 Jun 2022 21:03:35 +0000 (23:03 +0200)
17 files changed:
MANIFEST.in
docs/source/Installing_SimGrid.rst
examples/sthread/CMakeLists.txt [new file with mode: 0644]
examples/sthread/pthread-mutex-simple.c [new file with mode: 0644]
examples/sthread/sthread-mutex-simple.c [new file with mode: 0644]
include/simgrid/forward.h
src/mc/api/State.cpp
src/mc/mc_pattern.hpp
src/smpi/internals/smpi_global.cpp
src/sthread/sthread.c [new file with mode: 0644]
src/sthread/sthread.h [new file with mode: 0644]
src/sthread/sthread_impl.cpp [new file with mode: 0644]
src/xbt/log.cpp
src/xbt/xbt_main.cpp
tools/cmake/DefinePackages.cmake
tools/cmake/Distrib.cmake
tools/cmake/MakeLib.cmake

index c3f49ce..a284636 100644 (file)
@@ -710,6 +710,8 @@ include examples/smpi/trace_call_location/trace_call_location.c
 include examples/smpi/trace_call_location/trace_call_location.tesh
 include examples/smpi/trace_simple/trace_simple.c
 include examples/smpi/trace_simple/trace_simple.tesh
+include examples/sthread/pthread-mutex-simple.c
+include examples/sthread/sthread-mutex-simple.c
 include src/include/catch_simgrid.hpp
 include teshsuite/java/semaphoregc/SemaphoreGC.java
 include teshsuite/java/semaphoregc/semaphoregc.tesh
@@ -1973,6 +1975,7 @@ include examples/smpi/comm_dynamic_costs/CMakeLists.txt
 include examples/smpi/replay_multiple/CMakeLists.txt
 include examples/smpi/replay_multiple_manual_deploy/CMakeLists.txt
 include examples/smpi/smpi_s4u_masterworker/CMakeLists.txt
+include examples/sthread/CMakeLists.txt
 include include/simgrid/Exception.hpp
 include include/simgrid/actor.h
 include include/simgrid/barrier.h
@@ -2584,6 +2587,9 @@ include src/smpi/smpif90.in
 include src/smpi/smpiff.in
 include src/smpi/smpirun.in
 include src/smpi/smpitools.sh
+include src/sthread/sthread.c
+include src/sthread/sthread.h
+include src/sthread/sthread_impl.cpp
 include src/surf/HostImpl.cpp
 include src/surf/HostImpl.hpp
 include src/surf/cpu_cas01.cpp
index 2626419..9d5d606 100644 (file)
@@ -146,7 +146,7 @@ Grab the last **stable release** from `FramaGit
 
    $ tar xf simgrid-3-XX.tar.gz
    $ cd simgrid-*
-   $ cmake -DCMAKE_INSTALL_PREFIX=/opt/simgrid .
+   $ cmake -DCMAKE_INSTALL_PREFIX=/opt/simgrid -GNinja.
    $ make
    $ make install
 
diff --git a/examples/sthread/CMakeLists.txt b/examples/sthread/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d547302
--- /dev/null
@@ -0,0 +1,48 @@
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+
+# Regular pthread examples: test the interceptor of the pthread interface
+#########################################################################
+
+foreach(x
+        mutex-simple)
+
+  if("${CMAKE_SYSTEM}" MATCHES "Linux")
+    add_executable       (pthread-${x} EXCLUDE_FROM_ALL pthread-${x}.c)
+    set_target_properties(pthread-${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+    target_link_libraries(pthread-${x} PRIVATE Threads::Threads)
+
+    add_dependencies(tests pthread-${x})
+  endif()
+
+#  set(tesh_files    ${tesh_files}    ${CMAKE_CURRENT_SOURCE_DIR}/pthread-${x}.tesh)
+  set(examples_src  ${examples_src}  ${CMAKE_CURRENT_SOURCE_DIR}/pthread-${x}.c)
+endforeach()
+
+# Regular sthread examples: test the internal interface for debugging purpose
+#############################################################################
+
+foreach(x
+        mutex-simple)
+  if("${CMAKE_SYSTEM}" MATCHES "Linux")
+    add_executable       (sthread-${x} EXCLUDE_FROM_ALL sthread-${x}.c)
+    set_target_properties(sthread-${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+    target_link_libraries(sthread-${x} sthread)
+    set_property(TARGET sthread-${x} APPEND PROPERTY INCLUDE_DIRECTORIES "${INTERNAL_INCLUDES}")
+    add_dependencies(tests sthread-${x})
+  endif()
+
+#  set(tesh_files    ${tesh_files}    ${CMAKE_CURRENT_SOURCE_DIR}/sthread-${x}.tesh)
+  set(examples_src  ${examples_src}  ${CMAKE_CURRENT_SOURCE_DIR}/sthread-${x}.c)
+endforeach()
+
+
+# Add all extra files to the archive
+####################################
+
+set(tesh_files    ${tesh_files}     PARENT_SCOPE)
+set(bin_files     ${bin_files}      PARENT_SCOPE)
+set(examples_src  ${examples_src}   PARENT_SCOPE)
+set(xml_files     ${xml_files}      PARENT_SCOPE)
+
+
diff --git a/examples/sthread/pthread-mutex-simple.c b/examples/sthread/pthread-mutex-simple.c
new file mode 100644 (file)
index 0000000..ae928c2
--- /dev/null
@@ -0,0 +1,38 @@
+/* Simple test code with no bug  */
+
+#include <pthread.h>
+#include <stdio.h>
+
+pthread_mutex_t mutex;
+
+static void* thread1_fun(void* ignore)
+{
+  pthread_mutex_lock(&mutex);
+  pthread_mutex_unlock(&mutex);
+
+  return NULL;
+}
+static void* thread2_fun(void* ignore)
+{
+  pthread_mutex_lock(&mutex);
+  pthread_mutex_unlock(&mutex);
+
+  return NULL;
+}
+
+int main(int argc, char* argv[])
+{
+  fprintf(stderr, "User main is starting\n");
+
+  pthread_mutex_init(&mutex, NULL);
+
+  pthread_t thread1, thread2;
+  fprintf(stderr, "prout\n");
+  pthread_create(&thread1, NULL, thread1_fun, NULL);
+  pthread_create(&thread2, NULL, thread2_fun, NULL);
+  // pthread_join(thread1, NULL);
+  // pthread_join(thread2, NULL);
+
+  fprintf(stderr, "User main is done\n");
+  return 0;
+}
diff --git a/examples/sthread/sthread-mutex-simple.c b/examples/sthread/sthread-mutex-simple.c
new file mode 100644 (file)
index 0000000..efbedd3
--- /dev/null
@@ -0,0 +1,36 @@
+/* Simple test code with no bug  */
+
+#include "src/sthread/sthread.h"
+#include <stdio.h>
+
+sthread_mutex_t mutex;
+
+static void* thread1_fun(void* ignore)
+{
+  sthread_mutex_lock(&mutex);
+  sthread_mutex_unlock(&mutex);
+
+  return NULL;
+}
+static void* thread2_fun(void* ignore)
+{
+  sthread_mutex_lock(&mutex);
+  sthread_mutex_unlock(&mutex);
+
+  return NULL;
+}
+
+int main(int argc, char* argv[])
+{
+  sthread_inside_simgrid = 1;
+  sthread_mutex_init(&mutex, NULL);
+
+  sthread_t thread1, thread2;
+  sthread_create(&thread1, NULL, thread1_fun, NULL);
+  sthread_create(&thread2, NULL, thread2_fun, NULL);
+  // pthread_join(thread1, NULL);
+  // pthread_join(thread2, NULL);
+  fprintf(stderr, "done\n");
+
+  return 0;
+}
index e8356af..9b81d2a 100644 (file)
@@ -324,4 +324,6 @@ typedef enum {
   SG_ERROR_VM
 } sg_error_t;
 
+XBT_PUBLIC int SMPI_is_inited();
+
 #endif /* SIMGRID_TYPES_H */
index e3048b1..fac456f 100644 (file)
@@ -54,18 +54,13 @@ int State::next_transition() const
 void State::execute_next(int next)
 {
   std::vector<ActorInformation>& actors = mc_model_checker->get_remote_process().actors();
-
   const kernel::actor::ActorImpl* actor = actors[next].copy.get_buffer();
-  aid_t aid                       = actor->get_pid();
-  int times_considered;
+  const aid_t aid                       = actor->get_pid();
 
-  simgrid::mc::ActorState* actor_state = &actor_states_[aid];
   /* This actor is ready to be executed. Prepare its execution when simcall_handle will be called on it */
-  times_considered = actor_state->get_times_considered_and_inc();
-  if (actor->simcall_.mc_max_consider_ <= actor_state->get_times_considered())
-    actor_state->set_done();
+  const unsigned times_considered = actor_states_[aid].do_consider(actor->simcall_.mc_max_consider_);
 
-  XBT_DEBUG("Let's run actor %ld (times_considered = %d)", aid, times_considered);
+  XBT_DEBUG("Let's run actor %ld (times_considered = %u)", aid, times_considered);
 
   Transition::executed_transitions_++;
 
index 8702a24..e29895c 100644 (file)
@@ -35,8 +35,13 @@ class ActorState {
   unsigned int times_considered_ = 0;
 
 public:
+  unsigned int do_consider(unsigned int max_consider)
+  {
+    if (max_consider <= times_considered_ + 1)
+      set_done();
+    return times_considered_++;
+  }
   unsigned int get_times_considered() const { return times_considered_; }
-  unsigned int get_times_considered_and_inc() { return times_considered_++; }
 
   bool is_disabled() const { return this->state_ == InterleavingType::disabled; }
   bool is_done() const { return this->state_ == InterleavingType::done; }
index 03048a0..3ff42f8 100644 (file)
@@ -583,6 +583,11 @@ int smpi_main(const char* executable, int argc, char* argv[])
   return smpi_exit_status;
 }
 
+static bool smpi_inited = false;
+int SMPI_is_inited()
+{
+  return smpi_inited;
+}
 // Called either directly from the user code, or from the code called by smpirun
 void SMPI_init(){
   smpi_init_options_internal(false);
@@ -601,6 +606,7 @@ void SMPI_init(){
   }
   smpi_init_papi();
   smpi_check_options();
+  smpi_inited = true;
 }
 
 void SMPI_finalize()
diff --git a/src/sthread/sthread.c b/src/sthread/sthread.c
new file mode 100644 (file)
index 0000000..4c36bd7
--- /dev/null
@@ -0,0 +1,193 @@
+/* SimGrid's pthread interposer. Redefinition of the pthread symbols (see the comment in sthread.h) */
+
+#define _GNU_SOURCE
+#include "src/sthread/sthread.h"
+#include <dlfcn.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+/* We don't want to intercept pthread within simgrid. Instead we should provide the real implem to simgrid */
+static int (*raw_pthread_create)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*);
+static int (*raw_mutex_init)(pthread_mutex_t*, const pthread_mutexattr_t*) = NULL;
+static int (*raw_mutex_lock)(pthread_mutex_t*)                             = NULL;
+static int (*raw_mutex_trylock)(pthread_mutex_t*)                          = NULL;
+static int (*raw_mutex_unlock)(pthread_mutex_t*)                           = NULL;
+static int (*raw_mutex_destroy)(pthread_mutex_t*)                          = NULL;
+static sem_t* (*raw_sem_open)(const char*, int)                            = NULL;
+static int (*raw_sem_init)(sem_t*, int, unsigned int)                      = NULL;
+static int (*raw_sem_wait)(sem_t*)                                         = NULL;
+static int (*raw_sem_post)(sem_t*)                                         = NULL;
+static void intercepter_init()
+{
+  raw_pthread_create =
+      (int (*)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*))dlsym(RTLD_NEXT, "pthread_create");
+  raw_mutex_init    = (int (*)(pthread_mutex_t*, const pthread_mutexattr_t*))dlsym(RTLD_NEXT, "pthread_mutex_init");
+  raw_mutex_lock    = (int (*)(pthread_mutex_t*))dlsym(RTLD_NEXT, "pthread_mutex_lock");
+  raw_mutex_trylock = (int (*)(pthread_mutex_t*))dlsym(RTLD_NEXT, "pthread_mutex_trylock");
+  raw_mutex_unlock  = (int (*)(pthread_mutex_t*))dlsym(RTLD_NEXT, "pthread_mutex_unlock");
+  raw_mutex_destroy = (int (*)(pthread_mutex_t*))dlsym(RTLD_NEXT, "pthread_mutex_destroy");
+
+  raw_sem_open = (sem_t * (*)(const char*, int)) dlsym(RTLD_NEXT, "sem_open");
+  raw_sem_init = (int (*)(sem_t*, int, unsigned int))dlsym(RTLD_NEXT, "sem_init");
+  raw_sem_wait = (int (*)(sem_t*))dlsym(RTLD_NEXT, "sem_wait");
+  raw_sem_post = (int (*)(sem_t*))dlsym(RTLD_NEXT, "sem_post");
+}
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg)
+{
+  if (raw_pthread_create == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    return raw_pthread_create(thread, attr, start_routine, arg);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_create(thread, attr, start_routine, arg);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+
+int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr)
+{
+  if (raw_mutex_init == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    raw_mutex_init(mutex, attr);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_mutex_init((sthread_mutex_t*)mutex, attr);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+
+int pthread_mutex_lock(pthread_mutex_t* mutex)
+{
+  if (raw_mutex_lock == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    return raw_mutex_lock(mutex);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_mutex_lock((sthread_mutex_t*)mutex);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+
+int pthread_mutex_trylock(pthread_mutex_t* mutex)
+{
+  if (raw_mutex_trylock == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    return raw_mutex_trylock(mutex);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_mutex_trylock((sthread_mutex_t*)mutex);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t* mutex)
+{
+  if (raw_mutex_unlock == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    return raw_mutex_unlock(mutex);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_mutex_unlock((sthread_mutex_t*)mutex);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+int pthread_mutex_destroy(pthread_mutex_t* mutex)
+{
+  if (raw_mutex_destroy == NULL)
+    intercepter_init();
+
+  if (sthread_inside_simgrid)
+    return raw_mutex_destroy(mutex);
+
+  sthread_inside_simgrid = 1;
+  int res                = sthread_mutex_destroy((sthread_mutex_t*)mutex);
+  sthread_inside_simgrid = 0;
+  return res;
+}
+
+#if 0
+int sem_init(sem_t *sem, int pshared, unsigned int value) {
+       int res;
+
+       res=raw_sem_init(sem,pshared,value);
+       return res;
+}
+
+int sem_wait(sem_t *sem) {
+       int res;
+
+       res = raw_sem_wait(sem);
+       return res;
+}
+
+int sem_post(sem_t *sem) {
+       return raw_sem_post(sem);
+}
+
+int pthread_join(pthread_t thread, void **retval) {
+       sg_actor_join(thread, -1);
+    return 0;
+}
+
+int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) {
+    *cond = sg_cond_init();
+    return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t *cond) {
+       sg_cond_notify_one(*cond);
+    return 0;
+}
+
+int pthread_cond_broadcast(pthread_cond_t *cond) {
+       sg_cond_notify_all(*cond);
+    return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
+       sg_cond_wait(*cond, *mutex);
+    return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *cond) {
+       sg_cond_destroy(*cond);
+    return 0;
+}
+#endif
+
+/* Trampoline for the real main() */
+static int (*raw_main)(int, char**, char**);
+
+/* Our fake main() that gets called by __libc_start_main() */
+static int main_hook(int argc, char** argv, char** envp)
+{
+  return sthread_main(argc, argv, envp, raw_main);
+}
+
+/* Wrapper for __libc_start_main() that replaces the real main function with our hooked version. */
+int __libc_start_main(int (*main)(int, char**, char**), int argc, char** argv, int (*init)(int, char**, char**),
+                      void (*fini)(void), void (*rtld_fini)(void), void* stack_end);
+
+int __libc_start_main(int (*main)(int, char**, char**), int argc, char** argv, int (*init)(int, char**, char**),
+                      void (*fini)(void), void (*rtld_fini)(void), void* stack_end)
+{
+  /* Save the real main function address */
+  raw_main = main;
+
+  /* Find the real __libc_start_main()... */
+  typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main");
+
+  /* ... and call it with our custom main function */
+  return orig(main_hook, argc, argv, init, fini, rtld_fini, stack_end);
+}
\ No newline at end of file
diff --git a/src/sthread/sthread.h b/src/sthread/sthread.h
new file mode 100644 (file)
index 0000000..2099432
--- /dev/null
@@ -0,0 +1,32 @@
+/* SimGrid's pthread interposer. Intercepts most of the pthread and semaphore calls to model-check them.
+ *
+ * Intercepting on pthread is somewhat complicated by the fact that pthread is used everywhere in the system headers.
+ * To reduce definition conflicts, our redefinitions of the pthread symbols (in sthread.c) load as little headers as
+ * possible. Thus, the actual implementations are separated in another file (sthread_impl.cpp) and are used as black
+ * boxes by our redefinitions.
+ *
+ * The sthread_* symbols are those actual implementations, used in the pthread_* redefinitions. */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern int
+    sthread_inside_simgrid; // allows logs and library constructors to disable the interception on pthread operations
+
+int sthread_main(int argc, char** argv, char** envp, int (*raw_main)(int, char**, char**));
+
+typedef unsigned long int sthread_t;
+int sthread_create(sthread_t* thread, const /*pthread_attr_t*/ void* attr, void* (*start_routine)(void*), void* arg);
+
+typedef struct {
+  void* mutex;
+} sthread_mutex_t;
+int sthread_mutex_init(sthread_mutex_t* mutex, const /*pthread_mutexattr_t*/ void* attr);
+int sthread_mutex_lock(sthread_mutex_t* mutex);
+int sthread_mutex_trylock(sthread_mutex_t* mutex);
+int sthread_mutex_unlock(sthread_mutex_t* mutex);
+int sthread_mutex_destroy(sthread_mutex_t* mutex);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/src/sthread/sthread_impl.cpp b/src/sthread/sthread_impl.cpp
new file mode 100644 (file)
index 0000000..d2bb5d6
--- /dev/null
@@ -0,0 +1,162 @@
+/* SimGrid's pthread interposer. Actual implementation of the symbols (see the comment in sthread.h) */
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "smpi/smpi.h"
+#include <simgrid/actor.h>
+#include <simgrid/s4u/Actor.hpp>
+#include <simgrid/s4u/Engine.hpp>
+#include <simgrid/s4u/Mutex.hpp>
+#include <simgrid/s4u/NetZone.hpp>
+#include <xbt/base.h>
+#include <xbt/sysdep.h>
+
+#include "src/internal_config.h"
+#include "src/sthread/sthread.h"
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(sthread, "pthread intercepter");
+namespace sg4 = simgrid::s4u;
+
+static sg4::Host* lilibeth = NULL;
+
+int sthread_main(int argc, char** argv, char** envp, int (*raw_main)(int, char**, char**))
+{
+  XBT_INFO("sthread main() is starting");
+  sthread_inside_simgrid = 1;
+
+  sg4::Engine e(&argc, argv);
+  auto* zone = sg4::create_full_zone("world");
+  lilibeth   = zone->create_host("Lilibeth", 1e15);
+  zone->seal();
+  sthread_inside_simgrid = 0;
+
+  /* Launch the user's main() on an actor */
+  sg4::ActorPtr main_actor = sg4::Actor::create("tid 0", lilibeth, raw_main, argc, argv, envp);
+
+  XBT_INFO("sthread main() is launching the simulation");
+  sg4::Engine::get_instance()->run();
+
+  return 0;
+}
+struct sthread_mutex {
+  s4u_Mutex* mutex;
+};
+
+static void thread_create_wrapper(void* (*user_function)(void*), void* param)
+{
+#if HAVE_SMPI
+  if (SMPI_is_inited())
+    SMPI_thread_create();
+#endif
+  sthread_inside_simgrid = 0;
+  user_function(param);
+  sthread_inside_simgrid = 1;
+}
+
+int sthread_create(unsigned long int* thread, const /*pthread_attr_t*/ void* attr, void* (*start_routine)(void*),
+                   void* arg)
+{
+  static int TID = 1;
+
+  if (TID == 0) {
+  }
+  TID++;
+  int rank = 0;
+#if HAVE_SMPI
+  if (SMPI_is_inited())
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+#endif
+  char name[100];
+  sprintf(name, "%d:%d", rank, TID);
+  sg4::ActorPtr actor = sg4::Actor::init(name, lilibeth);
+  actor->start(thread_create_wrapper, start_routine, arg);
+
+  intrusive_ptr_add_ref(actor.get());
+  *thread = reinterpret_cast<unsigned long>(actor.get());
+  return 0;
+}
+
+int sthread_mutex_init(sthread_mutex_t* mutex, const /*pthread_mutexattr_t*/ void* attr)
+{
+  auto m = sg4::Mutex::create();
+  intrusive_ptr_add_ref(m.get());
+
+  mutex->mutex = m.get();
+  return 0;
+}
+
+int sthread_mutex_lock(sthread_mutex_t* mutex)
+{
+  static_cast<sg4::Mutex*>(mutex->mutex)->lock();
+  return 0;
+}
+
+int sthread_mutex_trylock(sthread_mutex_t* mutex)
+{
+  return static_cast<sg4::Mutex*>(mutex->mutex)->try_lock();
+}
+
+int sthread_mutex_unlock(sthread_mutex_t* mutex)
+{
+  static_cast<sg4::Mutex*>(mutex->mutex)->unlock();
+  return 0;
+}
+int sthread_mutex_destroy(sthread_mutex_t* mutex)
+{
+  intrusive_ptr_release(static_cast<sg4::Mutex*>(mutex->mutex));
+  return 0;
+}
+
+#if 0
+int sem_init(sem_t *sem, int pshared, unsigned int value) {
+       int res;
+
+       res=raw_sem_init(sem,pshared,value);
+       return res;
+}
+
+int sem_wait(sem_t *sem) {
+       int res;
+
+       res = raw_sem_wait(sem);
+       return res;
+}
+
+int sem_post(sem_t *sem) {
+       return raw_sem_post(sem);
+}
+
+int pthread_join(pthread_t thread, void **retval) {
+       sg_actor_join(thread, -1);
+    return 0;
+}
+
+int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) {
+    *cond = sg_cond_init();
+    return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t *cond) {
+       sg_cond_notify_one(*cond);
+    return 0;
+}
+
+int pthread_cond_broadcast(pthread_cond_t *cond) {
+       sg_cond_notify_all(*cond);
+    return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
+       sg_cond_wait(*cond, *mutex);
+    return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *cond) {
+       sg_cond_destroy(*cond);
+    return 0;
+}
+#endif
index 916c77b..bdb7d6f 100644 (file)
@@ -5,6 +5,7 @@
 /* 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 "src/sthread/sthread.h" // sthread_inside_simgrid
 #include "src/xbt/log_private.hpp"
 #include "xbt/string.hpp"
 #include "xbt/sysdep.h"
@@ -246,6 +247,8 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority
   if (category->initialized)
     return priority >= category->threshold;
 
+  int old_inside_simgrid = sthread_inside_simgrid;
+  sthread_inside_simgrid = 1;
   if (log_cat_init_mutex != nullptr)
     log_cat_init_mutex->lock();
 
@@ -293,6 +296,7 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority
   category->initialized = 1;
   if (log_cat_init_mutex != nullptr)
     log_cat_init_mutex->unlock();
+  sthread_inside_simgrid = old_inside_simgrid;
   return priority >= category->threshold;
 }
 
index 065f79a..f452565 100644 (file)
@@ -10,6 +10,7 @@
 #include "simgrid/config.h"
 #include "simgrid/sg_config.hpp"
 #include "src/internal_config.h"
+#include "src/sthread/sthread.h" // sthread_inside_simgrid
 #include "xbt/config.hpp"
 #include "xbt/coverage.h"
 #include "xbt/dynar.h"
@@ -40,6 +41,8 @@ std::string binary_name;          /* Name of the system process containing us (m
 std::vector<std::string> cmdline; /* all we got in argv */
 } // namespace simgrid::xbt
 
+int sthread_inside_simgrid = 0; // whether sthread should leave pthread operations or intercept them.
+
 int xbt_initialized = 0;
 simgrid::config::Flag<bool> cfg_dbg_clean_atexit{
     "debug/clean-atexit",
@@ -79,6 +82,7 @@ static BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserv
 
 static void xbt_preinit()
 {
+  sthread_inside_simgrid = 1;
 #ifdef _WIN32
   SYSTEM_INFO si;
   GetSystemInfo(&si);
@@ -98,6 +102,7 @@ static void xbt_preinit()
   xbt_log_preinit();
   xbt_dict_preinit();
   atexit(xbt_postexit);
+  sthread_inside_simgrid = 0;
 }
 
 static void xbt_postexit()
@@ -157,3 +162,10 @@ void xbt_abort()
 #endif
   abort();
 }
+
+#ifndef HAVE_SMPI
+int SMPI_is_inited()
+{
+  return false;
+}
+#endif
\ No newline at end of file
index 97661ce..66fd9c8 100644 (file)
@@ -248,6 +248,11 @@ set(SMPI_SRC
   src/surf/network_ib.cpp
   src/surf/network_smpi.cpp
   )
+set(STHREAD_SRC
+  src/sthread/sthread_impl.cpp
+  src/sthread/sthread.c
+  src/sthread/sthread.h
+)
 
 set(XBT_SRC
   src/xbt/OsSemaphore.hpp
@@ -1030,6 +1035,7 @@ set(CMAKEFILES_TXT
   examples/smpi/replay_multiple/CMakeLists.txt
   examples/smpi/replay_multiple_manual_deploy/CMakeLists.txt
   examples/smpi/smpi_s4u_masterworker/CMakeLists.txt
+  examples/sthread/CMakeLists.txt
 
   teshsuite/java/CMakeLists.txt
   teshsuite/kernel/CMakeLists.txt
index 47e8911..8d871e3 100644 (file)
@@ -111,6 +111,7 @@ set(source_to_pack
   ${TRACING_SRC}
   ${XBT_RL_SRC}
   ${XBT_SRC}
+  ${STHREAD_SRC}
   ${EXTRA_DIST}
   ${CMAKE_SOURCE_FILES}
   ${CMAKEFILES_TXT}
index 8729e1c..f5d906c 100644 (file)
@@ -26,6 +26,17 @@ set_property(TARGET simgrid
 
 add_dependencies(simgrid maintainer_files)
 
+if("${CMAKE_SYSTEM}" MATCHES "Linux")
+  add_library(sthread SHARED ${STHREAD_SRC})
+  set_property(TARGET sthread
+                APPEND PROPERTY INCLUDE_DIRECTORIES "${INTERNAL_INCLUDES}")
+  install(TARGETS sthread # install that binary without breaking the rpath on Mac
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/)
+  target_link_libraries(sthread simgrid)
+else()
+  set(EXTRA_DIST ${EXTRA_DIST} ${STHREAD_SRC})
+endif()
+
 if(enable_model-checking)
   add_executable(simgrid-mc ${MC_SIMGRID_MC_SRC})
   target_link_libraries(simgrid-mc simgrid)
@@ -36,9 +47,9 @@ if(enable_model-checking)
   install(TARGETS simgrid-mc # install that binary without breaking the rpath on Mac
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/)
   add_dependencies(tests-mc simgrid-mc)
+  add_dependencies(tests-mc sthread)
 endif()
 
-
 # Compute the dependencies of SimGrid
 #####################################
 # search for dlopen