Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorFrederic Suter <frederic.suter@cc.in2p3.fr>
Wed, 25 Oct 2017 21:41:33 +0000 (23:41 +0200)
committerFrederic Suter <frederic.suter@cc.in2p3.fr>
Wed, 25 Oct 2017 21:41:33 +0000 (23:41 +0200)
44 files changed:
ChangeLog
examples/simdag/daxload/sd_daxload.c
examples/smpi/replay_multiple/replay_multiple.c
include/xbt.h
include/xbt/Extendable.hpp
include/xbt/exception.hpp
include/xbt/file.h [deleted file]
include/xbt/file.hpp [new file with mode: 0644]
include/xbt/range.hpp
include/xbt/string.hpp
src/include/surf/maxmin.hpp
src/include/surf/surf.h
src/kernel/EngineImpl.hpp
src/kernel/context/ContextRaw.hpp
src/kernel/context/ContextThread.cpp
src/kernel/context/ContextThread.hpp
src/kernel/context/ContextUnix.cpp
src/kernel/context/ContextUnix.hpp [new file with mode: 0644]
src/kernel/routing/FloydZone.cpp
src/mc/DwarfExpression.hpp
src/mc/LocationList.hpp
src/mc/compare.cpp
src/mc/mc_checkpoint.cpp
src/mc/mc_dwarf.cpp
src/mc/mc_state.hpp
src/mc/remote/RemoteClient.cpp
src/plugins/vm/VirtualMachineImpl.hpp
src/simdag/sd_daxloader.cpp
src/simdag/sd_dotloader.cpp
src/simix/smx_global.cpp
src/simix/smx_host_private.hpp
src/smpi/mpi/smpi_request.cpp
src/surf/cpu_interface.hpp
src/surf/ns3/ns3_simulator.hpp
src/surf/plugins/host_load.cpp
src/surf/xml/surfxml_sax_cb.cpp
src/xbt/backtrace_linux.cpp
src/xbt/config.cpp
src/xbt/graph.c
src/xbt/memory_map.cpp
src/xbt/xbt_os_file.c [deleted file]
src/xbt/xbt_os_file.cpp [new file with mode: 0644]
teshsuite/smpi/timers/timers.c
tools/cmake/DefinePackages.cmake

index 5dc0488..3c8d633 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,11 @@ SimGrid (3.18) NOT RELEASED YET (target: December 24 2017)
  - Storage::getName() changed to return a std::string, use intead
    Storage::getCname() to get a char*.
 
+ XBT
+ - Define class simgrid::xbt::Path to manage file names.
+ - Removed unused functions:
+   - xbt/file.h: xbt_basename(), xbt_dirname(), xbt_getline()
+
 SimGrid (3.17) Released October 8 2017
 
  The Drained Leaks release: (almost) no known leaks despite the tests.
index 8276fc9..e268452 100644 (file)
@@ -7,7 +7,9 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include "simgrid/simdag.h"
-#include "xbt/file.h"
+
+#include <stdio.h>
+#include <string.h>
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(test, "Logging specific to this SimDag example");
 
@@ -79,9 +81,8 @@ int main(int argc, char **argv)
   XBT_INFO("------------------- Run the schedule ---------------------------");
   SD_simulate(-1);
   XBT_INFO("------------------- Produce the trace file---------------------------");
-  char * basename = xbt_basename(tracefilename);
-  XBT_INFO("Producing the trace of the run into %s", basename);
-  free(basename);
+  char* basename = strrchr(tracefilename, '/');
+  XBT_INFO("Producing the trace of the run into %s", basename ? basename + 1 : tracefilename);
   FILE *out = fopen(tracefilename, "w");
   xbt_assert(out, "Cannot write to %s", tracefilename);
   free(tracefilename);
index a7cfeb5..ebb03f3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2015. The SimGrid Team.
+/* Copyright (c) 2009-2017. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -7,6 +7,9 @@
 #include "simgrid/msg.h"
 #include "mpi.h"
 
+#include <stdio.h>
+#include <string.h>
+
 XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test, "Messages specific for this msg example");
 
 static int smpi_replay(int argc, char *argv[]) {
@@ -29,10 +32,10 @@ int main(int argc, char *argv[]){
   FILE* fp = fopen(argv[1], "r");
   if (fp == NULL)
     xbt_die("Cannot open %s", argv[1]);
-  char *line = NULL;
-  size_t n   = 0;
+  char line[2048];
   const char* instance_id = NULL;
-  while (xbt_getline(&line, &n, fp) != -1 ){
+  while (fgets(line, sizeof line, fp)) {
+    xbt_assert(1 + strlen(line) < sizeof line, "input buffer too short (read: %s)", line);
     xbt_dynar_t elems = xbt_str_split_quoted_in_place(line);
     if(xbt_dynar_length(elems)<3){
       xbt_die ("Not enough elements in the line");
@@ -47,7 +50,6 @@ int main(int argc, char *argv[]){
 
     xbt_free(line_char);
   }
-  xbt_free(line);
 
   fclose(fp);
 
index 9d5510e..9dd4caf 100644 (file)
@@ -1,6 +1,6 @@
 /* xbt.h - Public interface to the xbt (SimGrid's toolbox)                  */
 
-/* Copyright (c) 2004-2014. The SimGrid Team.
+/* Copyright (c) 2004-2017. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -12,7 +12,6 @@
 #include <xbt/misc.h>
 #include <xbt/sysdep.h>
 #include <xbt/str.h>
-#include <xbt/file.h>
 #include <xbt/function_types.h>
 
 #include <xbt/asserts.h>
index 1da9b31..785e337 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015. The SimGrid Team.
+/* Copyright (c) 2015, 2017. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@ class Extension {
   static const std::size_t INVALID_ID = std::numeric_limits<std::size_t>::max();
   std::size_t id_;
   friend class Extendable<T>;
-  constexpr Extension(std::size_t id) : id_(id) {}
+  explicit constexpr Extension(std::size_t id) : id_(id) {}
 public:
   explicit constexpr Extension() : id_(INVALID_ID) {}
   std::size_t id() const { return id_; }
@@ -64,7 +64,7 @@ public:
   template<class U> static
   Extension<T,U> extension_create()
   {
-    return extension_create([](void* p){ delete static_cast<U*>(p); });
+    return Extension<T, U>(extension_create([](void* p) { delete static_cast<U*>(p); }));
   }
   Extendable() : extensions_(deleters_.size(), nullptr) {}
   ~Extendable()
index 7c826cd..3d648a1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005-2016. The SimGrid Team.All rights reserved. */
+/* Copyright (c) 2005-2017. 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. */
@@ -99,8 +99,7 @@ class WithContext : public E, public WithContextException
 public:
   static_assert(not std::is_base_of<WithContextException, E>::value, "Trying to appli WithContext twice");
 
-  WithContext(E exception) :
-    E(std::move(exception)) {}
+  explicit WithContext(E exception) : E(std::move(exception)) {}
   WithContext(E exception, ThrowPoint throwpoint, Backtrace backtrace) :
     E(std::move(exception)),
     WithContextException(throwpoint, std::move(backtrace)) {}
diff --git a/include/xbt/file.h b/include/xbt/file.h
deleted file mode 100644 (file)
index 8f6941a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (c) 2007-2015. 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. */
-
-#ifndef XBT_FILE_H
-#define XBT_FILE_H
-
-#include <stdint.h> /* ssize_t */
-#include <stdarg.h>             /* va_* */
-#include <stdio.h>  /* FILE */
-#include <stdlib.h> /* size_t, ssize_t */
-#include "xbt/misc.h"
-#include "xbt/dynar.h"
-#include "xbt/dict.h"
-#include "simgrid_config.h"     /* FILE for getline */
-
-SG_BEGIN_DECL()
-
-/** @defgroup XBT_file File manipulation functions
- *  @ingroup XBT_misc
- *
- * This module redefine some quite classical functions such as xbt_getline() or xbt_dirname() for the platforms
- * lacking them.
- * @{
- */
-/* Our own implementation of getline, mainly useful on the platforms not enjoying this function */
-XBT_PUBLIC(ssize_t) xbt_getline(char **lineptr, size_t * n, FILE * stream);
-
-/* Our own implementation of dirname, that does not exist on windows */
-XBT_PUBLIC(char *) xbt_dirname(const char *path);
-XBT_PUBLIC(char *) xbt_basename(const char *path);
-
-/**@}*/
-
-SG_END_DECL()
-#endif                          /* XBT_FILE_H */
diff --git a/include/xbt/file.hpp b/include/xbt/file.hpp
new file mode 100644 (file)
index 0000000..e642320
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (c) 2017. 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. */
+
+#ifndef XBT_FILE_HPP
+#define XBT_FILE_HPP
+
+#include <string>
+#include <xbt/base.h>
+
+namespace simgrid {
+namespace xbt {
+
+class Path {
+public:
+  explicit Path(const char* path): path_(path) {}
+  explicit Path(std::string path): path_(std::move(path)) {}
+
+  /** @brief Returns the full path name */
+  std::string getName() { return path_; }
+  /** @brief Returns the directory component of a path (reimplementation of POSIX dirname) */
+  std::string getDirname();
+  /** @brief Returns the file component of a path (reimplementation of POSIX basename) */
+  std::string getBasename();
+
+private:
+  std::string path_;
+};
+}}
+
+#endif                          /* XBT_FILE_HPP */
index 5c20a9c..be1e7e8 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016. The SimGrid Team.
+/* Copyright (c) 2016-2017. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -17,7 +17,7 @@ template<class T> class Range {
 public:
   Range()               : begin_(), end_() {}
   Range(T begin, T end) : begin_(std::move(begin)), end_(std::move(end)) {}
-  Range(T value) : begin_(value), end_(value + 1) {}
+  explicit Range(T value) : begin_(value), end_(value + 1) {}
   T& begin()             { return begin_; }
   T& end()               { return end_; }
   const T& begin() const { return begin_; }
index ae6728c..e610b81 100644 (file)
@@ -98,7 +98,7 @@ public:
     s.string_data::len = 0;
     s.string_data::data = &NUL;
   }
-  string(std::string const& s) : string(s.c_str(), s.size()) {}
+  explicit string(std::string const& s) : string(s.c_str(), s.size()) {}
 
   // Assign
   void assign(const char* s, size_t size)
index 1df5043..e0dd9d7 100644 (file)
@@ -7,17 +7,11 @@
 #define SURF_MAXMIN_HPP
 
 #include "src/internal_config.h"
-#include "surf/datatypes.h"
+#include "surf/surf.h"
 #include "xbt/asserts.h"
 #include "xbt/misc.h"
 #include <cmath>
 
-namespace simgrid {
-namespace surf {
-class Action;
-}
-}
-
 /** @addtogroup SURF_lmm
  * @details
  * A linear maxmin solver to resolve inequations systems.
index d83c9a0..837c31f 100644 (file)
@@ -26,7 +26,6 @@ class CpuModel;
 class HostModel;
 class NetworkModel;
 class StorageModel;
-class Resource;
 class NetworkCm02Link;
 class Action;
 }
@@ -37,7 +36,6 @@ typedef simgrid::surf::CpuModel surf_CpuModel;
 typedef simgrid::surf::HostModel surf_HostModel;
 typedef simgrid::surf::NetworkModel surf_NetworkModel;
 typedef simgrid::surf::StorageModel surf_StorageModel;
-typedef simgrid::surf::Resource surf_Resource;
 typedef simgrid::surf::Action surf_Action;
 
 #else
@@ -47,7 +45,6 @@ typedef struct surf_CpuModel surf_CpuModel;
 typedef struct surf_HostModel surf_HostModel;
 typedef struct surf_NetworkModel surf_NetworkModel;
 typedef struct surf_StorageModel surf_StorageModel;
-typedef struct surf_Resource surf_Resource;
 typedef struct surf_Action surf_Action;
 
 #endif
index 39f041a..8593bf8 100644 (file)
@@ -3,16 +3,13 @@
 /* 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 <simgrid/s4u/NetZone.hpp>
 #include <simgrid/s4u/forward.hpp>
 #include <string>
 #include <unordered_map>
 
 namespace simgrid {
 namespace kernel {
-namespace routing {
-class NetZoneImpl;
-class NetPoint;
-}
 
 class EngineImpl {
 public:
index b4f30ec..f2c9bc6 100644 (file)
@@ -3,8 +3,8 @@
 /* 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. */
 
-#ifndef SIMGRID_SIMIX_BOOST_CONTEXT_HPP
-#define SIMGRID_SIMIX_BOOST_CONTEXT_HPP
+#ifndef SIMGRID_SIMIX_RAW_CONTEXT_HPP
+#define SIMGRID_SIMIX_RAW_CONTEXT_HPP
 
 #include <cstdint>
 #include <functional>
index ebcdfbe..8679b20 100644 (file)
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
 
-static xbt_os_sem_t smx_ctx_thread_sem = nullptr;
-
 namespace simgrid {
 namespace kernel {
 namespace context {
 
-XBT_PRIVATE ContextFactory* thread_factory()
-{
-  XBT_VERB("Activating thread context factory");
-  return new ThreadContextFactory();
-}
+// ThreadContextFactory
 
 ThreadContextFactory::ThreadContextFactory()
-  : ContextFactory("ThreadContextFactory")
+    : ContextFactory("ThreadContextFactory"), parallel_(SIMIX_context_is_parallel())
 {
-  if (SIMIX_context_is_parallel()) {
-    smx_ctx_thread_sem = xbt_os_sem_init(SIMIX_context_get_nthreads());
-  } else {
-    smx_ctx_thread_sem = nullptr;
-  }
+  if (parallel_)
+    ParallelThreadContext::initialize();
 }
 
 ThreadContextFactory::~ThreadContextFactory()
 {
-  if (smx_ctx_thread_sem) {
-    xbt_os_sem_destroy(smx_ctx_thread_sem);
-    smx_ctx_thread_sem = nullptr;
-  }
+  if (parallel_)
+    ParallelThreadContext::finalize();
 }
 
-ThreadContext* ThreadContextFactory::create_context(
-    std::function<void()> code,
-    void_pfn_smxprocess_t cleanup, smx_actor_t process)
+ThreadContext* ThreadContextFactory::create_context(std::function<void()> code, void_pfn_smxprocess_t cleanup,
+                                                    smx_actor_t process, bool maestro)
 {
-  return this->new_context<ThreadContext>(std::move(code), cleanup, process, not code);
+  if (parallel_)
+    return this->new_context<ParallelThreadContext>(std::move(code), cleanup, process, maestro);
+  else
+    return this->new_context<SerialThreadContext>(std::move(code), cleanup, process, maestro);
 }
 
 void ThreadContextFactory::run_all()
 {
-  if (smx_ctx_thread_sem == nullptr) {
-    // Serial execution
-    for (smx_actor_t const& process : simix_global->process_to_run) {
-      XBT_DEBUG("Handling %p",process);
-      ThreadContext* context = static_cast<ThreadContext*>(process->context);
-      xbt_os_sem_release(context->begin_);
-      xbt_os_sem_acquire(context->end_);
-    }
-  } else {
+  if (parallel_) {
     // Parallel execution
-    for (smx_actor_t const& process : simix_global->process_to_run)
-      xbt_os_sem_release(static_cast<ThreadContext*>(process->context)->begin_);
-    for (smx_actor_t const& process : simix_global->process_to_run)
-      xbt_os_sem_acquire(static_cast<ThreadContext*>(process->context)->end_);
+    ParallelThreadContext::run_all();
+  } else {
+    // Serial execution
+    SerialThreadContext::run_all();
   }
 }
 
-ThreadContext* ThreadContextFactory::self()
-{
-  return static_cast<ThreadContext*>(xbt_os_thread_get_extra_data());
-}
-
-ThreadContext* ThreadContextFactory::attach(void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
-{
-  return this->new_context<ThreadContext>(
-    std::function<void()>(), cleanup_func, process, false);
-}
-
-ThreadContext* ThreadContextFactory::create_maestro(std::function<void()> code, smx_actor_t process)
-{
-    return this->new_context<ThreadContext>(std::move(code), nullptr, process, true);
-}
+// ThreadContext
 
-ThreadContext::ThreadContext(std::function<void()> code,
-    void_pfn_smxprocess_t cleanup, smx_actor_t process, bool maestro)
-  : AttachContext(std::move(code), cleanup, process)
+ThreadContext::ThreadContext(std::function<void()> code, void_pfn_smxprocess_t cleanup, smx_actor_t process,
+                             bool maestro)
+    : AttachContext(std::move(code), cleanup, process), is_maestro_(maestro)
 {
   // We do not need the semaphores when maestro is in main,
   // but creating them anyway simplifies things when maestro is externalized
@@ -108,10 +77,7 @@ ThreadContext::ThreadContext(std::function<void()> code,
     /* create and start the process */
     /* NOTE: The first argument to xbt_os_thread_create used to be the process *
     * name, but now the name is stored at SIMIX level, so we pass a null  */
-    this->thread_ =
-      xbt_os_thread_create(nullptr,
-        maestro ? &ThreadContext::maestro_wrapper : &ThreadContext::wrapper,
-        this, this);
+    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_);
   }
@@ -144,24 +110,21 @@ void *ThreadContext::wrapper(void *param)
   stack.ss_flags = 0;
   sigaltstack(&stack, nullptr);
 #endif
-  /* Tell the maestro we are starting, and wait for its green light */
+  // Tell the caller (normally the maestro) we are starting, and wait for its green light
   xbt_os_sem_release(context->end_);
-
-  xbt_os_sem_acquire(context->begin_);
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_acquire(smx_ctx_thread_sem);
+  context->start();
 
   try {
     (*context)();
-    context->Context::stop();
+    if (not context->isMaestro()) // really?
+      context->Context::stop();
   } catch (StopRequest const&) {
     XBT_DEBUG("Caught a StopRequest");
+    xbt_assert(not context->isMaestro(), "I'm not supposed to be maestro here.");
   }
 
-  if (smx_ctx_thread_sem)
-    xbt_os_sem_release(smx_ctx_thread_sem);
-  // Signal to the maestro that it has finished:
-  xbt_os_sem_release(context->end_);
+  // Signal to the caller (normally the maestro) that we have finished:
+  context->yield();
 
 #ifndef WIN32
   stack.ss_flags = SS_DISABLE;
@@ -170,40 +133,26 @@ void *ThreadContext::wrapper(void *param)
   return nullptr;
 }
 
-void *ThreadContext::maestro_wrapper(void *param)
+void ThreadContext::release()
 {
-  ThreadContext* context = static_cast<ThreadContext*>(param);
-
-#ifndef WIN32
-  /* Install alternate signal stack, for SIGSEGV handler. */
-  stack_t stack;
-  stack.ss_sp = sigsegv_stack;
-  stack.ss_size = sizeof sigsegv_stack;
-  stack.ss_flags = 0;
-  sigaltstack(&stack, nullptr);
-#endif
-  /* Tell the caller we are starting */
-  xbt_os_sem_release(context->end_);
-
-  // Wait for the caller to give control back to us:
-  xbt_os_sem_acquire(context->begin_);
-  (*context)();
-
-  // Tell main that we have finished:
-  xbt_os_sem_release(context->end_);
+  xbt_os_sem_release(this->begin_);
+}
 
-#ifndef WIN32
-  stack.ss_flags = SS_DISABLE;
-  sigaltstack(&stack, nullptr);
-#endif
-  return nullptr;
+void ThreadContext::wait()
+{
+  xbt_os_sem_acquire(this->end_);
 }
 
 void ThreadContext::start()
 {
   xbt_os_sem_acquire(this->begin_);
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_acquire(smx_ctx_thread_sem);
+  this->start_hook();
+}
+
+void ThreadContext::yield()
+{
+  this->yield_hook();
+  xbt_os_sem_release(this->end_);
 }
 
 void ThreadContext::stop()
@@ -214,12 +163,8 @@ void ThreadContext::stop()
 
 void ThreadContext::suspend()
 {
-  if (smx_ctx_thread_sem)
-    xbt_os_sem_release(smx_ctx_thread_sem);
-  xbt_os_sem_release(this->end_);
-  xbt_os_sem_acquire(this->begin_);
-  if (smx_ctx_thread_sem)
-    xbt_os_sem_acquire(smx_ctx_thread_sem);
+  this->yield();
+  this->start();
 }
 
 void ThreadContext::attach_start()
@@ -227,14 +172,14 @@ 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_);
+  xbt_assert(not this->isMaestro());
   this->start();
 }
 
 void ThreadContext::attach_stop()
 {
-  if (smx_ctx_thread_sem)
-    xbt_os_sem_release(smx_ctx_thread_sem);
-  xbt_os_sem_release(this->end_);
+  xbt_assert(not this->isMaestro());
+  this->yield();
 
   ThreadContext* maestro = (ThreadContext*) simix_global->maestro_process->context;
   xbt_os_sem_acquire(maestro->end_);
@@ -242,4 +187,56 @@ void ThreadContext::attach_stop()
   xbt_os_thread_set_extra_data(nullptr);
 }
 
+// SerialThreadContext
+
+void SerialThreadContext::run_all()
+{
+  for (smx_actor_t const& process : simix_global->process_to_run) {
+    XBT_DEBUG("Handling %p", process);
+    ThreadContext* context = static_cast<ThreadContext*>(process->context);
+    context->release();
+    context->wait();
+  }
+}
+
+// ParallelThreadContext
+
+xbt_os_sem_t ParallelThreadContext::thread_sem_ = nullptr;
+
+void ParallelThreadContext::initialize()
+{
+  thread_sem_ = xbt_os_sem_init(SIMIX_context_get_nthreads());
+}
+
+void ParallelThreadContext::finalize()
+{
+  xbt_os_sem_destroy(thread_sem_);
+  thread_sem_ = nullptr;
+}
+
+void ParallelThreadContext::run_all()
+{
+  for (smx_actor_t const& process : simix_global->process_to_run)
+    static_cast<ThreadContext*>(process->context)->release();
+  for (smx_actor_t const& process : simix_global->process_to_run)
+    static_cast<ThreadContext*>(process->context)->wait();
+}
+
+void ParallelThreadContext::start_hook()
+{
+  if (not isMaestro()) /* parallel run */
+    xbt_os_sem_acquire(thread_sem_);
+}
+
+void ParallelThreadContext::yield_hook()
+{
+  if (not isMaestro()) /* parallel run */
+    xbt_os_sem_release(thread_sem_);
+}
+
+XBT_PRIVATE ContextFactory* thread_factory()
+{
+  XBT_VERB("Activating thread context factory");
+  return new ThreadContextFactory();
+}
 }}} // namespace
index 3449f88..36104b3 100644 (file)
@@ -16,20 +16,19 @@ namespace simgrid {
 namespace kernel {
 namespace context {
 
-class ThreadContext;
-class ThreadContextFactory;
-
 class ThreadContext : public AttachContext {
 public:
-  friend ThreadContextFactory;
-  ThreadContext(std::function<void()> code,
-          void_pfn_smxprocess_t cleanup_func,
-          smx_actor_t process, bool maestro =false);
+  ThreadContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process, bool maestro);
   ~ThreadContext() override;
   void stop() override;
   void suspend() override;
   void attach_start() override;
   void attach_stop() override;
+
+  bool isMaestro() const { return is_maestro_; }
+  void release(); // unblock context's start()
+  void wait();    // wait for context's yield()
+
 private:
   /** A portable thread */
   xbt_os_thread_t thread_ = nullptr;
@@ -37,27 +36,74 @@ private:
   xbt_os_sem_t begin_ = nullptr;
   /** Semaphore used to schedule/unschedule */
   xbt_os_sem_t end_ = nullptr;
+  bool is_maestro_;
+
+  void start();                // match a call to release()
+  void yield();                // match a call to yield()
+  virtual void start_hook() { /* empty placeholder, called after start() */}
+  virtual void yield_hook() { /* empty placeholder, called before yield() */}
 
   static void* wrapper(void *param);
-  static void* maestro_wrapper(void *param);
+};
+
+class SerialThreadContext : public ThreadContext {
+public:
+  SerialThreadContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process, bool maestro)
+      : ThreadContext(std::move(code), cleanup_func, process, maestro)
+  {
+  }
+
+  static void run_all();
+};
+
+class ParallelThreadContext : public ThreadContext {
 public:
-  void start();
+  ParallelThreadContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process,
+                        bool maestro)
+      : ThreadContext(std::move(code), cleanup_func, process, maestro)
+  {
+  }
+
+  static void initialize();
+  static void finalize();
+  static void run_all();
+
+private:
+  static xbt_os_sem_t thread_sem_;
+
+  void start_hook() override;
+  void yield_hook() override;
 };
 
 class ThreadContextFactory : public ContextFactory {
 public:
   ThreadContextFactory();
   ~ThreadContextFactory() override;
-  ThreadContext* create_context(std::function<void()> code,
-    void_pfn_smxprocess_t cleanup_func,  smx_actor_t process) override;
+  ThreadContext* create_context(std::function<void()> code, void_pfn_smxprocess_t cleanup_func,
+                                smx_actor_t process) override
+  {
+    bool maestro = not code;
+    return create_context(std::move(code), cleanup_func, process, maestro);
+  }
   void run_all() override;
-  ThreadContext* self() override;
+  ThreadContext* self() override { return static_cast<ThreadContext*>(xbt_os_thread_get_extra_data()); }
 
   // Optional methods:
-  ThreadContext* attach(void_pfn_smxprocess_t cleanup_func, smx_actor_t process) override;
-  ThreadContext* create_maestro(std::function<void()> code, smx_actor_t process) override;
-};
+  ThreadContext* attach(void_pfn_smxprocess_t cleanup_func, smx_actor_t process) override
+  {
+    return create_context(std::function<void()>(), cleanup_func, process, false);
+  }
+  ThreadContext* create_maestro(std::function<void()> code, smx_actor_t process) override
+  {
+    return create_context(std::move(code), nullptr, process, true);
+  }
+
+private:
+  bool parallel_;
 
+  ThreadContext* create_context(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process,
+                                bool maestro);
+};
 }}} // namespace
 
 #endif
index fd6562f..ea21e25 100644 (file)
@@ -5,25 +5,14 @@
 
 /* \file UContext.cpp Context switching with ucontexts from System V        */
 
-#include <ucontext.h>           /* context relative declarations */
+#include "ContextUnix.hpp"
 
 #include "mc/mc.h"
 #include "src/mc/mc_ignore.h"
 #include "src/simix/ActorImpl.hpp"
-#include "src/simix/smx_private.hpp"
-#include "xbt/parmap.hpp"
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
 
-namespace simgrid {
-namespace kernel {
-namespace context {
-  class UContext;
-  class SerialUContext;
-  class ParallelUContext;
-  class UContextFactory;
-}}}
-
 /** Many integers are needed to store a pointer
  *
  * Support up to two ints. */
@@ -32,187 +21,97 @@ constexpr int CTX_ADDR_LEN = 2;
 static_assert(sizeof(simgrid::kernel::context::UContext*) <= CTX_ADDR_LEN * sizeof(int),
               "Ucontexts are not supported on this arch yet");
 
-/** A better makecontext
- *
- * Makecontext expects integer arguments, we the context
- * variable is decomposed into a serie of integers and
- * each integer is passed as argument to makecontext. */
-static void simgrid_makecontext(ucontext_t* ucp, void (*func)(int, int), simgrid::kernel::context::UContext* arg)
-{
-  int ctx_addr[CTX_ADDR_LEN]{};
-  memcpy(ctx_addr, &arg, sizeof arg);
-  makecontext(ucp, (void (*)())func, 2, ctx_addr[0], ctx_addr[1]);
-}
-
-#if HAVE_THREAD_CONTEXTS
-static simgrid::xbt::Parmap<smx_actor_t>* sysv_parmap;
-static simgrid::kernel::context::UContext** sysv_workers_context; /* space to save the worker's context
-                                                                   * in each thread */
-static uintptr_t sysv_threads_working;     /* number of threads that have started their work */
-static xbt_os_thread_key_t sysv_worker_id_key; /* thread-specific storage for the thread id */
-#endif
-static unsigned long sysv_process_index = 0;   /* index of the next process to run in the
-                                                * list of runnable processes */
-static simgrid::kernel::context::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, int);
+static void smx_ctx_sysv_wrapper(int i1, int i2)
+{
+  // Rebuild the Context* pointer from the integers:
+  int ctx_addr[CTX_ADDR_LEN] = {i1, i2};
+  simgrid::kernel::context::UContext* context;
+  memcpy(&context, ctx_addr, sizeof context);
+
+  try {
+    (*context)();
+    context->Context::stop();
+  } catch (simgrid::kernel::context::Context::StopRequest const&) {
+    XBT_DEBUG("Caught a StopRequest");
+  }
+  context->suspend();
+}
 
 namespace simgrid {
 namespace kernel {
 namespace context {
 
-class UContext : public Context {
-private:
-  ucontext_t uc_;         /* the ucontext that executes the code */
-  char *stack_ = nullptr; /* the thread stack */
-public:
-  friend UContextFactory;
-  UContext(std::function<void()>  code,
-    void_pfn_smxprocess_t cleanup_func, smx_actor_t process);
-  ~UContext() override;
-  void stop() override;
-  static void swap(UContext* from, UContext* to) { swapcontext(&from->uc_, &to->uc_); }
-};
-
-class SerialUContext : public UContext {
-public:
-  SerialUContext(std::function<void()>  code,
-      void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
-    : UContext(std::move(code), cleanup_func, process)
-  {}
-  void suspend() override;
-  void resume();
-};
-
-class ParallelUContext : public UContext {
-public:
-  ParallelUContext(std::function<void()>  code,
-      void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
-    : UContext(std::move(code), cleanup_func, process)
-  {}
-  void suspend() override;
-  void resume();
-};
-
-class UContextFactory : public ContextFactory {
-public:
-  friend UContext;
-  friend SerialUContext;
-  friend ParallelUContext;
-
-  UContextFactory();
-  ~UContextFactory() override;
-  Context* create_context(std::function<void()> code,
-    void_pfn_smxprocess_t cleanup, smx_actor_t process) override;
-  void run_all() override;
-};
-
-XBT_PRIVATE ContextFactory* sysv_factory()
-{
-  XBT_VERB("Activating SYSV context factory");
-  return new UContextFactory();
-}
+// UContextFactory
 
-UContextFactory::UContextFactory() : ContextFactory("UContextFactory")
+UContextFactory::UContextFactory() : ContextFactory("UContextFactory"), parallel_(SIMIX_context_is_parallel())
 {
-  if (SIMIX_context_is_parallel()) {
-    sysv_parallel = true;
-#if HAVE_THREAD_CONTEXTS  /* To use parallel ucontexts a thread pool is needed */
-    int nthreads = SIMIX_context_get_nthreads();
-    sysv_parmap = nullptr;
-    sysv_workers_context = new UContext*[nthreads];
-    sysv_maestro_context = nullptr;
-    xbt_os_thread_key_create(&sysv_worker_id_key);
+  UContext::setMaestro(nullptr);
+  if (parallel_) {
+#if HAVE_THREAD_CONTEXTS
+    ParallelUContext::initialize();
 #else
-    THROWF(arg_error, 0, "No thread support for parallel context execution");
+    xbt_die("No thread support for parallel context execution");
 #endif
-  } else {
-    sysv_parallel = false;
   }
 }
 
 UContextFactory::~UContextFactory()
 {
 #if HAVE_THREAD_CONTEXTS
-  delete sysv_parmap;
-  delete[] sysv_workers_context;
+  if (parallel_)
+    ParallelUContext::finalize();
 #endif
 }
 
-/* This function is called by maestro at the beginning of a scheduling round to get all working threads executing some stuff
- * It is much easier to understand what happens if you see the working threads as bodies that swap their soul for the
- *    ones of the simulated processes that must run.
- */
-void UContextFactory::run_all()
+Context* UContextFactory::create_context(std::function<void()> code, void_pfn_smxprocess_t cleanup, smx_actor_t process)
 {
-  if (sysv_parallel) {
 #if 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),
-      //  and runs the smx_ctx_sysv_resume_parallel function on that index
-
-      // We lazily create the parmap because the parmap creates context
-      // with simix_global->context_factory (which might not be initialized
-      // when bootstrapping):
-      if (sysv_parmap == nullptr)
-        sysv_parmap =
-            new simgrid::xbt::Parmap<smx_actor_t>(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
-
-      sysv_parmap->apply(
-          [](smx_actor_t process) {
-            ParallelUContext* context = static_cast<ParallelUContext*>(process->context);
-            context->resume();
-          },
-          simix_global->process_to_run);
-#else
-      xbt_die("You asked for a parallel execution, but you don't have any threads.");
+  if (parallel_)
+    return new_context<ParallelUContext>(std::move(code), cleanup, process);
+  else
 #endif
-  } else {
-    // Serial:
-    if (simix_global->process_to_run.empty())
-      return;
-
-    smx_actor_t first_process = simix_global->process_to_run.front();
-    sysv_process_index = 1;
-    SerialUContext* context = static_cast<SerialUContext*>(first_process->context);
-    context->resume();
-  }
+    return new_context<SerialUContext>(std::move(code), cleanup, process);
 }
 
-Context* UContextFactory::create_context(std::function<void()> code,
-  void_pfn_smxprocess_t cleanup, smx_actor_t process)
+/* This function is called by maestro at the beginning of a scheduling round to get all working threads executing some
+ * stuff It is much easier to understand what happens if you see the working threads as bodies that swap their soul for
+ * the ones of the simulated processes that must run.
+ */
+void UContextFactory::run_all()
 {
-  if (sysv_parallel)
-    return new_context<ParallelUContext>(std::move(code), cleanup, process);
+#if HAVE_THREAD_CONTEXTS
+  if (parallel_)
+    ParallelUContext::run_all();
   else
-    return new_context<SerialUContext>(std::move(code), cleanup, process);
+#endif
+    SerialUContext::run_all();
 }
 
-UContext::UContext(std::function<void()> code,
-    void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
-  : Context(std::move(code), cleanup_func, process)
+// UContext
+
+UContext* UContext::maestro_context_ = nullptr;
+
+UContext::UContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_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 (has_code()) {
-    this->stack_ = (char*) SIMIX_context_stack_new();
+    this->stack_ = SIMIX_context_stack_new();
     getcontext(&this->uc_);
     this->uc_.uc_link = nullptr;
     this->uc_.uc_stack.ss_sp   = sg_makecontext_stack_addr(this->stack_);
     this->uc_.uc_stack.ss_size = sg_makecontext_stack_size(smx_context_usable_stack_size);
-    simgrid_makecontext(&this->uc_, smx_ctx_sysv_wrapper, this);
+    UContext::make_ctx(&this->uc_, UContext::wrapper, this);
   } else {
-    if (process != nullptr && sysv_maestro_context == nullptr)
-      sysv_maestro_context = this;
+    if (process != nullptr && maestro_context_ == nullptr)
+      maestro_context_ = this;
   }
 
 #if SIMGRID_HAVE_MC
   if (MC_is_active() && has_code()) {
-    MC_register_stack_area(this->stack_, process,
-                      &(this->uc_), smx_context_usable_stack_size);
+    MC_register_stack_area(this->stack_, process, &(this->uc_), smx_context_usable_stack_size);
   }
 #endif
 }
@@ -222,129 +121,173 @@ UContext::~UContext()
   SIMIX_context_stack_delete(this->stack_);
 }
 
-void UContext::stop()
+void UContext::wrapper(int i1, int i2)
 {
-  Context::stop();
-  throw StopRequest();
+  smx_ctx_sysv_wrapper(i1, i2);
 }
-}}} // namespace simgrid::kernel::context
 
-static void smx_ctx_sysv_wrapper(int i1, int i2)
+/** A better makecontext
+ *
+ * Makecontext expects integer arguments, we the context variable is decomposed into a serie of integers and each
+ * integer is passed as argument to makecontext.
+ */
+void UContext::make_ctx(ucontext_t* ucp, void (*func)(int, int), UContext* arg)
 {
-  // Rebuild the Context* pointer from the integers:
-  int ctx_addr[CTX_ADDR_LEN] = {i1, i2};
-  simgrid::kernel::context::UContext* context;
-  memcpy(&context, ctx_addr, sizeof context);
+  int ctx_addr[CTX_ADDR_LEN]{};
+  memcpy(ctx_addr, &arg, sizeof arg);
+  makecontext(ucp, (void (*)())func, 2, ctx_addr[0], ctx_addr[1]);
+}
 
-  try {
-    (*context)();
-    context->Context::stop();
-  } catch (simgrid::kernel::context::Context::StopRequest const&) {
-    XBT_DEBUG("Caught a StopRequest");
-  }
-  context->suspend();
+void UContext::stop()
+{
+  Context::stop();
+  throw StopRequest();
 }
 
-namespace simgrid {
-namespace kernel {
-namespace context {
+// SerialUContext
+
+unsigned long SerialUContext::process_index_; /* index of the next process to run in the list of runnable processes */
 
 void SerialUContext::suspend()
 {
   /* determine the next context */
-  UContext* next_context = nullptr;
-  unsigned long int i    = sysv_process_index;
-  sysv_process_index++;
+  SerialUContext* next_context;
+  unsigned long int i = process_index_;
+  process_index_++;
 
   if (i < simix_global->process_to_run.size()) {
     /* execute the next process */
     XBT_DEBUG("Run next process");
-    next_context = static_cast<UContext*>(simix_global->process_to_run[i]->context);
+    next_context = static_cast<SerialUContext*>(simix_global->process_to_run[i]->context);
   } else {
     /* all processes were run, return to maestro */
     XBT_DEBUG("No more process to run");
-    next_context = sysv_maestro_context;
+    next_context = static_cast<SerialUContext*>(UContext::getMaestro());
   }
   SIMIX_context_set_current(next_context);
   UContext::swap(this, next_context);
 }
 
-// UContextSerial
-
 void SerialUContext::resume()
 {
   SIMIX_context_set_current(this);
-  UContext::swap(sysv_maestro_context, this);
+  UContext::swap(UContext::getMaestro(), this);
 }
 
-/** Run one particular simulated process on the current thread. */
-void ParallelUContext::resume()
+void SerialUContext::run_all()
 {
+  if (simix_global->process_to_run.empty())
+    return;
+  smx_actor_t first_process = simix_global->process_to_run.front();
+  process_index_            = 1;
+  static_cast<SerialUContext*>(first_process->context)->resume();
+}
+
+// ParallelUContext
+
 #if HAVE_THREAD_CONTEXTS
-  // What is my containing body?
-  uintptr_t worker_id = __sync_fetch_and_add(&sysv_threads_working, 1);
-  // Store the number of my containing body in os-thread-specific area :
-  xbt_os_thread_set_specific(sysv_worker_id_key, (void*) worker_id);
-  // Get my current soul:
-  UContext* worker_context = static_cast<UContext*>(SIMIX_context_self());
-  // Write down that this soul is hosted in that body (for now)
-  sysv_workers_context[worker_id] = worker_context;
-  // Write in simix that I switched my soul
-  SIMIX_context_set_current(this);
-   // Actually do that using the relevant library call:
-  UContext::swap(worker_context, this);
-  // No body runs that soul anymore at this point.
-  // Instead the current body took the soul of simulated process
-  // The simulated process wakes back after the call to
-  // "SIMIX_context_suspend(self->context);" within
-  // smx_process.c::SIMIX_process_yield()
 
-  // From now on, the simulated processes will change their
-  // soul with the next soul to execute (in suspend_parallel, below).
-  // When nobody is to be executed in this scheduling round,
-  // the last simulated process will take back the initial
-  // soul of the current working thread
-#endif
+simgrid::xbt::Parmap<smx_actor_t>* ParallelUContext::parmap_;
+uintptr_t ParallelUContext::threads_working_;                      /* number of threads that have started their work */
+xbt_os_thread_key_t ParallelUContext::worker_id_key_;              /* thread-specific storage for the thread id */
+std::vector<ParallelUContext*> ParallelUContext::workers_context_; /* space to save the worker's context
+                                                                    * in each thread */
+
+void ParallelUContext::initialize()
+{
+  parmap_ = nullptr;
+  workers_context_.clear();
+  workers_context_.resize(SIMIX_context_get_nthreads(), nullptr);
+  xbt_os_thread_key_create(&worker_id_key_);
+}
+
+void ParallelUContext::finalize()
+{
+  delete parmap_;
+  parmap_ = nullptr;
+  workers_context_.clear();
+  xbt_os_thread_key_destroy(worker_id_key_);
+}
+
+void ParallelUContext::run_all()
+{
+  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), and runs the ParallelUContext::resume function on that index
+
+  // We lazily create the parmap because the parmap creates context with simix_global->context_factory (which might not
+  // be initialized when bootstrapping):
+  if (parmap_ == nullptr)
+    parmap_ = new simgrid::xbt::Parmap<smx_actor_t>(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
+  parmap_->apply(
+      [](smx_actor_t process) {
+        ParallelUContext* context = static_cast<ParallelUContext*>(process->context);
+        context->resume();
+      },
+      simix_global->process_to_run);
 }
 
 /** Yield
  *
- * This function is called when a simulated process wants to yield back
- * to the maestro in a blocking simcall. This naturally occurs within
- * SIMIX_context_suspend(self->context), called from SIMIX_process_yield()
- * Actually, it does not really yield back to maestro, but into the next
- * process that must be executed. If no one is to be executed, then it
- * yields to the initial soul that was in this working thread (that was
- * saved in resume_parallel).
+ * This function is called when a simulated process wants to yield back to the maestro in a blocking simcall. This
+ * naturally occurs within SIMIX_context_suspend(self->context), called from SIMIX_process_yield() Actually, it does not
+ * really yield back to maestro, but into the next process that must be executed. If no one is to be executed, then it
+ * yields to the initial soul that was in this working thread (that was saved in resume_parallel).
  */
 void ParallelUContext::suspend()
 {
-#if HAVE_THREAD_CONTEXTS
   /* determine the next context */
   // Get the next soul to embody now:
-  boost::optional<smx_actor_t> next_work = sysv_parmap->next();
-  UContext* next_context;
+  boost::optional<smx_actor_t> next_work = parmap_->next();
+  ParallelUContext* next_context;
   if (next_work) {
     // There is a next soul to embody (ie, a next process to resume)
     XBT_DEBUG("Run next process");
-    next_context = static_cast<UContext*>(next_work.get()->context);
+    next_context = static_cast<ParallelUContext*>(next_work.get()->context);
   } else {
     // All processes were run, go to the barrier
     XBT_DEBUG("No more processes to run");
-    // Get back the identity of my body that was stored when starting
-    // the scheduling round
-    uintptr_t worker_id =
-        (uintptr_t) xbt_os_thread_get_specific(sysv_worker_id_key);
+    // Get back the identity of my body that was stored when starting the scheduling round
+    uintptr_t worker_id = reinterpret_cast<uintptr_t>(xbt_os_thread_get_specific(worker_id_key_));
     // Deduce the initial soul of that body
-    next_context = sysv_workers_context[worker_id];
+    next_context = workers_context_[worker_id];
     // When given that soul, the body will wait for the next scheduling round
   }
 
   SIMIX_context_set_current(next_context);
   // Get the next soul to run, either simulated or initial minion's one:
   UContext::swap(this, next_context);
-#endif
 }
 
-}}} // namespace simgrid::kernel::context
+/** Run one particular simulated process on the current thread. */
+void ParallelUContext::resume()
+{
+  // What is my containing body?
+  uintptr_t worker_id = __sync_fetch_and_add(&threads_working_, 1);
+  // Store the number of my containing body in os-thread-specific area :
+  xbt_os_thread_set_specific(worker_id_key_, reinterpret_cast<void*>(worker_id));
+  // Get my current soul:
+  ParallelUContext* worker_context = static_cast<ParallelUContext*>(SIMIX_context_self());
+  // Write down that this soul is hosted in that body (for now)
+  workers_context_[worker_id] = worker_context;
+  // Write in simix that I switched my soul
+  SIMIX_context_set_current(this);
+  // Actually do that using the relevant library call:
+  UContext::swap(worker_context, this);
+  // No body runs that soul anymore at this point.  Instead the current body took the soul of simulated process The
+  // simulated process wakes back after the call to "SIMIX_context_suspend(self->context);" within
+  // smx_process.c::SIMIX_process_yield()
+
+  // From now on, the simulated processes will change their soul with the next soul to execute (in suspend_parallel,
+  // below).  When nobody is to be executed in this scheduling round, the last simulated process will take back the
+  // initial soul of the current working thread
+}
 
+#endif
+
+XBT_PRIVATE ContextFactory* sysv_factory()
+{
+  XBT_VERB("Activating SYSV context factory");
+  return new UContextFactory();
+}
+}}} // namespace simgrid::kernel::context
diff --git a/src/kernel/context/ContextUnix.hpp b/src/kernel/context/ContextUnix.hpp
new file mode 100644 (file)
index 0000000..91badf2
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (c) 2009-2017. 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. */
+
+#ifndef SIMGRID_SIMIX_UNIX_CONTEXT_HPP
+#define SIMGRID_SIMIX_UNIX_CONTEXT_HPP
+
+#include <ucontext.h> /* context relative declarations */
+
+#include <cstdint>
+#include <functional>
+#include <vector>
+
+#include <simgrid/simix.hpp>
+#include <xbt/parmap.hpp>
+#include <xbt/xbt_os_thread.h>
+
+#include "Context.hpp"
+#include "src/internal_config.h"
+#include "src/simix/smx_private.hpp"
+
+namespace simgrid {
+namespace kernel {
+namespace context {
+
+class UContext : public Context {
+public:
+  UContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process);
+  ~UContext() override;
+  void stop() override;
+  virtual void resume() = 0;
+
+  static void swap(UContext* from, UContext* to) { swapcontext(&from->uc_, &to->uc_); }
+  static UContext* getMaestro() { return maestro_context_; }
+  static void setMaestro(UContext* maestro) { maestro_context_ = maestro; }
+
+private:
+  static UContext* maestro_context_;
+  void* stack_ = nullptr; /* the thread stack */
+  ucontext_t uc_;         /* the ucontext that executes the code */
+
+  static void wrapper(int, int);
+  static void make_ctx(ucontext_t* ucp, void (*func)(int, int), UContext* arg);
+};
+
+class SerialUContext : public UContext {
+public:
+  SerialUContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
+      : UContext(std::move(code), cleanup_func, process)
+  {
+  }
+  void suspend() override;
+  void resume() override;
+
+  static void run_all();
+
+private:
+  static unsigned long process_index_;
+};
+
+#if HAVE_THREAD_CONTEXTS
+class ParallelUContext : public UContext {
+public:
+  ParallelUContext(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process)
+      : UContext(std::move(code), cleanup_func, process)
+  {
+  }
+  void suspend() override;
+  void resume() override;
+
+  static void initialize();
+  static void finalize();
+  static void run_all();
+
+private:
+  static simgrid::xbt::Parmap<smx_actor_t>* parmap_;
+  static std::vector<ParallelUContext*> workers_context_;
+  static uintptr_t threads_working_;
+  static xbt_os_thread_key_t worker_id_key_;
+};
+#endif
+
+class UContextFactory : public ContextFactory {
+public:
+  UContextFactory();
+  ~UContextFactory() override;
+  Context* create_context(std::function<void()> code, void_pfn_smxprocess_t cleanup, smx_actor_t process) override;
+  void run_all() override;
+
+private:
+  bool parallel_;
+};
+}}} // namespace
+
+#endif
index b434384..4162fa4 100644 (file)
@@ -191,12 +191,11 @@ void FloydZone::seal()
   for (unsigned int c = 0; c < table_size; c++) {
     for (unsigned int a = 0; a < table_size; a++) {
       for (unsigned int b = 0; b < table_size; b++) {
-        if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX) {
-          if (fabs(TO_FLOYD_COST(a, b) - DBL_MAX) < std::numeric_limits<double>::epsilon() ||
-              (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) < TO_FLOYD_COST(a, b))) {
-            TO_FLOYD_COST(a, b) = TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
-            TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
-          }
+        if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX &&
+            (fabs(TO_FLOYD_COST(a, b) - DBL_MAX) < std::numeric_limits<double>::epsilon() ||
+             (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) < TO_FLOYD_COST(a, b)))) {
+          TO_FLOYD_COST(a, b) = TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
+          TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
         }
       }
     }
index defb89c..38bcbca 100644 (file)
@@ -58,7 +58,7 @@ public:
 /** When an error happens in the execution of a DWARF expression */
 class evaluation_error : std::runtime_error {
 public:
-  evaluation_error(const char* what): std::runtime_error(what) {}
+  explicit evaluation_error(const char* what) : std::runtime_error(what) {}
 };
 
 /** A stack for evaluating a DWARF expression
index 8e4aee3..807291e 100644 (file)
@@ -37,7 +37,9 @@ public:
   LocationListEntry(DwarfExpression expression, range_type range)
     : expression_(std::move(expression)), range_(range)
   {}
-  LocationListEntry(DwarfExpression expression) : expression_(std::move(expression)), range_({0, UINT64_MAX}) {}
+  explicit LocationListEntry(DwarfExpression expression) : expression_(std::move(expression)), range_({0, UINT64_MAX})
+  {
+  }
 
   DwarfExpression& expression()
   {
index 0e3887d..386e017 100644 (file)
@@ -1031,14 +1031,12 @@ int compare_heap_area(simgrid::mc::StateComparator& state, int process_index,
       return 0;
     }
 
-    if (type_size != -1) {
-      if (type_size != (ssize_t) heapinfo1->busy_block.busy_size
-          && type_size != (ssize_t)   heapinfo2->busy_block.busy_size
-          && (type->name.empty() || type->name == "struct s_smx_context")) {
-        if (match_pairs)
-          state.match_equals(previous);
-        return -1;
-      }
+    if (type_size != -1 && type_size != (ssize_t)heapinfo1->busy_block.busy_size &&
+        type_size != (ssize_t)heapinfo2->busy_block.busy_size &&
+        (type->name.empty() || type->name == "struct s_smx_context")) {
+      if (match_pairs)
+        state.match_equals(previous);
+      return -1;
     }
 
     if (heapinfo1->busy_block.size != heapinfo2->busy_block.size)
@@ -1098,12 +1096,11 @@ int compare_heap_area(simgrid::mc::StateComparator& state, int process_index,
     }
 
     // Check if the blocks are already matched together:
-    if (state.equals_to1_(block1, frag1).valid_ && state.equals_to2_(block2, frag2).valid_) {
-      if (offset1==offset2 && state.fragmentsEqual(block1, frag1, block2, frag2)) {
-        if (match_pairs)
-          state.match_equals(previous);
-        return 0;
-      }
+    if (state.equals_to1_(block1, frag1).valid_ && state.equals_to2_(block2, frag2).valid_ && offset1 == offset2 &&
+        state.fragmentsEqual(block1, frag1, block2, frag2)) {
+      if (match_pairs)
+        state.match_equals(previous);
+      return 0;
     }
     // Compare the size of both fragments:
     if (heapinfo1->busy_frag.frag_size[frag1] != heapinfo2->busy_frag.frag_size[frag2]) {
index 1e24eff..aa9f21d 100644 (file)
@@ -18,6 +18,7 @@
 #include "src/internal_config.h"
 #include "src/mc/mc_private.hpp"
 #include "src/smpi/include/private.hpp"
+#include "xbt/file.hpp"
 #include "xbt/mmalloc.h"
 #include "xbt/module.h"
 
@@ -185,18 +186,15 @@ void find_object_address(
   std::vector<simgrid::xbt::VmMap> const& maps,
   simgrid::mc::ObjectInformation* result)
 {
-  char* name = xbt_basename(result->file_name.c_str());
+  std::string name = simgrid::xbt::Path(result->file_name).getBasename();
 
   for (size_t i = 0; i < maps.size(); ++i) {
     simgrid::xbt::VmMap const& reg = maps[i];
     if (maps[i].pathname.empty())
       continue;
-    char* map_basename = xbt_basename(maps[i].pathname.c_str());
-    if (strcmp(name, map_basename) != 0) {
-      free(map_basename);
+    std::string map_basename = simgrid::xbt::Path(maps[i].pathname).getBasename();
+    if (map_basename != name)
       continue;
-    }
-    free(map_basename);
 
     // This is the non-GNU_RELRO-part of the data segment:
     if (reg.prot == PROT_RW) {
@@ -250,8 +248,6 @@ void find_object_address(
     result->end = result->end_exec;
 
   xbt_assert(result->start_exec || result->start_rw || result->start_ro);
-
-  free(name);
 }
 
 /************************************* Take Snapshot ************************************/
@@ -522,12 +518,9 @@ static std::vector<s_fd_infos_t> get_current_fds(pid_t pid)
 
     // If dot_output enabled, do not handle the corresponding file
     if (dot_output != nullptr) {
-      char* link_basename = xbt_basename(link);
-      if (strcmp(link_basename, _sg_mc_dot_output_file) == 0) {
-        free(link_basename);
+      std::string link_basename = simgrid::xbt::Path(link).getBasename();
+      if (link_basename == _sg_mc_dot_output_file)
         continue;
-      }
-      free(link_basename);
     }
 
     // This is probably a shared memory used by lttng-ust:
index 88e1369..5e95580 100644 (file)
@@ -776,7 +776,7 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(
         variable->address = (void *) (base + offset);
       } else
         variable->location_list = {
-          simgrid::dwarf::DwarfExpression(expr, expr + len) };
+            simgrid::dwarf::LocationListEntry(simgrid::dwarf::DwarfExpression(expr, expr + len))};
 
       break;
     }
index edef946..d14e7fd 100644 (file)
@@ -125,7 +125,7 @@ public:
   std::vector<std::vector<simgrid::mc::PatternCommunication>> incomplete_comm_pattern;
   std::vector<unsigned> communicationIndices;
 
-  State(unsigned long state_number);
+  explicit State(unsigned long state_number);
 
   std::size_t interleaveSize() const;
   void addInterleavingSet(smx_actor_t actor) { this->actorStates[actor->pid].consider(); }
index 92a3955..297c545 100644 (file)
@@ -28,6 +28,7 @@
 #include <libunwind.h>
 
 #include "xbt/base.h"
+#include "xbt/file.hpp"
 #include "xbt/log.h"
 #include <xbt/mmalloc.h>
 
@@ -118,17 +119,13 @@ struct s_mc_memory_map_re {
 
 static char* get_lib_name(const char* pathname, s_mc_memory_map_re* res)
 {
-  char* map_basename = xbt_basename(pathname);
+  std::string map_basename = simgrid::xbt::Path(pathname).getBasename();
 
   regmatch_t match;
-  if (regexec(&res->so_re, map_basename, 1, &match, 0)) {
-    free(map_basename);
+  if (regexec(&res->so_re, map_basename.c_str(), 1, &match, 0))
     return nullptr;
-  }
 
-  char* libname = strndup(map_basename, match.rm_so);
-  free(map_basename);
-  map_basename = nullptr;
+  char* libname = strndup(map_basename.c_str(), match.rm_so);
 
   // Strip the version suffix:
   if (libname && not regexec(&res->version_re, libname, 1, &match, 0)) {
index 026071e..771747b 100644 (file)
@@ -21,13 +21,6 @@ typedef struct s_dirty_page* dirty_page_t;
 namespace simgrid {
 namespace vm {
 
-/***********
- * Classes *
- ***********/
-
-class XBT_PRIVATE VMModel;
-XBT_PUBLIC_CLASS VirtualMachineImpl; // Made visible to the Java plugin
-
 /*************
  * Callbacks *
  *************/
@@ -114,7 +107,7 @@ private:
  * @brief SURF VM model interface class
  * @details A model is an object which handle the interactions between its Resources and its Actions
  */
-class VMModel : public surf::HostModel {
+class XBT_PRIVATE VMModel : public surf::HostModel {
 public:
   VMModel();
   void ignoreEmptyVmInPmLMM() override{};
index 409caee..eb18b68 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "simdag_private.hpp"
 #include "simgrid/simdag.h"
-#include "xbt/file.h" /* xbt_basename() */
+#include "xbt/file.hpp"
 #include "xbt/log.h"
 #include "xbt/misc.h"
 #include <map>
@@ -241,9 +241,8 @@ xbt_dynar_t SD_daxload(const char *filename)
   }
 
   if (not acyclic_graph_detail(result)) {
-    char* base = xbt_basename(filename);
-    XBT_ERROR("The DAX described in %s is not a DAG. It contains a cycle.", base);
-    free(base);
+    std::string base = simgrid::xbt::Path(filename).getBasename();
+    XBT_ERROR("The DAX described in %s is not a DAG. It contains a cycle.", base.c_str());
     xbt_dynar_foreach(result, cpt, file)
       SD_task_destroy(file);
     xbt_dynar_free_container(&result);
index 8e3f736..b4f8b3b 100644 (file)
@@ -7,7 +7,7 @@
 #include "simdag_private.hpp"
 #include "simgrid/simdag.h"
 #include "src/internal_config.h"
-#include "xbt/file.h"
+#include "xbt/file.hpp"
 #include <cstring>
 #include <unordered_map>
 
@@ -238,9 +238,8 @@ xbt_dynar_t SD_dotload_generic(const char* filename, bool sequential, bool sched
   }
 
   if (result && not acyclic_graph_detail(result)) {
-    char* base = xbt_basename(filename);
-    XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", base);
-    free(base);
+    std::string base = simgrid::xbt::Path(filename).getBasename();
+    XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", base.c_str());
     xbt_dynar_free(&result);
     result = nullptr;
   }
index d612436..0644ac7 100644 (file)
@@ -66,7 +66,7 @@ public:
 void (*SMPI_switch_data_segment)(int) = nullptr;
 
 int _sg_do_verbose_exit = 1;
-static void inthandler(int ignored)
+static void inthandler(int)
 {
   if ( _sg_do_verbose_exit ) {
      XBT_INFO("CTRL-C pressed. The current status will be displayed before exit (disable that behavior with option 'verbose-exit').");
@@ -79,7 +79,7 @@ static void inthandler(int ignored)
 }
 
 #ifndef _WIN32
-static void segvhandler(int signum, siginfo_t *siginfo, void *context)
+static void segvhandler(int signum, siginfo_t* siginfo, void* /*context*/)
 {
   if (siginfo->si_signo == SIGSEGV && siginfo->si_code == SEGV_ACCERR) {
     fprintf(stderr, "Access violation detected.\n"
index 6943f19..5f49d3f 100644 (file)
 #include "popping_private.hpp"
 #include "simgrid/simix.h"
 
+#include "ActorImpl.hpp"
 #include "src/kernel/activity/ExecImpl.hpp"
 
 /** @brief Host datatype from SIMIX POV */
 namespace simgrid {
 namespace simix {
-class ProcessArg;
 
 class Host {
 public:
index 10a6da2..0ed24fa 100644 (file)
@@ -692,12 +692,11 @@ void Request::finish_wait(MPI_Request* request, MPI_Status * status)
     if (((req->flags_ & ACCUMULATE) != 0) ||
         (datatype->flags() & DT_FLAG_DERIVED)) { // && (not smpi_is_shared(req->old_buf_))){
 
-      if (not smpi_process()->replaying()) {
-        if (smpi_privatize_global_variables != 0 && (static_cast<char*>(req->old_buf_) >= smpi_data_exe_start) &&
-            ((char*)req->old_buf_ < smpi_data_exe_start + smpi_data_exe_size)) {
-          XBT_VERB("Privatization : We are unserializing to a zone in global memory  Switch data segment ");
-          smpi_switch_data_segment(smpi_process()->index());
-        }
+      if (not smpi_process()->replaying() && smpi_privatize_global_variables != 0 &&
+          static_cast<char*>(req->old_buf_) >= smpi_data_exe_start &&
+          static_cast<char*>(req->old_buf_) < smpi_data_exe_start + smpi_data_exe_size) {
+        XBT_VERB("Privatization : We are unserializing to a zone in global memory  Switch data segment ");
+        smpi_switch_data_segment(smpi_process()->index());
       }
 
       if(datatype->flags() & DT_FLAG_DERIVED){
index fc67386..f360cf1 100644 (file)
 namespace simgrid {
 namespace surf {
 
-class CpuModel;
-class Cpu;
-class CpuAction;
-
  /** @ingroup SURF_cpu_interface
  * @brief SURF cpu model interface class
  * @details A model is an object which handle the interactions between its Resources and its Actions
index f339e64..743f003 100644 (file)
@@ -18,7 +18,7 @@
 #include <ns3/point-to-point-helper.h>
 #include <ns3/tcp-socket-factory.h>
 
-class SgFlow {
+class XBT_PRIVATE SgFlow {
 public:
   SgFlow(uint32_t totalBytes, simgrid::surf::NetworkNS3Action* action);
 
index f1e039a..eb057d1 100644 (file)
@@ -125,7 +125,7 @@ static void onHostChange(simgrid::s4u::Host& host)
 }
 
 /* This callback is called when an action (computation, idle, ...) terminates */
-static void onActionStateChange(simgrid::surf::CpuAction* action, simgrid::surf::Action::State previous)
+static void onActionStateChange(simgrid::surf::CpuAction* action, simgrid::surf::Action::State /*previous*/)
 {
   for (simgrid::surf::Cpu* const& cpu : action->cpus()) {
     simgrid::s4u::Host* host = cpu->getHost();
index f67afd6..d1c9456 100644 (file)
@@ -7,7 +7,7 @@
 #include "simgrid/sg_config.h"
 #include "src/kernel/routing/NetPoint.hpp"
 #include "src/surf/network_interface.hpp"
-#include "xbt/file.h"
+#include "xbt/file.hpp"
 
 #include "src/surf/xml/platf_private.hpp"
 #include <boost/algorithm/string.hpp>
@@ -1069,9 +1069,8 @@ void surf_parse_open(const char *file)
   xbt_assert(file, "Cannot parse the nullptr file. Bypassing the parser is strongly deprecated nowadays.");
 
   surf_parsed_filename = xbt_strdup(file);
-  char* dir            = xbt_dirname(file);
-  surf_path.push_back(std::string(dir));
-  xbt_free(dir);
+  std::string dir      = simgrid::xbt::Path(file).getDirname();
+  surf_path.push_back(dir);
 
   surf_file_to_parse = surf_fopen(file, "r");
   if (surf_file_to_parse == nullptr)
index 5b23cb1..c5e7651 100644 (file)
@@ -6,6 +6,8 @@
 /* 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 <cerrno>
+#include <cstring>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -221,9 +223,12 @@ std::vector<std::string> resolveBacktrace(
       int found = 0;
 
       /* let's look for the offset of this library in our addressing space */
-      std::string maps_name = std::string("/proc/") + std::to_string(getpid()) + "maps";
+      std::string maps_name = std::string("/proc/") + std::to_string(getpid()) + "/maps";
       FILE* maps            = fopen(maps_name.c_str(), "r");
-
+      if (maps == nullptr) {
+        XBT_CRITICAL("fopen(\"%s\") failed: %s", maps_name.c_str(), strerror(errno));
+        continue;
+      }
       unsigned long int addr = strtoul(addrs[i].c_str(), &p, 16);
       if (*p != '\0') {
         XBT_CRITICAL("Cannot parse backtrace address '%s' (addr=%#lx)", addrs[i].c_str(), addr);
@@ -322,9 +327,19 @@ std::vector<std::string> resolveBacktrace(
     addrs[i].clear();
 
     /* Mask the bottom of the stack */
-    if (not strncmp("main", line_func, strlen("main")) ||
-        not strncmp("xbt_thread_context_wrapper", line_func, strlen("xbt_thread_context_wrapper")) ||
-        not strncmp("smx_ctx_sysv_wrapper", line_func, strlen("smx_ctx_sysv_wrapper")))
+    const char* const breakers[] = {
+        "main",
+        "_ZN7simgrid6kernel7context13ThreadContext7wrapperE", // simgrid::kernel::context::ThreadContext::wrapper
+        "_ZN7simgrid6kernel7context8UContext7wrapperE"        // simgrid::kernel::context::UContext::wrapper
+    };
+    bool do_break = false;
+    for (const char* b : breakers) {
+      if (strncmp(b, line_func, strlen(b)) == 0) {
+        do_break = true;
+        break;
+      }
+    }
+    if (do_break)
       break;
   }
   pclose(pipe);
index f7d8d81..3632eb1 100644 (file)
@@ -38,8 +38,6 @@ namespace config {
 
 missing_key_error::~missing_key_error() = default;
 
-class Config;
-
 namespace {
 
 const char* true_values[] = {
index b5f95c6..a07efb9 100644 (file)
@@ -12,9 +12,9 @@
 #include "graph_private.h"
 #include "xbt/dict.h"
 #include "xbt/heap.h"
-#include "xbt/file.h"
 
 #include <errno.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_graph, xbt, "Graph");
index ed7ee9d..b575f5e 100644 (file)
@@ -3,9 +3,12 @@
 /* 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 <cstdlib>
 #include <cstdio>
+#include <cstdlib>
 #include <cstring>
+#include <fstream>
+#include <iostream>
+#include <string>
 
 #include <sys/types.h>
 
@@ -45,7 +48,6 @@
 
 #include <xbt/sysdep.h>
 #include <xbt/base.h>
-#include <xbt/file.h>
 #include <xbt/log.h>
 
 #include "memory_map.hpp"
@@ -168,27 +170,23 @@ XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid)
 #elif defined __linux__
   /* Open the actual process's proc maps file and create the memory_map_t */
   /* to be returned. */
-  char* path = bprintf("/proc/%i/maps", (int) pid);
-  FILE *fp = std::fopen(path, "r");
-  if (fp == nullptr) {
-    std::perror("fopen failed");
-    xbt_die("Cannot open %s to investigate the memory map of the process.", path);
+  std::string path = std::string("/proc/") + std::to_string(pid) + "/maps";
+  std::ifstream fp;
+  fp.rdbuf()->pubsetbuf(0, 0);
+  fp.open(path);
+  if (not fp) {
+    std::perror("open failed");
+    xbt_die("Cannot open %s to investigate the memory map of the process.", path.c_str());
   }
-  free(path);
-  setbuf(fp, nullptr);
 
   /* Read one line at the time, parse it and add it to the memory map to be returned */
-  ssize_t read; /* Number of bytes readed */
-  char* line = nullptr;
-  std::size_t n = 0; /* Amount of bytes to read by xbt_getline */
-  while ((read = xbt_getline(&line, &n, fp)) != -1) {
+  std::string sline;
+  while (std::getline(fp, sline)) {
     /**
      * The lines that we read have this format: (This is just an example)
      * 00602000-00603000 rw-p 00002000 00:28 1837264                            <complete-path-to-file>
      */
-
-    /* Wipeout the new line character */
-    line[read - 1] = '\0';
+    char* line = &sline[0];
 
     /* Tokenize the line using spaces as delimiters and store each token in lfields array. We expect 5 tokens for 6 fields */
     char* saveptr = nullptr; // for strtok_r()
@@ -301,8 +299,7 @@ XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid)
     ret.push_back(std::move(memreg));
   }
 
-  std::free(line);
-  std::fclose(fp);
+  fp.close();
 #elif defined __FreeBSD__
   struct procstat *prstat;
   struct kinfo_proc *proc;
diff --git a/src/xbt/xbt_os_file.c b/src/xbt/xbt_os_file.c
deleted file mode 100644 (file)
index 692b7c3..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* xbt_os_file.c -- portable interface to file-related functions            */
-
-/* Copyright (c) 2007-2010, 2012-2017. 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. */
-
-#include "xbt/sysdep.h"
-#include "xbt/file.h"    /* this module */
-#include "xbt/log.h"
-#include "src/internal_config.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include "libgen.h" /* POSIX dirname */
-
-/** @brief Get a single line from the stream (reimplementation of the GNU getline)
- *
- * This is a reimplementation of the GNU getline function, so that our code don't depends on the GNU libc.
- *
- * xbt_getline() reads an entire line from stream, storing the address of the buffer containing the text into *buf.
- * The buffer is null-terminated and includes the newline character, if one was found.
- *
- * If *buf is NULL, then xbt_getline() will allocate a buffer for storing the  line, which should be freed by the user
- * program.
- *
- * Alternatively, before calling xbt_getline(), *buf can contain a pointer to a malloc()-allocated buffer *n bytes in
- * size. If the buffer is not large enough to hold the line, xbt_getline() resizes it with realloc(), updating
- * *buf and *n as necessary.
- *
- * In either case, on a successful call, *buf and *n will be updated to reflect the buffer address and allocated size
- * respectively.
- */
-ssize_t xbt_getline(char **buf, size_t *n, FILE *stream)
-{
-  int ch = getc(stream);
-  if (ferror(stream) || feof(stream))
-    return -1;
-
-  if (!*buf) {
-    *n = 512;
-    *buf = xbt_malloc(*n);
-  }
-
-  ssize_t i = 0;
-  do {
-    if (i == *n) {
-      *n += 512;
-      *buf = xbt_realloc(*buf, *n);
-    }
-    (*buf)[i] = ch;
-    i++;
-    if (ch == '\n')
-      break;
-  } while ((ch = getc(stream)) != EOF);
-
-  if (i == *n) {
-    *n += 1;
-    *buf = xbt_realloc(*buf, *n);
-  }
-  (*buf)[i] = '\0';
-
-  return i;
-}
-
-/** @brief Returns the directory component of a path (reimplementation of POSIX dirname)
- *
- * The argument is never modified, and the returned value must be freed after use.
- */
-char *xbt_dirname(const char *path) {
-  char *tmp = xbt_strdup(path);
-  char *res = xbt_strdup(dirname(tmp));
-  free(tmp);
-  return res;
-}
-
-/** @brief Returns the file component of a path (reimplementation of POSIX basename)
- *
- * The argument is never modified, and the returned value must be freed after use.
- */
-char *xbt_basename(const char *path) {
-  char *tmp = xbt_strdup(path);
-  char *res = xbt_strdup(basename(tmp));
-  free(tmp);
-  return res;
-}
diff --git a/src/xbt/xbt_os_file.cpp b/src/xbt/xbt_os_file.cpp
new file mode 100644 (file)
index 0000000..1248350
--- /dev/null
@@ -0,0 +1,30 @@
+/* xbt_os_file.cpp -- portable interface to file-related functions            */
+
+/* Copyright (c) 2017. 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. */
+
+#include "xbt/file.hpp" /* this module */
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <cstring>
+#include <libgen.h> /* POSIX dirname */
+
+std::string simgrid::xbt::Path::getDirname()
+{
+  std::string p(path_);
+  char *res = dirname(&p[0]);
+  return std::string(res, strlen(res));
+}
+
+std::string simgrid::xbt::Path::getBasename()
+{
+  std::string p(path_);
+  char *res = basename(&p[0]);
+  return std::string(res, strlen(res));
+}
index 18ff5d8..ad0cab5 100644 (file)
@@ -28,7 +28,7 @@ int main(int argc, char* argv[])
   gettimeofday(&tv1, NULL);
   sleep(1);
   gettimeofday(&tv2, NULL);
-  long res = ((tv2.tv_sec * 1000000 + tv2.tv_usec)) - ((tv1.tv_sec * 1000000 + tv1.tv_usec));
+  long res = (tv2.tv_sec * 1000000 + tv2.tv_usec) - (tv1.tv_sec * 1000000 + tv1.tv_usec);
   if (res < 999998 || res > 1000002)
     printf("Error, sleep(1) did not exactly slept 1s\n");
 
@@ -36,7 +36,7 @@ int main(int argc, char* argv[])
   gettimeofday(&tv1, NULL);
   usleep(100);
   gettimeofday(&tv2, NULL);
-  res = ((tv2.tv_sec * 1000000 + tv2.tv_usec)) - ((tv1.tv_sec * 1000000 + tv1.tv_usec));
+  res = (tv2.tv_sec * 1000000 + tv2.tv_usec) - (tv1.tv_sec * 1000000 + tv1.tv_usec);
   if (res < 98 || res > 102)
     printf("Error, usleep did not really sleep 100us, but %ld\n", res);
 
@@ -48,7 +48,7 @@ int main(int argc, char* argv[])
   struct timespec tpsleep;
   clock_gettime(CLOCK_REALTIME, &tp1);
   clock_gettime(CLOCK_REALTIME, &tp2);
-  if ((tp1.tv_sec != tp2.tv_sec) || (tp1.tv_nsec != tp2.tv_nsec))
+  if (tp1.tv_sec != tp2.tv_sec || tp1.tv_nsec != tp2.tv_nsec)
     printf("Error, two consecutive calls to gettimeofday did not return same time (with running power to 0)\n");
 
   // nanosleep for 100ns
@@ -57,7 +57,7 @@ int main(int argc, char* argv[])
   tpsleep.tv_nsec = 100;
   nanosleep(&tpsleep, NULL);
   clock_gettime(CLOCK_REALTIME, &tp2);
-  res = ((tp2.tv_sec * 1000000000 + tp2.tv_nsec)) - ((tp1.tv_sec * 1000000000 + tp1.tv_nsec));
+  res = (tp2.tv_sec * 1000000000 + tp2.tv_nsec) - (tp1.tv_sec * 1000000000 + tp1.tv_nsec);
   if (res < 98 || res > 102)
     printf("Error, nanosleep did not really sleep 100ns, but %ld\n", res);
 #endif
index 802efdd..cae9f73 100644 (file)
@@ -288,7 +288,7 @@ set(XBT_SRC
   src/xbt/xbt_log_layout_format.c
   src/xbt/xbt_log_layout_simple.c
   src/xbt/xbt_main.cpp
-  src/xbt/xbt_os_file.c
+  src/xbt/xbt_os_file.cpp
   src/xbt/xbt_os_synchro.cpp
   src/xbt/xbt_os_time.c
   src/xbt/xbt_replay.cpp
@@ -716,7 +716,7 @@ set(headers_to_install
   include/xbt/ex.hpp
   include/xbt/exception.hpp
   include/xbt/Extendable.hpp
-  include/xbt/file.h
+  include/xbt/file.hpp
   include/xbt/functional.hpp
   include/xbt/function_types.h
   include/xbt/future.hpp
@@ -766,9 +766,11 @@ else() # NOT pthread
 endif()
 
 if(${HAVE_UCONTEXT_CONTEXTS}) #ucontext
-  set(SURF_SRC    ${SURF_SRC}   src/kernel/context/ContextUnix.cpp)
+  set(SURF_SRC    ${SURF_SRC}   src/kernel/context/ContextUnix.hpp
+                                src/kernel/context/ContextUnix.cpp)
 else() # NOT ucontext
-  set(EXTRA_DIST  ${EXTRA_DIST} src/kernel/context/ContextUnix.cpp)
+  set(EXTRA_DIST  ${EXTRA_DIST} src/kernel/context/ContextUnix.hpp
+                                src/kernel/context/ContextUnix.cpp)
 endif()
 
 ### Simgrid Lib sources