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
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
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
$ 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
--- /dev/null
+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)
+
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
SG_ERROR_VM
} sg_error_t;
+XBT_PUBLIC int SMPI_is_inited();
+
#endif /* SIMGRID_TYPES_H */
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_++;
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; }
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);
}
smpi_init_papi();
smpi_check_options();
+ smpi_inited = true;
}
void SMPI_finalize()
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
/* 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"
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();
category->initialized = 1;
if (log_cat_init_mutex != nullptr)
log_cat_init_mutex->unlock();
+ sthread_inside_simgrid = old_inside_simgrid;
return priority >= category->threshold;
}
#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"
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",
static void xbt_preinit()
{
+ sthread_inside_simgrid = 1;
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
xbt_log_preinit();
xbt_dict_preinit();
atexit(xbt_postexit);
+ sthread_inside_simgrid = 0;
}
static void xbt_postexit()
#endif
abort();
}
+
+#ifndef HAVE_SMPI
+int SMPI_is_inited()
+{
+ return false;
+}
+#endif
\ No newline at end of file
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
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
${TRACING_SRC}
${XBT_RL_SRC}
${XBT_SRC}
+ ${STHREAD_SRC}
${EXTRA_DIST}
${CMAKE_SOURCE_FILES}
${CMAKEFILES_TXT}
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)
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