1 //  Copyright (c) 2007-2018 Hartmut Kaiser
2 //  Copyright (c)      2011 Bryce Lelbach
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #if !defined(HPX_RUNTIME_RUNTIME_JUN_10_2008_1012AM)
8 #define HPX_RUNTIME_RUNTIME_JUN_10_2008_1012AM
9 
10 #include <hpx/config.hpp>
11 #include <hpx/compat/mutex.hpp>
12 #include <hpx/lcos/local/spinlock.hpp>
13 #include <hpx/performance_counters/counters.hpp>
14 #include <hpx/runtime/applier_fwd.hpp>
15 #include <hpx/runtime/components/component_type.hpp>
16 #include <hpx/runtime/parcelset/locality.hpp>
17 #include <hpx/runtime/parcelset_fwd.hpp>
18 #include <hpx/runtime/runtime_mode.hpp>
19 #include <hpx/runtime/shutdown_function.hpp>
20 #include <hpx/runtime/startup_function.hpp>
21 #include <hpx/runtime/thread_hooks.hpp>
22 #include <hpx/runtime/threads/policies/callback_notifier.hpp>
23 #include <hpx/runtime/threads/topology.hpp>
24 #include <hpx/runtime_fwd.hpp>
25 #include <hpx/state.hpp>
26 #include <hpx/util/runtime_configuration.hpp>
27 #include <hpx/util/thread_specific_ptr.hpp>
28 
29 #include <boost/smart_ptr/scoped_ptr.hpp>
30 
31 #include <atomic>
32 #include <cstddef>
33 #include <cstdint>
34 #include <exception>
35 #include <map>
36 #include <memory>
37 #include <mutex>
38 #include <string>
39 #include <vector>
40 
41 #include <hpx/config/warnings_prefix.hpp>
42 
43 ///////////////////////////////////////////////////////////////////////////////
44 namespace hpx
45 {
46     // \brief Returns if HPX continues past connection signals
47     // caused by crashed nodes
48     HPX_EXPORT bool tolerate_node_faults();
49     namespace util
50     {
51         class thread_mapper;
52         class query_counters;
53         class unique_id_ranges;
54     }
55     namespace components
56     {
57         struct static_factory_load_data_type;
58 
59         namespace server
60         {
61             class runtime_support;
62             class HPX_EXPORT memory;
63         }
64     }
65 
66     namespace performance_counters
67     {
68         class registry;
69     }
70 
71     int pre_main(runtime_mode);
72 
73     ///////////////////////////////////////////////////////////////////////////
74     class HPX_EXPORT runtime_impl;
75 
76     class HPX_EXPORT runtime
77     {
78     public:
79 
get_state() const80         state get_state() const { return state_.load(); }
81 
82         /// The \a hpx_main_function_type is the default function type usable
83         /// as the main HPX thread function.
84         typedef int hpx_main_function_type();
85 
86         ///
87         typedef void hpx_errorsink_function_type(
88             std::uint32_t, std::string const&);
89 
90         /// construct a new instance of a runtime
91         runtime(util::runtime_configuration & rtcfg);
92 
93         virtual ~runtime();
94 
95         /// \brief Manage list of functions to call on exit
on_exit(util::function_nonser<void ()> const & f)96         void on_exit(util::function_nonser<void()> const& f)
97         {
98             std::lock_guard<compat::mutex> l(mtx_);
99             on_exit_functions_.push_back(f);
100         }
101 
102         /// \brief Manage runtime 'stopped' state
starting()103         void starting()
104         {
105             state_.store(state_pre_main);
106         }
107 
108         /// \brief Call all registered on_exit functions
stopping()109         void stopping()
110         {
111             state_.store(state_stopped);
112 
113             typedef util::function_nonser<void()> value_type;
114 
115             std::lock_guard<compat::mutex> l(mtx_);
116             for (value_type const& f : on_exit_functions_)
117                 f();
118         }
119 
120         /// This accessor returns whether the runtime instance has been stopped
stopped() const121         bool stopped() const
122         {
123             return state_.load() == state_stopped;
124         }
125 
126         // the TSS holds a pointer to the runtime associated with a given
127         // OS thread
128         struct tls_tag {};
129         static util::thread_specific_ptr<runtime*, tls_tag> runtime_;
130         static util::thread_specific_ptr<std::string, tls_tag> thread_name_;
131         static util::thread_specific_ptr<std::uint64_t, tls_tag> uptime_;
132 
133         /// \brief access configuration information
get_config()134         util::runtime_configuration& get_config()
135         {
136             return ini_;
137         }
get_config() const138         util::runtime_configuration const& get_config() const
139         {
140             return ini_;
141         }
142 
get_instance_number() const143         std::size_t get_instance_number() const
144         {
145             return static_cast<std::size_t>(instance_number_);
146         }
147 
148         /// \brief Return the name of the calling thread.
149         static std::string get_thread_name();
150 
151         /// \brief Return the system uptime measure on the thread executing this call
152         static std::uint64_t get_system_uptime();
153 
154         /// \brief Allow access to the registry counter registry instance used
155         ///        by the HPX runtime.
156         performance_counters::registry& get_counter_registry();
157 
158         /// \brief Allow access to the registry counter registry instance used
159         ///        by the HPX runtime.
160         performance_counters::registry const& get_counter_registry() const;
161 
162         /// \brief Return a reference to the internal PAPI thread manager
163         util::thread_mapper& get_thread_mapper();
164 
get_topology() const165         threads::topology const& get_topology() const
166         {
167             return topology_;
168         }
169 
170         std::uint32_t assign_cores(std::string const& locality_basename,
171             std::uint32_t num_threads);
172 
173         std::uint32_t assign_cores();
174 
175         /// \brief Install all performance counters related to this runtime
176         ///        instance
177         void register_counter_types();
178 
179         ///////////////////////////////////////////////////////////////////////
180         virtual int run(util::function_nonser<hpx_main_function_type> const& func) = 0;
181 
182         virtual int run() = 0;
183 
184         virtual void rethrow_exception() = 0;
185 
186         virtual int start(util::function_nonser<hpx_main_function_type> const& func,
187             bool blocking = false) = 0;
188 
189         virtual int start(bool blocking = false) = 0;
190 
191         virtual int wait() = 0;
192 
193         virtual void stop(bool blocking = true) = 0;
194 
195         virtual int suspend() = 0;
196         virtual int resume() = 0;
197 
198         virtual parcelset::parcelhandler& get_parcel_handler() = 0;
199         virtual parcelset::parcelhandler const& get_parcel_handler() const = 0;
200 
201         virtual threads::threadmanager& get_thread_manager() = 0;
202 
203         virtual naming::resolver_client& get_agas_client() = 0;
204 
205         virtual parcelset::endpoints_type const& endpoints() const = 0;
206         virtual std::string here() const = 0;
207 
208         virtual applier::applier& get_applier() = 0;
209 
210         virtual std::uint64_t get_runtime_support_lva() const = 0;
211 
212         virtual std::uint64_t get_memory_lva() const = 0;
213 
214         virtual bool report_error(std::size_t num_thread,
215             std::exception_ptr const& e) = 0;
216 
217         virtual bool report_error(std::exception_ptr const& e) = 0;
218 
219         virtual naming::gid_type get_next_id(std::size_t count = 1) = 0;
220 
221         virtual util::unique_id_ranges& get_id_pool() = 0;
222 
223         virtual void add_pre_startup_function(startup_function_type f) = 0;
224 
225         virtual void add_startup_function(startup_function_type f) = 0;
226 
227         virtual void add_pre_shutdown_function(shutdown_function_type f) = 0;
228 
229         virtual void add_shutdown_function(shutdown_function_type f) = 0;
230 
231         /// Access one of the internal thread pools (io_service instances)
232         /// HPX is using to perform specific tasks. The three possible values
233         /// for the argument \p name are "main_pool", "io_pool", "parcel_pool",
234         /// and "timer_pool". For any other argument value the function will
235         /// return zero.
236         virtual hpx::util::io_service_pool* get_thread_pool(char const* name) = 0;
237 
238         /// \brief Register an external OS-thread with HPX
239         ///
240         /// This function should be called from any OS-thread which is external to
241         /// HPX (not created by HPX), but which needs to access HPX functionality,
242         /// such as setting a value on a promise or similar.
243         ///
244         /// \param name             [in] The name to use for thread registration.
245         /// \param num              [in] The sequence number to use for thread
246         ///                         registration. The default for this parameter
247         ///                         is zero.
248         /// \param service_thread   [in] The thread should be registered as a
249         ///                         service thread. The default for this parameter
250         ///                         is 'true'. Any service threads will be pinned
251         ///                         to cores not currently used by any of the HPX
252         ///                         worker threads.
253         ///
254         /// \note The function will compose a thread name of the form
255         ///       '<name>-thread#<num>' which is used to register the thread. It
256         ///       is the user's responsibility to ensure that each (composed)
257         ///       thread name is unique. HPX internally uses the following names
258         ///       for the threads it creates, do not reuse those:
259         ///
260         ///         'main', 'io', 'timer', 'parcel', 'worker'
261         ///
262         /// \note This function should be called for each thread exactly once. It
263         ///       will fail if it is called more than once.
264         ///
265         /// \returns This function will return whether th erequested operation
266         ///          succeeded or not.
267         ///
268         virtual bool register_thread(char const* name, std::size_t num = 0,
269             bool service_thread = true, error_code& ec = throws) = 0;
270 
271         /// \brief Unregister an external OS-thread with HPX
272         ///
273         /// This function will unregister any external OS-thread from HPX.
274         ///
275         /// \note This function should be called for each thread exactly once. It
276         ///       will fail if it is called more than once. It will fail as well
277         ///       if the thread has not been registered before (see
278         ///       \a register_thread).
279         ///
280         /// \returns This function will return whether th erequested operation
281         ///          succeeded or not.
282         ///
283         virtual bool unregister_thread() = 0;
284 
285         /// Generate a new notification policy instance for the given thread
286         /// name prefix
287         typedef threads::policies::callback_notifier notification_policy_type;
288         virtual notification_policy_type
289             get_notification_policy(char const* prefix) = 0;
290 
291         ///////////////////////////////////////////////////////////////////////
292         // management API for active performance counters
293         void register_query_counters(
294             std::shared_ptr<util::query_counters> const& active_counters);
295 
296         void start_active_counters(error_code& ec = throws);
297         void stop_active_counters(error_code& ec = throws);
298         void reset_active_counters(error_code& ec = throws);
299         void reinit_active_counters(bool reset = true, error_code& ec = throws);
300         void evaluate_active_counters(bool reset = false,
301             char const* description = nullptr, error_code& ec = throws);
302 
303         // stop periodic evaluation of counters during shutdown
304         void stop_evaluating_counters();
305 
306         void register_message_handler(char const* message_handler_type,
307             char const* action, error_code& ec = throws);
308         parcelset::policies::message_handler* create_message_handler(
309             char const* message_handler_type, char const* action,
310             parcelset::parcelport* pp, std::size_t num_messages,
311             std::size_t interval, error_code& ec = throws);
312         serialization::binary_filter* create_binary_filter(
313             char const* binary_filter_type, bool compress,
314             serialization::binary_filter* next_filter, error_code& ec = throws);
315 
316         notification_policy_type::on_startstop_type on_start_func() const;
317         notification_policy_type::on_startstop_type on_stop_func() const;
318         notification_policy_type::on_error_type on_error_func() const;
319 
320         notification_policy_type::on_startstop_type on_start_func(
321             notification_policy_type::on_startstop_type&&);
322         notification_policy_type::on_startstop_type on_stop_func(
323             notification_policy_type::on_startstop_type&&);
324         notification_policy_type::on_error_type on_error_func(
325             notification_policy_type::on_error_type&&);
326 
327     protected:
328         void init_tss();
329         void deinit_tss();
330 
331     public:
332         void set_state(state s);
333 
334     protected:
335         // list of functions to call on exit
336         typedef std::vector<util::function_nonser<void()> > on_exit_type;
337         on_exit_type on_exit_functions_;
338         mutable compat::mutex mtx_;
339 
340         util::runtime_configuration ini_;
341         std::shared_ptr<performance_counters::registry> counters_;
342         std::shared_ptr<util::query_counters> active_counters_;
343 
344         long instance_number_;
345         static std::atomic<int> instance_number_counter_;
346 
347         // certain components (such as PAPI) require all threads to be
348         // registered with the library
349         boost::scoped_ptr<util::thread_mapper> thread_support_;
350 
351         // topology and affinity data
352         threads::topology& topology_;
353 
354         // locality basename -> used cores
355         typedef std::map<std::string, std::uint32_t> used_cores_map_type;
356         used_cores_map_type used_cores_map_;
357 
358         std::atomic<state> state_;
359 
360         boost::scoped_ptr<components::server::memory> memory_;
361         boost::scoped_ptr<components::server::runtime_support> runtime_support_;
362 
363         // support tieing in external functions to be called for thread events
364         notification_policy_type::on_startstop_type on_start_func_;
365         notification_policy_type::on_startstop_type on_stop_func_;
366         notification_policy_type::on_error_type on_error_func_;
367     };
368 }   // namespace hpx
369 
370 #include <hpx/config/warnings_suffix.hpp>
371 
372 #endif
373