From d7a342ebdb564e43f7d192eb49402e2d96ac8a46 Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Fri, 4 Jan 2019 23:50:59 +0100 Subject: [PATCH] Introduce a portable xbt::OsSemaphore using C++11 threads --- ChangeLog | 4 ++++ src/kernel/context/ContextThread.cpp | 35 +++++++++++----------------- src/kernel/context/ContextThread.hpp | 11 +++++---- src/simgrid/sg_config.cpp | 2 +- src/xbt/xbt_os_thread.c | 3 +-- tools/cmake/DefinePackages.cmake | 1 + 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 121fc47a34..e9981e095a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,10 @@ MSG: XBT: - Drop sg_cmdline. Please use xbt_cmdline instead. + - Drop the C xbt_os_sem_t; Use the C++ xbt::OsSemaphore. + OsSemaphore is implemented in a portable way with C++11 threads. + This should introduce a major scalability improvement to the thread + backend, from which Mac users and Java users will benefit for free. Fixed bugs: - #261: Document the parameters of parallel execution's constructor diff --git a/src/kernel/context/ContextThread.cpp b/src/kernel/context/ContextThread.cpp index 008f641cc5..ab202159bd 100644 --- a/src/kernel/context/ContextThread.cpp +++ b/src/kernel/context/ContextThread.cpp @@ -61,11 +61,6 @@ void ThreadContextFactory::run_all() ThreadContext::ThreadContext(std::function code, void_pfn_smxprocess_t cleanup, smx_actor_t actor, bool maestro) : AttachContext(std::move(code), cleanup, actor), is_maestro_(maestro) { - // We do not need the semaphores when maestro is in main, - // but creating them anyway simplifies things when maestro is externalized - this->begin_ = xbt_os_sem_init(0); - this->end_ = xbt_os_sem_init(0); - /* If the user provided a function for the process then use it */ if (has_code()) { if (smx_context_stack_size_was_set) @@ -78,7 +73,7 @@ ThreadContext::ThreadContext(std::function code, void_pfn_smxprocess_t c * name, but now the name is stored at SIMIX level, so we pass a null */ this->thread_ = xbt_os_thread_create(nullptr, ThreadContext::wrapper, this, this); /* wait the starting of the newly created process */ - xbt_os_sem_acquire(this->end_); + this->end_.acquire(); } /* Otherwise, we attach to the current thread */ @@ -91,10 +86,6 @@ ThreadContext::~ThreadContext() { if (this->thread_) /* If there is a thread (maestro don't have any), wait for its termination */ xbt_os_thread_join(this->thread_, nullptr); - - /* destroy the synchronization objects */ - xbt_os_sem_destroy(this->begin_); - xbt_os_sem_destroy(this->end_); } void *ThreadContext::wrapper(void *param) @@ -110,7 +101,7 @@ void *ThreadContext::wrapper(void *param) sigaltstack(&stack, nullptr); #endif // Tell the caller (normally the maestro) we are starting, and wait for its green light - xbt_os_sem_release(context->end_); + context->end_.release(); context->start(); try { @@ -137,24 +128,24 @@ void *ThreadContext::wrapper(void *param) void ThreadContext::release() { - xbt_os_sem_release(this->begin_); + this->begin_.release(); } void ThreadContext::wait() { - xbt_os_sem_acquire(this->end_); + this->end_.acquire(); } void ThreadContext::start() { - xbt_os_sem_acquire(this->begin_); + this->begin_.acquire(); this->start_hook(); } void ThreadContext::yield() { this->yield_hook(); - xbt_os_sem_release(this->end_); + this->end_.release(); } void ThreadContext::stop() @@ -173,7 +164,7 @@ void ThreadContext::attach_start() { // We're breaking the layers here by depending on the upper layer: ThreadContext* maestro = (ThreadContext*)simix_global->maestro_process->context_; - xbt_os_sem_release(maestro->begin_); + maestro->begin_.release(); xbt_assert(not this->is_maestro()); this->start(); } @@ -184,7 +175,7 @@ void ThreadContext::attach_stop() this->yield(); ThreadContext* maestro = (ThreadContext*)simix_global->maestro_process->context_; - xbt_os_sem_acquire(maestro->end_); + maestro->end_.acquire(); xbt_os_thread_set_extra_data(nullptr); } @@ -203,16 +194,16 @@ void SerialThreadContext::run_all() // ParallelThreadContext -xbt_os_sem_t ParallelThreadContext::thread_sem_ = nullptr; +xbt::OsSemaphore* ParallelThreadContext::thread_sem_ = nullptr; void ParallelThreadContext::initialize() { - thread_sem_ = xbt_os_sem_init(SIMIX_context_get_nthreads()); + thread_sem_ = new xbt::OsSemaphore(SIMIX_context_get_nthreads()); } void ParallelThreadContext::finalize() { - xbt_os_sem_destroy(thread_sem_); + delete thread_sem_; thread_sem_ = nullptr; } @@ -227,13 +218,13 @@ void ParallelThreadContext::run_all() void ParallelThreadContext::start_hook() { if (not is_maestro()) /* parallel run */ - xbt_os_sem_acquire(thread_sem_); + thread_sem_->acquire(); } void ParallelThreadContext::yield_hook() { if (not is_maestro()) /* parallel run */ - xbt_os_sem_release(thread_sem_); + thread_sem_->release(); } XBT_PRIVATE ContextFactory* thread_factory() diff --git a/src/kernel/context/ContextThread.hpp b/src/kernel/context/ContextThread.hpp index cd83102a10..5024b6ff4c 100644 --- a/src/kernel/context/ContextThread.hpp +++ b/src/kernel/context/ContextThread.hpp @@ -10,6 +10,7 @@ #include "simgrid/simix.hpp" #include "src/kernel/context/Context.hpp" +#include "src/xbt/OsSemaphore.hpp" #include "xbt/xbt_os_thread.h" namespace simgrid { @@ -32,10 +33,10 @@ public: private: /** A portable thread */ xbt_os_thread_t thread_ = nullptr; - /** Semaphore used to schedule/yield the process */ - xbt_os_sem_t begin_ = nullptr; - /** Semaphore used to schedule/unschedule */ - xbt_os_sem_t end_ = nullptr; + /** Semaphore used to schedule/yield the process (not needed when the maestro is in main, but harmless then) */ + xbt::OsSemaphore begin_{0}; + /** Semaphore used to schedule/unschedule (not needed when the maestro is in main, but harmless then) */ + xbt::OsSemaphore end_{0}; bool is_maestro_; void start(); // match a call to release() @@ -69,7 +70,7 @@ public: static void run_all(); private: - static xbt_os_sem_t thread_sem_; + static xbt::OsSemaphore* thread_sem_; void start_hook() override; void yield_hook() override; diff --git a/src/simgrid/sg_config.cpp b/src/simgrid/sg_config.cpp index 553d43f539..46eb22c889 100644 --- a/src/simgrid/sg_config.cpp +++ b/src/simgrid/sg_config.cpp @@ -344,7 +344,7 @@ void sg_config_init(int *argc, char **argv) /* synchronization mode for parallel user contexts */ #if HAVE_FUTEX_H std::string default_synchro_mode = "futex"; -#else //No futex on mac and posix is unimplememted yet +#else // No futex on mac and posix is unimplemented yet std::string default_synchro_mode = "busy_wait"; #endif simgrid::config::declare_flag("contexts/synchro", "Synchronization mode to use when running contexts in " diff --git a/src/xbt/xbt_os_thread.c b/src/xbt/xbt_os_thread.c index 5b0f98f71f..fdbbd81026 100644 --- a/src/xbt/xbt_os_thread.c +++ b/src/xbt/xbt_os_thread.c @@ -2,8 +2,7 @@ /* Used in RL to get win/lin portability, and in SG when CONTEXT_THREAD */ /* in SG, when using HAVE_UCONTEXT_CONTEXTS, xbt_os_thread_stub is used instead */ -/* Copyright (c) 2007-2018. The SimGrid Team. - * All rights reserved. */ +/* Copyright (c) 2007-2018. 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. */ diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index d2654e6e21..9ed5340770 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -282,6 +282,7 @@ set(XBT_SRC src/xbt/mallocator.c src/xbt/memory_map.cpp src/xbt/memory_map.hpp + src/xbt/OsSemaphore.hpp src/xbt/parmap.cpp src/xbt/snprintf.c src/xbt/string.cpp -- 2.20.1