#include <stdarg.h>
+#include <functional>
+
#include "xbt/parmap.h"
-#include "smx_private.h"
-#include "smx_private.hpp"
+#include "src/simix/smx_private.h"
+#include "src/simix/smx_private.hpp"
#include "src/internal_config.h"
#include "src/context_sysv_config.h" /* loads context system definitions */
#include "mc/mc.h"
* Makecontext expects integer arguments, we the context
* variable is decomposed into a serie of integers and
* each integer is passed as argument to makecontext. */
-XBT_PRIVATE
-void simgrid_makecontext(ucontext* ucp, void (*func)(int first, ...), void* arg)
+static
+void simgrid_makecontext(ucontext_t* ucp, void (*func)(int first, ...), void* arg)
{
int ctx_addr[CTX_ADDR_LEN];
memcpy(ctx_addr, &arg, sizeof(void*));
}
}
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
static xbt_parmap_t sysv_parmap;
static simgrid::simix::ParallelUContext** sysv_workers_context; /* space to save the worker's context in each thread */
static unsigned long sysv_threads_working; /* number of threads that have started their work */
static simgrid::simix::UContext* sysv_maestro_context;
static bool sysv_parallel;
+// The name of this function is currently hardcoded in the code (as string).
+// Do not change it without fixing those references as well.
+static void smx_ctx_sysv_wrapper(int first, ...);
+
namespace simgrid {
namespace simix {
char *stack_ = nullptr; /* the thread stack */
public:
friend UContextFactory;
- UContext(xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t process);
+ UContext(std::function<void()> code,
+ void_pfn_smxprocess_t cleanup_func, smx_process_t process);
~UContext();
-protected:
- static void wrapper(int first, ...);
};
class SerialUContext : public UContext {
public:
- SerialUContext(xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t process)
- : UContext(code, argc, argv, cleanup_func, process)
+ SerialUContext(std::function<void()> code,
+ void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+ : UContext(std::move(code), cleanup_func, process)
{}
void stop() override;
void suspend() override;
class ParallelUContext : public UContext {
public:
- ParallelUContext(xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t process)
- : UContext(code, argc, argv, cleanup_func, process)
+ ParallelUContext(std::function<void()> code,
+ void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+ : UContext(std::move(code), cleanup_func, process)
{}
void stop() override;
void suspend() override;
UContextFactory();
virtual ~UContextFactory();
- virtual Context* create_context(
- xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
- smx_process_t process
- ) override;
+ virtual Context* create_context(std::function<void()> code,
+ void_pfn_smxprocess_t, smx_process_t process) override;
void run_all() override;
};
{
if (SIMIX_context_is_parallel()) {
sysv_parallel = true;
-#ifdef CONTEXT_THREADS /* To use parallel ucontexts a thread pool is needed */
+#ifdef HAVE_THREAD_CONTEXTS /* To use parallel ucontexts a thread pool is needed */
int nthreads = SIMIX_context_get_nthreads();
sysv_parmap = nullptr;
sysv_workers_context = xbt_new(ParallelUContext*, nthreads);
UContextFactory::~UContextFactory()
{
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
if (sysv_parmap)
xbt_parmap_destroy(sysv_parmap);
xbt_free(sysv_workers_context);
void UContextFactory::run_all()
{
if (sysv_parallel) {
- #ifdef CONTEXT_THREADS
+ #ifdef HAVE_THREAD_CONTEXTS
sysv_threads_working = 0;
// Parmap_apply ensures that every working thread get an index in the
// process_to_run array (through an atomic fetch_and_add),
}
}
-Context* UContextFactory::create_context(
- xbt_main_func_t code, int argc, char ** argv,
- void_pfn_smxprocess_t cleanup,
- smx_process_t process
- )
+Context* UContextFactory::create_context(std::function<void()> code,
+ void_pfn_smxprocess_t cleanup, smx_process_t process)
{
if (sysv_parallel)
- return new_context<ParallelUContext>(code, argc, argv, cleanup, process);
+ return new_context<ParallelUContext>(std::move(code), cleanup, process);
else
- return new_context<SerialUContext>(code, argc, argv, cleanup, process);
+ return new_context<SerialUContext>(std::move(code), cleanup, process);
}
-UContext::UContext(xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t process)
- : Context(code, argc, argv, cleanup_func, process)
+UContext::UContext(std::function<void()> code,
+ void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+ : Context(std::move(code), cleanup_func, process)
{
/* if the user provided a function for the process then use it,
otherwise it is the context for maestro */
- if (code) {
+ if (has_code()) {
this->stack_ = (char*) SIMIX_context_stack_new();
getcontext(&this->uc_);
this->uc_.uc_link = nullptr;
this->stack_, smx_context_usable_stack_size);
this->uc_.uc_stack.ss_size = pth_sksize_makecontext(
this->stack_, smx_context_usable_stack_size);
- simgrid_makecontext(&this->uc_, UContext::wrapper, this);
+ simgrid_makecontext(&this->uc_, smx_ctx_sysv_wrapper, this);
} else {
if (process != NULL && sysv_maestro_context == NULL)
sysv_maestro_context = this;
}
#ifdef HAVE_MC
- if (MC_is_active() && code) {
- MC_register_stack_area(this->stack_, context->process,
+ if (MC_is_active() && has_code()) {
+ MC_register_stack_area(this->stack_, process,
&(this->uc_), smx_context_usable_stack_size);
}
#endif
SIMIX_context_stack_delete(this->stack_);
}
-void UContext::wrapper(int first, ...)
+}
+}
+
+static void smx_ctx_sysv_wrapper(int first, ...)
{
// Rebuild the Context* pointer from the integers:
int ctx_addr[CTX_ADDR_LEN];
- UContext* context;
+ simgrid::simix::UContext* context;
ctx_addr[0] = first;
if (CTX_ADDR_LEN > 1) {
va_list ap;
ctx_addr[i] = va_arg(ap, int);
va_end(ap);
}
- memcpy(&context, ctx_addr, sizeof(UContext*));
+ memcpy(&context, ctx_addr, sizeof(simgrid::simix::UContext*));
(*context)();
context->stop();
}
+namespace simgrid {
+namespace simix {
+
void SerialUContext::stop()
{
Context::stop();
/** Run one particular simulated process on the current thread. */
void ParallelUContext::resume()
{
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
// What is my containing body?
unsigned long worker_id = __sync_fetch_and_add(&sysv_threads_working, 1);
// Store the number of my containing body in os-thread-specific area :
*/
void ParallelUContext::suspend()
{
-#ifdef CONTEXT_THREADS
+#ifdef HAVE_THREAD_CONTEXTS
/* determine the next context */
// Get the next soul to embody now:
smx_process_t next_work = (smx_process_t) xbt_parmap_next(sysv_parmap);