Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Introduce a portable xbt::OsSemaphore using C++11 threads
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 4 Jan 2019 22:50:59 +0000 (23:50 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 4 Jan 2019 22:50:59 +0000 (23:50 +0100)
ChangeLog
src/kernel/context/ContextThread.cpp
src/kernel/context/ContextThread.hpp
src/simgrid/sg_config.cpp
src/xbt/xbt_os_thread.c
tools/cmake/DefinePackages.cmake

index 121fc47..e9981e0 100644 (file)
--- 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
index 008f641..ab20215 100644 (file)
@@ -61,11 +61,6 @@ void ThreadContextFactory::run_all()
 ThreadContext::ThreadContext(std::function<void()> 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<void()> 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()
index cd83102..5024b6f 100644 (file)
@@ -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;
index 553d43f..46eb22c 100644 (file)
@@ -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<std::string>("contexts/synchro", "Synchronization mode to use when running contexts in "
index 5b0f98f..fdbbd81 100644 (file)
@@ -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. */
index d2654e6..9ed5340 100644 (file)
@@ -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