Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / src / simix / UContext.cpp
index a5e8e8f..45b50be 100644 (file)
@@ -8,9 +8,11 @@
 
 #include <stdarg.h>
 
+#include <functional>
+
 #include "xbt/parmap.h"
-#include "smx_private.h"
-#include "smx_private.hpp"
+#include "src/simix/smx_private.h"
+#include "src/simix/smx_private.hpp"
 #include "src/internal_config.h"
 #include "src/context_sysv_config.h"        /* loads context system definitions */
 #include "mc/mc.h"
@@ -34,8 +36,8 @@
  * Makecontext expects integer arguments, we the context
  * variable is decomposed into a serie of integers and
  * each integer is passed as argument to makecontext. */
-XBT_PRIVATE
-void simgrid_makecontext(ucontext* ucp, void (*func)(int first, ...), void* arg)
+static
+void simgrid_makecontext(ucontext_t* ucp, void (*func)(int first, ...), void* arg)
 {
   int ctx_addr[CTX_ADDR_LEN];
   memcpy(ctx_addr, &arg, sizeof(void*));
@@ -63,7 +65,7 @@ namespace simix {
 }
 }
 
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
 static xbt_parmap_t sysv_parmap;
 static simgrid::simix::ParallelUContext** sysv_workers_context;   /* space to save the worker's context in each thread */
 static unsigned long sysv_threads_working;     /* number of threads that have started their work */
@@ -74,6 +76,10 @@ static unsigned long sysv_process_index = 0;   /* index of the next process to r
 static simgrid::simix::UContext* sysv_maestro_context;
 static bool sysv_parallel;
 
+// The name of this function is currently hardcoded in the code (as string).
+// Do not change it without fixing those references as well.
+static void smx_ctx_sysv_wrapper(int first, ...);
+
 namespace simgrid {
 namespace simix {
 
@@ -83,22 +89,16 @@ protected:
   char *stack_ = nullptr; /* the thread stack */
 public:
   friend UContextFactory;
-  UContext(xbt_main_func_t code,
-          int argc, char **argv,
-          void_pfn_smxprocess_t cleanup_func,
-          smx_process_t process);
+  UContext(std::function<void()>  code,
+    void_pfn_smxprocess_t cleanup_func, smx_process_t process);
   ~UContext();
-protected:
-  static void wrapper(int first, ...);
 };
 
 class SerialUContext : public UContext {
 public:
-  SerialUContext(xbt_main_func_t code,
-          int argc, char **argv,
-          void_pfn_smxprocess_t cleanup_func,
-          smx_process_t process)
-    : UContext(code, argc, argv, cleanup_func, process)
+  SerialUContext(std::function<void()>  code,
+      void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+    : UContext(std::move(code), cleanup_func, process)
   {}
   void stop() override;
   void suspend() override;
@@ -107,11 +107,9 @@ public:
 
 class ParallelUContext : public UContext {
 public:
-  ParallelUContext(xbt_main_func_t code,
-          int argc, char **argv,
-          void_pfn_smxprocess_t cleanup_func,
-          smx_process_t process)
-    : UContext(code, argc, argv, cleanup_func, process)
+  ParallelUContext(std::function<void()>  code,
+      void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+    : UContext(std::move(code), cleanup_func, process)
   {}
   void stop() override;
   void suspend() override;
@@ -126,10 +124,8 @@ public:
 
   UContextFactory();
   virtual ~UContextFactory();
-  virtual Context* create_context(
-    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
-    smx_process_t process
-    ) override;
+  virtual Context* create_context(std::function<void()> code,
+    void_pfn_smxprocess_t, smx_process_t process) override;
   void run_all() override;
 };
 
@@ -143,7 +139,7 @@ UContextFactory::UContextFactory() : ContextFactory("UContextFactory")
 {
   if (SIMIX_context_is_parallel()) {
     sysv_parallel = true;
-#ifdef CONTEXT_THREADS  /* To use parallel ucontexts a thread pool is needed */
+#ifdef HAVE_THREAD_CONTEXTS  /* To use parallel ucontexts a thread pool is needed */
     int nthreads = SIMIX_context_get_nthreads();
     sysv_parmap = nullptr;
     sysv_workers_context = xbt_new(ParallelUContext*, nthreads);
@@ -159,7 +155,7 @@ UContextFactory::UContextFactory() : ContextFactory("UContextFactory")
 
 UContextFactory::~UContextFactory()
 {
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
   if (sysv_parmap)
     xbt_parmap_destroy(sysv_parmap);
   xbt_free(sysv_workers_context);
@@ -173,7 +169,7 @@ UContextFactory::~UContextFactory()
 void UContextFactory::run_all()
 {
   if (sysv_parallel) {
-    #ifdef CONTEXT_THREADS
+    #ifdef HAVE_THREAD_CONTEXTS
       sysv_threads_working = 0;
       // Parmap_apply ensures that every working thread get an index in the
       // process_to_run array (through an atomic fetch_and_add),
@@ -207,27 +203,22 @@ void UContextFactory::run_all()
   }
 }
 
-Context* UContextFactory::create_context(
-  xbt_main_func_t code, int argc, char ** argv,
-  void_pfn_smxprocess_t cleanup,
-  smx_process_t process
-  )
+Context* UContextFactory::create_context(std::function<void()> code,
+  void_pfn_smxprocess_t cleanup, smx_process_t process)
 {
   if (sysv_parallel)
-    return new_context<ParallelUContext>(code, argc, argv, cleanup, process);
+    return new_context<ParallelUContext>(std::move(code), cleanup, process);
   else
-    return new_context<SerialUContext>(code, argc, argv, cleanup, process);
+    return new_context<SerialUContext>(std::move(code), cleanup, process);
 }
 
-UContext::UContext(xbt_main_func_t code,
-        int argc, char **argv,
-        void_pfn_smxprocess_t cleanup_func,
-        smx_process_t process)
-  : Context(code, argc, argv, cleanup_func, process)
+UContext::UContext(std::function<void()> code,
+    void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+  : Context(std::move(code), cleanup_func, process)
 {
   /* if the user provided a function for the process then use it,
      otherwise it is the context for maestro */
-  if (code) {
+  if (has_code()) {
     this->stack_ = (char*) SIMIX_context_stack_new();
     getcontext(&this->uc_);
     this->uc_.uc_link = nullptr;
@@ -235,7 +226,7 @@ UContext::UContext(xbt_main_func_t code,
           this->stack_, smx_context_usable_stack_size);
     this->uc_.uc_stack.ss_size = pth_sksize_makecontext(
           this->stack_, smx_context_usable_stack_size);
-    simgrid_makecontext(&this->uc_, UContext::wrapper, this);
+    simgrid_makecontext(&this->uc_, smx_ctx_sysv_wrapper, this);
   } else {
     if (process != NULL && sysv_maestro_context == NULL)
       sysv_maestro_context = this;
@@ -243,7 +234,7 @@ UContext::UContext(xbt_main_func_t code,
 
 #ifdef HAVE_MC
   if (MC_is_active() && code) {
-    MC_register_stack_area(this->stack_, context->process,
+    MC_register_stack_area(this->stack_, process,
                       &(this->uc_), smx_context_usable_stack_size);
   }
 #endif
@@ -254,11 +245,14 @@ UContext::~UContext()
   SIMIX_context_stack_delete(this->stack_);
 }
 
-void UContext::wrapper(int first, ...)
+}
+}
+
+static void smx_ctx_sysv_wrapper(int first, ...)
 {
   // Rebuild the Context* pointer from the integers:
   int ctx_addr[CTX_ADDR_LEN];
-  UContext* context;
+  simgrid::simix::UContext* context;
   ctx_addr[0] = first;
   if (CTX_ADDR_LEN > 1) {
     va_list ap;
@@ -267,12 +261,15 @@ void UContext::wrapper(int first, ...)
       ctx_addr[i] = va_arg(ap, int);
     va_end(ap);
   }
-  memcpy(&context, ctx_addr, sizeof(UContext*));
+  memcpy(&context, ctx_addr, sizeof(simgrid::simix::UContext*));
 
   (*context)();
   context->stop();
 }
 
+namespace simgrid {
+namespace simix {
+
 void SerialUContext::stop()
 {
   Context::stop();
@@ -317,7 +314,7 @@ void ParallelUContext::stop()
 /** Run one particular simulated process on the current thread. */
 void ParallelUContext::resume()
 {
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
   // What is my containing body?
   unsigned long worker_id = __sync_fetch_and_add(&sysv_threads_working, 1);
   // Store the number of my containing body in os-thread-specific area :
@@ -358,7 +355,7 @@ void ParallelUContext::resume()
  */
 void ParallelUContext::suspend()
 {
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
   /* determine the next context */
   // Get the next soul to embody now:
   smx_process_t next_work = (smx_process_t) xbt_parmap_next(sysv_parmap);