- 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.
* 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");
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);
-/* 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
#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[]) {
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");
xbt_free(line_char);
}
- xbt_free(line);
fclose(fp);
/* 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
#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>
-/* 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
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_; }
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()
-/* 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. */
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)) {}
+++ /dev/null
-/* 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 */
--- /dev/null
+/* 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 */
-/* 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
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_; }
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)
#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.
class HostModel;
class NetworkModel;
class StorageModel;
-class Resource;
class NetworkCm02Link;
class Action;
}
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
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
/* 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:
/* 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>
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
/* 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_);
}
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;
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()
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()
// 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_);
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
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;
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
/* \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. */
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
}
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
--- /dev/null
+/* 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
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);
}
}
}
/** 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
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()
{
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)
}
// 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]) {
#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"
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) {
result->end = result->end_exec;
xbt_assert(result->start_exec || result->start_rw || result->start_ro);
-
- free(name);
}
/************************************* Take Snapshot ************************************/
// 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:
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;
}
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(); }
#include <libunwind.h>
#include "xbt/base.h"
+#include "xbt/file.hpp"
#include "xbt/log.h"
#include <xbt/mmalloc.h>
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)) {
namespace simgrid {
namespace vm {
-/***********
- * Classes *
- ***********/
-
-class XBT_PRIVATE VMModel;
-XBT_PUBLIC_CLASS VirtualMachineImpl; // Made visible to the Java plugin
-
/*************
* Callbacks *
*************/
* @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{};
#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>
}
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);
#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>
}
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;
}
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').");
}
#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"
#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:
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){
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
#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);
}
/* 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();
#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>
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)
/* 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>
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);
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);
missing_key_error::~missing_key_error() = default;
-class Config;
-
namespace {
const char* true_values[] = {
#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");
/* 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>
#include <xbt/sysdep.h>
#include <xbt/base.h>
-#include <xbt/file.h>
#include <xbt/log.h>
#include "memory_map.hpp"
#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()
ret.push_back(std::move(memreg));
}
- std::free(line);
- std::fclose(fp);
+ fp.close();
#elif defined __FreeBSD__
struct procstat *prstat;
struct kinfo_proc *proc;
+++ /dev/null
-/* 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;
-}
--- /dev/null
+/* 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));
+}
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");
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);
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
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
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
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
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