Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Always call process_on_exit in the actor context
[simgrid.git] / src / kernel / context / Context.cpp
1 /* Copyright (c) 2007-2019. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "mc/mc.h"
7
8 #include "simgrid/s4u/Host.hpp"
9 #include "src/kernel/context/Context.hpp"
10 #include "src/simix/smx_private.hpp"
11 #include "src/surf/surf_interface.hpp"
12
13 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
14
15 /**
16  * @brief creates a new context for a user level process
17  * @param code a main function
18  * @param cleanup_func the function to call when the context stops
19  * @param simix_process
20  */
21 smx_context_t SIMIX_context_new(
22   std::function<void()> code,
23   void_pfn_smxprocess_t cleanup_func,
24   smx_actor_t simix_process)
25 {
26   return simix_global->context_factory->create_context(
27     std::move(code), cleanup_func, simix_process);
28 }
29
30 namespace simgrid {
31 namespace kernel {
32 namespace context {
33
34 ContextFactoryInitializer factory_initializer = nullptr;
35
36 ContextFactory::~ContextFactory() = default;
37
38 static thread_local smx_context_t smx_current_context = nullptr;
39 Context* Context::self()
40 {
41   return smx_current_context;
42 }
43 void Context::set_current(Context* self)
44 {
45   smx_current_context = self;
46 }
47
48 void Context::declare_context(std::size_t size)
49 {
50 #if SIMGRID_HAVE_MC
51   /* Store the address of the stack in heap to compare it apart of heap comparison */
52   if(MC_is_active())
53     MC_ignore_heap(this, size);
54 #endif
55 }
56
57 Context* ContextFactory::attach(void_pfn_smxprocess_t, smx_actor_t)
58 {
59   xbt_die("Cannot attach with this ContextFactory.\n"
60     "Try using --cfg=contexts/factory:thread instead.\n");
61 }
62
63 Context* ContextFactory::create_maestro(std::function<void()>, smx_actor_t)
64 {
65   xbt_die("Cannot create_maestro with this ContextFactory.\n"
66     "Try using --cfg=contexts/factory:thread instead.\n");
67 }
68
69 Context::Context(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t actor)
70     : code_(std::move(code)), cleanup_func_(cleanup_func), actor_(actor)
71 {
72   /* If no function was provided, this is the context for maestro
73    * and we should set it as the current context */
74   if (not has_code())
75     set_current(this);
76 }
77
78 Context::~Context()
79 {
80   if (self() == this)
81     set_current(nullptr);
82 }
83
84 void Context::stop()
85 {
86   actor_->finished_ = true;
87
88   if (actor_->auto_restart_ && actor_->host_->is_off()) {
89     XBT_DEBUG("Insert host %s to watched_hosts because it's off and %s needs to restart", actor_->host_->get_cname(),
90               actor_->get_cname());
91     watched_hosts.insert(actor_->host_->get_cname());
92   }
93
94   actor_->finished_ = true;
95   SIMIX_process_on_exit_runall(actor_);
96
97   if (this->cleanup_func_)
98     this->cleanup_func_(this->actor_);
99
100   this->iwannadie = false; // don't let the simcall's yield() do a Context::stop(), because that's me
101   simgrid::simix::simcall([this] { SIMIX_process_cleanup(this->actor_); });
102   this->iwannadie = true;
103 }
104
105 AttachContext::~AttachContext() = default;
106
107 StopRequest::~StopRequest() = default;
108
109 void StopRequest::do_throw()
110 {
111   throw StopRequest();
112 }
113
114 bool StopRequest::try_n_catch(std::function<void(void)> try_block)
115 {
116   bool res;
117   try {
118     try_block();
119     res = true;
120   } catch (StopRequest const&) {
121     XBT_DEBUG("Caught a StopRequest");
122     res = false;
123   }
124   return res;
125 }
126 }}}
127
128 /** @brief Executes all the processes to run (in parallel if possible). */
129 void SIMIX_context_runall()
130 {
131   simix_global->context_factory->run_all();
132 }