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 #include <hpx/config.hpp>
8 #include <hpx/compat/mutex.hpp>
9 #include <hpx/exception.hpp>
10 #include <hpx/performance_counters/counter_creators.hpp>
11 #include <hpx/performance_counters/counters.hpp>
12 #include <hpx/performance_counters/manage_counter_type.hpp>
13 #include <hpx/performance_counters/registry.hpp>
14 #include <hpx/runtime.hpp>
15 #include <hpx/runtime/thread_hooks.hpp>
16 #include <hpx/runtime/agas/addressing_service.hpp>
17 #include <hpx/runtime/applier/applier.hpp>
18 #include <hpx/runtime/components/server/memory.hpp>
19 #include <hpx/runtime/components/server/runtime_support.hpp>
20 #include <hpx/runtime/components/server/simple_component_base.hpp>    // EXPORTS get_next_id
21 #include <hpx/runtime/config_entry.hpp>
22 #include <hpx/runtime/launch_policy.hpp>
23 #include <hpx/runtime/parcelset/parcelhandler.hpp>
24 #include <hpx/runtime/threads/coroutines/coroutine.hpp>
25 #include <hpx/runtime/threads/policies/scheduler_mode.hpp>
26 #include <hpx/runtime/threads/threadmanager.hpp>
27 #include <hpx/runtime/threads/topology.hpp>
28 #include <hpx/state.hpp>
29 #include <hpx/util/assert.hpp>
30 #include <hpx/util/backtrace.hpp>
31 #include <hpx/util/command_line_handling.hpp>
32 #include <hpx/util/debugging.hpp>
33 #include <hpx/util/high_resolution_clock.hpp>
34 #include <hpx/util/logging.hpp>
35 #include <hpx/util/query_counters.hpp>
36 #include <hpx/util/static_reinit.hpp>
37 #include <hpx/util/thread_mapper.hpp>
38 #include <hpx/version.hpp>
39 
40 #include <atomic>
41 #include <cstddef>
42 #include <cstdint>
43 #include <exception>
44 #include <iostream>
45 #include <memory>
46 #include <mutex>
47 #include <string>
48 #include <utility>
49 #include <vector>
50 
51 #if defined(_WIN64) && defined(_DEBUG) && !defined(HPX_HAVE_FIBER_BASED_COROUTINES)
52 #include <io.h>
53 #endif
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 // Make sure the system gets properly shut down while handling Ctrl-C and other
57 // system signals
58 #if defined(HPX_WINDOWS)
59 
60 namespace hpx
61 {
62     ///////////////////////////////////////////////////////////////////////////
handle_termination(char const * reason)63     void handle_termination(char const* reason)
64     {
65         if (get_config_entry("hpx.attach_debugger", "") == "exception")
66         {
67             util::attach_debugger();
68         }
69 
70         if (get_config_entry("hpx.diagnostics_on_terminate", "1") == "1")
71         {
72             std::cerr
73 #if defined(HPX_HAVE_STACKTRACES)
74                 << "{stack-trace}: " << hpx::util::trace() << "\n"
75 #endif
76                 << "{what}: " << (reason ? reason : "Unknown reason") << "\n"
77                 << full_build_string();           // add full build information
78         }
79     }
80 
termination_handler(DWORD ctrl_type)81     HPX_EXPORT BOOL WINAPI termination_handler(DWORD ctrl_type)
82     {
83         switch (ctrl_type) {
84         case CTRL_C_EVENT:
85             handle_termination("Ctrl-C");
86             return TRUE;
87 
88         case CTRL_BREAK_EVENT:
89             handle_termination("Ctrl-Break");
90             return TRUE;
91 
92         case CTRL_CLOSE_EVENT:
93             handle_termination("Ctrl-Close");
94             return TRUE;
95 
96         case CTRL_LOGOFF_EVENT:
97             handle_termination("Logoff");
98             return TRUE;
99 
100         case CTRL_SHUTDOWN_EVENT:
101             handle_termination("Shutdown");
102             return TRUE;
103 
104         default:
105             break;
106         }
107         return FALSE;
108     }
109 }
110 
111 #else
112 
113 #include <signal.h>
114 #include <stdlib.h>
115 #include <string.h>
116 
117 namespace hpx
118 {
119     ///////////////////////////////////////////////////////////////////////////
termination_handler(int signum)120     HPX_EXPORT HPX_NORETURN void termination_handler(int signum)
121     {
122         if (signum != SIGINT &&
123             get_config_entry("hpx.attach_debugger", "") == "exception")
124         {
125             util::attach_debugger();
126         }
127 
128         if (get_config_entry("hpx.diagnostics_on_terminate", "1") == "1")
129         {
130             char* reason = strsignal(signum);
131             std::cerr
132 #if defined(HPX_HAVE_STACKTRACES)
133                 << "{stack-trace}: " << hpx::util::trace() << "\n"
134 #endif
135                 << "{what}: " << (reason ? reason : "Unknown signal") << "\n"
136                 << full_build_string();           // add full build information
137         }
138         std::abort();
139     }
140 }
141 
142 #endif
143 
144 ///////////////////////////////////////////////////////////////////////////////
145 namespace hpx
146 {
147     ///////////////////////////////////////////////////////////////////////////
148     // There is no need to protect these global from thread concurrent access
149     // as they are access during early startup only.
150     std::vector<hpx::util::tuple<char const*, char const*> >
151         message_handler_registrations;
152 
153     ///////////////////////////////////////////////////////////////////////////
new_handler()154     HPX_EXPORT void HPX_CDECL new_handler()
155     {
156         HPX_THROW_EXCEPTION(out_of_memory, "new_handler",
157             "new allocator failed to allocate memory");
158     }
159 
set_error_handlers()160     void set_error_handlers()
161     {
162 #if defined(HPX_WINDOWS)
163         // Set console control handler to allow server to be stopped.
164         SetConsoleCtrlHandler(hpx::termination_handler, TRUE);
165 #else
166         struct sigaction new_action;
167         new_action.sa_handler = hpx::termination_handler;
168         sigemptyset(&new_action.sa_mask);
169         new_action.sa_flags = 0;
170 
171         sigaction(SIGINT, &new_action, nullptr);  // Interrupted
172         sigaction(SIGBUS, &new_action, nullptr);  // Bus error
173         sigaction(SIGFPE, &new_action, nullptr);  // Floating point exception
174         sigaction(SIGILL, &new_action, nullptr);  // Illegal instruction
175         sigaction(SIGPIPE, &new_action, nullptr); // Bad pipe
176         sigaction(SIGSEGV, &new_action, nullptr); // Segmentation fault
177         sigaction(SIGSYS, &new_action, nullptr);  // Bad syscall
178 #endif
179 
180         std::set_new_handler(hpx::new_handler);
181     }
182 
183 
184     ///////////////////////////////////////////////////////////////////////////
185     namespace strings
186     {
187         char const* const runtime_mode_names[] =
188         {
189             "invalid",    // -1
190             "console",    // 0
191             "worker",     // 1
192             "connect",    // 2
193             "default",    // 3
194         };
195     }
196 
get_runtime_mode_name(runtime_mode state)197     char const* get_runtime_mode_name(runtime_mode state)
198     {
199         if (state < runtime_mode_invalid || state >= runtime_mode_last)
200             return "invalid (value out of bounds)";
201         return strings::runtime_mode_names[state+1];
202     }
203 
get_runtime_mode_from_name(std::string const & mode)204     runtime_mode get_runtime_mode_from_name(std::string const& mode)
205     {
206         for (std::size_t i = 0; i < runtime_mode_last; ++i) {
207             if (mode == strings::runtime_mode_names[i])
208                 return static_cast<runtime_mode>(i-1);
209         }
210         return runtime_mode_invalid;
211     }
212 
213     namespace strings
214     {
215         char const* const runtime_state_names[] =
216         {
217             "state_invalid",      // -1
218             "state_initialized",  // 0
219             "state_pre_startup",  // 1
220             "state_startup",      // 2
221             "state_pre_main",     // 3
222             "state_starting",     // 4
223             "state_running",      // 5
224             "state_suspended",    // 6
225             "state_pre_sleep",    // 7
226             "state_sleeping",     // 8
227             "state_pre_shutdown", // 9
228             "state_shutdown",     // 10
229             "state_stopping",     // 11
230             "state_terminating",  // 12
231             "state_stopped"       // 13
232         };
233     }
234 
get_runtime_state_name(state st)235     char const* get_runtime_state_name(state st)
236     {
237         if (st < state_invalid || st >= last_valid_runtime_state)
238             return "invalid (value out of bounds)";
239         return strings::runtime_state_names[st+1];
240     }
241 
242     ///////////////////////////////////////////////////////////////////////////
243     threads::policies::callback_notifier::on_startstop_type global_on_start_func;
244     threads::policies::callback_notifier::on_startstop_type global_on_stop_func;
245     threads::policies::callback_notifier::on_error_type global_on_error_func;
246 
247     ///////////////////////////////////////////////////////////////////////////
runtime(util::runtime_configuration & rtcfg)248     runtime::runtime(util::runtime_configuration & rtcfg)
249       : ini_(rtcfg),
250         instance_number_(++instance_number_counter_),
251         thread_support_(new util::thread_mapper),
252         topology_(resource::get_partitioner().get_topology()),
253         state_(state_invalid),
254         memory_(new components::server::memory),
255         runtime_support_(new components::server::runtime_support(ini_)),
256         on_start_func_(global_on_start_func),
257         on_stop_func_(global_on_stop_func),
258         on_error_func_(global_on_error_func)
259     {
260         LPROGRESS_;
261 
262         // initialize our TSS
263         runtime::init_tss();
264         util::reinit_construct();       // call only after TLS was initialized
265 
266         counters_ = std::make_shared<performance_counters::registry>();
267     }
268 
~runtime()269     runtime::~runtime()
270     {
271         // allow to reuse instance number if this was the only instance
272         if (0 == instance_number_counter_)
273             --instance_number_counter_;
274 
275         util::reinit_destruct();
276         resource::detail::delete_partitioner();
277     }
278 
set_state(state s)279     void runtime::set_state(state s)
280     {
281         LPROGRESS_ << get_runtime_state_name(s);
282         state_.store(s);
283     }
284 
285     ///////////////////////////////////////////////////////////////////////////
286     std::atomic<int> runtime::instance_number_counter_(-1);
287 
288     ///////////////////////////////////////////////////////////////////////////
289     util::thread_specific_ptr<runtime*, runtime::tls_tag> runtime::runtime_;
290     util::thread_specific_ptr<std::string, runtime::tls_tag> runtime::thread_name_;
291     util::thread_specific_ptr<std::uint64_t, runtime::tls_tag> runtime::uptime_;
292 
init_tss()293     void runtime::init_tss()
294     {
295         // initialize our TSS
296         if (nullptr == runtime::runtime_.get())
297         {
298             HPX_ASSERT(nullptr == threads::thread_self::get_self());
299 
300             runtime::runtime_.reset(new runtime* (this));
301             runtime::uptime_.reset(new std::uint64_t);
302             *runtime::uptime_.get() = util::high_resolution_clock::now();
303 
304             threads::thread_self::init_self(); // done in resource_partitioner
305         }
306     }
307 
deinit_tss()308     void runtime::deinit_tss()
309     {
310         // reset our TSS
311         threads::thread_self::reset_self();
312         runtime::uptime_.reset();
313         runtime::runtime_.reset();
314         util::reset_held_lock_data();
315 
316         threads::reset_continuation_recursion_count();
317     }
318 
get_thread_name()319     std::string runtime::get_thread_name()
320     {
321         std::string const* str = runtime::thread_name_.get();
322         return str ? *str : "<unknown>";
323     }
324 
get_system_uptime()325     std::uint64_t runtime::get_system_uptime()
326     {
327         std::int64_t diff =
328             util::high_resolution_clock::now() - *runtime::uptime_.get();
329         return diff < 0LL ? 0ULL : static_cast<std::uint64_t>(diff);
330     }
331 
get_counter_registry()332     performance_counters::registry& runtime::get_counter_registry()
333     {
334         return *counters_;
335     }
336 
get_counter_registry() const337     performance_counters::registry const& runtime::get_counter_registry() const
338     {
339         return *counters_;
340     }
341 
get_thread_mapper()342     util::thread_mapper& runtime::get_thread_mapper()
343     {
344         return *thread_support_;
345     }
346 
347     ///////////////////////////////////////////////////////////////////////////
register_query_counters(std::shared_ptr<util::query_counters> const & active_counters)348     void runtime::register_query_counters(
349         std::shared_ptr<util::query_counters> const& active_counters)
350     {
351         active_counters_ = active_counters;
352     }
353 
start_active_counters(error_code & ec)354     void runtime::start_active_counters(error_code& ec)
355     {
356         if (active_counters_.get())
357             active_counters_->start_counters(ec);
358     }
359 
stop_active_counters(error_code & ec)360     void runtime::stop_active_counters(error_code& ec)
361     {
362         if (active_counters_.get())
363             active_counters_->stop_counters(ec);
364     }
365 
reset_active_counters(error_code & ec)366     void runtime::reset_active_counters(error_code& ec)
367     {
368         if (active_counters_.get())
369             active_counters_->reset_counters(ec);
370     }
371 
reinit_active_counters(bool reset,error_code & ec)372     void runtime::reinit_active_counters(bool reset, error_code& ec)
373     {
374         if (active_counters_.get())
375             active_counters_->reinit_counters(reset, ec);
376     }
377 
evaluate_active_counters(bool reset,char const * description,error_code & ec)378     void runtime::evaluate_active_counters(bool reset,
379         char const* description, error_code& ec)
380     {
381         if (active_counters_.get())
382             active_counters_->evaluate_counters(reset, description, ec);
383     }
384 
stop_evaluating_counters()385     void runtime::stop_evaluating_counters()
386     {
387         if (active_counters_.get())
388             active_counters_->stop_evaluating_counters();
389     }
390 
register_message_handler(char const * message_handler_type,char const * action,error_code & ec)391     void runtime::register_message_handler(char const* message_handler_type,
392         char const* action, error_code& ec)
393     {
394         return runtime_support_->register_message_handler(
395             message_handler_type, action, ec);
396     }
397 
create_message_handler(char const * message_handler_type,char const * action,parcelset::parcelport * pp,std::size_t num_messages,std::size_t interval,error_code & ec)398     parcelset::policies::message_handler* runtime::create_message_handler(
399         char const* message_handler_type, char const* action,
400         parcelset::parcelport* pp, std::size_t num_messages,
401         std::size_t interval, error_code& ec)
402     {
403         return runtime_support_->create_message_handler(message_handler_type,
404             action, pp, num_messages, interval, ec);
405     }
406 
create_binary_filter(char const * binary_filter_type,bool compress,serialization::binary_filter * next_filter,error_code & ec)407     serialization::binary_filter* runtime::create_binary_filter(
408         char const* binary_filter_type, bool compress,
409         serialization::binary_filter* next_filter, error_code& ec)
410     {
411         return runtime_support_->create_binary_filter(binary_filter_type,
412             compress, next_filter, ec);
413     }
414 
415     /// \brief Register all performance counter types related to this runtime
416     ///        instance
register_counter_types()417     void runtime::register_counter_types()
418     {
419         performance_counters::generic_counter_type_data statistic_counter_types[] =
420         {
421             // averaging counter
422             { "/statistics/average", performance_counters::counter_aggregating,
423               "returns the averaged value of its base counter over "
424               "an arbitrary time line; pass required base counter as the instance "
425               "name: /statistics{<base_counter_name>}/average",
426               HPX_PERFORMANCE_COUNTER_V1,
427               &performance_counters::detail::statistics_counter_creator,
428               &performance_counters::default_counter_discoverer,
429               ""
430             },
431 
432             // stddev counter
433             { "/statistics/stddev", performance_counters::counter_aggregating,
434               "returns the standard deviation value of its base counter over "
435               "an arbitrary time line; pass required base counter as the instance "
436               "name: /statistics{<base_counter_name>}/stddev",
437               HPX_PERFORMANCE_COUNTER_V1,
438               &performance_counters::detail::statistics_counter_creator,
439               &performance_counters::default_counter_discoverer,
440               ""
441             },
442 
443             // rolling_averaging counter
444             { "/statistics/rolling_average", performance_counters::counter_aggregating,
445               "returns the rolling average value of its base counter over "
446               "an arbitrary time line; pass required base counter as the instance "
447               "name: /statistics{<base_counter_name>}/rolling_averaging",
448               HPX_PERFORMANCE_COUNTER_V1,
449               &performance_counters::detail::statistics_counter_creator,
450               &performance_counters::default_counter_discoverer,
451               ""
452             },
453 
454             // rolling stddev counter
455             { "/statistics/rolling_stddev", performance_counters::counter_aggregating,
456               "returns the rolling standard deviation value of its base counter over "
457               "an arbitrary time line; pass required base counter as the instance "
458               "name: /statistics{<base_counter_name>}/rolling_stddev",
459               HPX_PERFORMANCE_COUNTER_V1,
460               &performance_counters::detail::statistics_counter_creator,
461               &performance_counters::default_counter_discoverer,
462               ""
463             },
464 
465             // median counter
466             { "/statistics/median", performance_counters::counter_aggregating,
467               "returns the median value of its base counter over "
468               "an arbitrary time line; pass required base counter as the instance "
469               "name: /statistics{<base_counter_name>}/median",
470               HPX_PERFORMANCE_COUNTER_V1,
471               &performance_counters::detail::statistics_counter_creator,
472               &performance_counters::default_counter_discoverer,
473               ""
474             },
475 
476             // max counter
477             { "/statistics/max", performance_counters::counter_aggregating,
478               "returns the maximum value of its base counter over "
479               "an arbitrary time line; pass required base counter as the instance "
480               "name: /statistics{<base_counter_name>}/max",
481               HPX_PERFORMANCE_COUNTER_V1,
482               &performance_counters::detail::statistics_counter_creator,
483               &performance_counters::default_counter_discoverer,
484               ""
485             },
486 
487             // min counter
488             { "/statistics/min", performance_counters::counter_aggregating,
489               "returns the minimum value of its base counter over "
490               "an arbitrary time line; pass required base counter as the instance "
491               "name: /statistics{<base_counter_name>}/min",
492               HPX_PERFORMANCE_COUNTER_V1,
493                &performance_counters::detail::statistics_counter_creator,
494                &performance_counters::default_counter_discoverer,
495               ""
496             },
497 
498             // rolling max counter
499             { "/statistics/rolling_max", performance_counters::counter_aggregating,
500               "returns the rolling maximum value of its base counter over "
501               "an arbitrary time line; pass required base counter as the instance "
502               "name: /statistics{<base_counter_name>}/rolling_max",
503               HPX_PERFORMANCE_COUNTER_V1,
504               &performance_counters::detail::statistics_counter_creator,
505               &performance_counters::default_counter_discoverer,
506               ""
507             },
508 
509             // rolling min counter
510             { "/statistics/rolling_min", performance_counters::counter_aggregating,
511               "returns the rolling minimum value of its base counter over "
512               "an arbitrary time line; pass required base counter as the instance "
513               "name: /statistics{<base_counter_name>}/rolling_min",
514               HPX_PERFORMANCE_COUNTER_V1,
515               &performance_counters::detail::statistics_counter_creator,
516               &performance_counters::default_counter_discoverer,
517               ""
518             },
519 
520             // uptime counters
521             { "/runtime/uptime", performance_counters::counter_elapsed_time,
522               "returns the up time of the runtime instance for the referenced "
523               "locality",
524               HPX_PERFORMANCE_COUNTER_V1,
525               &performance_counters::detail::uptime_counter_creator,
526               &performance_counters::locality_counter_discoverer,
527               "s"    // unit of measure is seconds
528             },
529 
530             // component instance counters
531             { "/runtime/count/component", performance_counters::counter_raw,
532               "returns the number of component instances currently alive on "
533               "this locality (the component type has to be specified as the "
534               "counter parameter)",
535               HPX_PERFORMANCE_COUNTER_V1,
536               &performance_counters::detail::component_instance_counter_creator,
537               &performance_counters::locality_counter_discoverer,
538               ""
539             },
540 
541             // action invocation counters
542             { "/runtime/count/action-invocation", performance_counters::counter_raw,
543               "returns the number of (local) invocations of a specific action "
544               "on this locality (the action type has to be specified as the "
545               "counter parameter)",
546               HPX_PERFORMANCE_COUNTER_V1,
547               &performance_counters::local_action_invocation_counter_creator,
548               &performance_counters::local_action_invocation_counter_discoverer,
549               ""
550             },
551 
552             { "/runtime/count/remote-action-invocation",
553               performance_counters::counter_raw,
554               "returns the number of (remote) invocations of a specific action "
555               "on this locality (the action type has to be specified as the "
556               "counter parameter)",
557               HPX_PERFORMANCE_COUNTER_V1,
558               &performance_counters::remote_action_invocation_counter_creator,
559               &performance_counters::remote_action_invocation_counter_discoverer,
560               ""
561             }
562         };
563         performance_counters::install_counter_types(
564             statistic_counter_types,
565             sizeof(statistic_counter_types)/sizeof(statistic_counter_types[0]));
566 
567         performance_counters::generic_counter_type_data arithmetic_counter_types[] =
568         {
569             // adding counter
570             { "/arithmetics/add", performance_counters::counter_aggregating,
571               "returns the sum of the values of the specified base counters; "
572               "pass required base counters as the parameters: "
573               "/arithmetics/add@<base_counter_name1>,<base_counter_name2>",
574               HPX_PERFORMANCE_COUNTER_V1,
575               &performance_counters::detail::arithmetics_counter_creator,
576               &performance_counters::default_counter_discoverer,
577               ""
578             },
579             // minus counter
580             { "/arithmetics/subtract", performance_counters::counter_aggregating,
581               "returns the difference of the values of the specified base counters; "
582               "pass the required base counters as the parameters: "
583               "/arithmetics/subtract@<base_counter_name1>,<base_counter_name2>",
584               HPX_PERFORMANCE_COUNTER_V1,
585               &performance_counters::detail::arithmetics_counter_creator,
586               &performance_counters::default_counter_discoverer,
587               ""
588             },
589             // multiply counter
590             { "/arithmetics/multiply", performance_counters::counter_aggregating,
591               "returns the product of the values of the specified base counters; "
592               "pass the required base counters as the parameters: "
593               "/arithmetics/multiply@<base_counter_name1>,<base_counter_name2>",
594               HPX_PERFORMANCE_COUNTER_V1,
595               &performance_counters::detail::arithmetics_counter_creator,
596               &performance_counters::default_counter_discoverer,
597               ""
598             },
599             // divide counter
600             { "/arithmetics/divide", performance_counters::counter_aggregating,
601               "returns the result of division of the values of the specified "
602               "base counters; pass the required base counters as the parameters: "
603               "/arithmetics/divide@<base_counter_name1>,<base_counter_name2>",
604               HPX_PERFORMANCE_COUNTER_V1,
605               &performance_counters::detail::arithmetics_counter_creator,
606               &performance_counters::default_counter_discoverer,
607               ""
608             },
609 
610             // arithmetics mean counter
611             { "/arithmetics/mean", performance_counters::counter_aggregating,
612               "returns the average value of all values of the specified "
613               "base counters; pass the required base counters as the parameters: "
614               "/arithmetics/mean@<base_counter_name1>,<base_counter_name2>",
615               HPX_PERFORMANCE_COUNTER_V1,
616               &performance_counters::detail::arithmetics_counter_extended_creator,
617               &performance_counters::default_counter_discoverer,
618               ""
619             },
620             // arithmetics variance counter
621             { "/arithmetics/variance", performance_counters::counter_aggregating,
622               "returns the standard deviation of all values of the specified "
623               "base counters; pass the required base counters as the parameters: "
624               "/arithmetics/variance@<base_counter_name1>,<base_counter_name2>",
625               HPX_PERFORMANCE_COUNTER_V1,
626               &performance_counters::detail::arithmetics_counter_extended_creator,
627               &performance_counters::default_counter_discoverer,
628               ""
629             },
630             // arithmetics median counter
631             { "/arithmetics/median", performance_counters::counter_aggregating,
632               "returns the median of all values of the specified "
633               "base counters; pass the required base counters as the parameters: "
634               "/arithmetics/median@<base_counter_name1>,<base_counter_name2>",
635               HPX_PERFORMANCE_COUNTER_V1,
636               &performance_counters::detail::arithmetics_counter_extended_creator,
637               &performance_counters::default_counter_discoverer,
638               ""
639             },
640             // arithmetics min counter
641             { "/arithmetics/min", performance_counters::counter_aggregating,
642               "returns the minimum value of all values of the specified "
643               "base counters; pass the required base counters as the parameters: "
644               "/arithmetics/min@<base_counter_name1>,<base_counter_name2>",
645               HPX_PERFORMANCE_COUNTER_V1,
646               &performance_counters::detail::arithmetics_counter_extended_creator,
647               &performance_counters::default_counter_discoverer,
648               ""
649             },
650             // arithmetics max counter
651             { "/arithmetics/max", performance_counters::counter_aggregating,
652               "returns the maximum value of all values of the specified "
653               "base counters; pass the required base counters as the parameters: "
654               "/arithmetics/max@<base_counter_name1>,<base_counter_name2>",
655               HPX_PERFORMANCE_COUNTER_V1,
656               &performance_counters::detail::arithmetics_counter_extended_creator,
657               &performance_counters::default_counter_discoverer,
658               ""
659             },
660             // arithmetics count counter
661             { "/arithmetics/count", performance_counters::counter_aggregating,
662               "returns the count value of all values of the specified "
663               "base counters; pass the required base counters as the parameters: "
664               "/arithmetics/count@<base_counter_name1>,<base_counter_name2>",
665               HPX_PERFORMANCE_COUNTER_V1,
666               &performance_counters::detail::arithmetics_counter_extended_creator,
667               &performance_counters::default_counter_discoverer,
668               ""
669             },
670         };
671         performance_counters::install_counter_types(
672             arithmetic_counter_types,
673             sizeof(arithmetic_counter_types)/sizeof(arithmetic_counter_types[0]));
674     }
675 
assign_cores(std::string const & locality_basename,std::uint32_t cores_needed)676     std::uint32_t runtime::assign_cores(std::string const& locality_basename,
677         std::uint32_t cores_needed)
678     {
679         std::lock_guard<compat::mutex> l(mtx_);
680 
681         used_cores_map_type::iterator it = used_cores_map_.find(locality_basename);
682         if (it == used_cores_map_.end())
683         {
684             used_cores_map_.insert(
685                 used_cores_map_type::value_type(locality_basename, cores_needed));
686             return 0;
687         }
688 
689         std::uint32_t current = (*it).second;
690         (*it).second += cores_needed;
691         return current;
692     }
693 
assign_cores()694     std::uint32_t runtime::assign_cores()
695     {
696         // adjust thread assignments to allow for more than one locality per
697         // node
698         std::size_t first_core = this->get_config().get_first_used_core();
699         std::size_t cores_needed =
700             hpx::resource::get_partitioner().assign_cores(first_core);
701 
702         return static_cast<std::uint32_t>(cores_needed);
703     }
704 
705     ///////////////////////////////////////////////////////////////////////////
706     threads::policies::callback_notifier::on_startstop_type
on_start_func() const707         runtime::on_start_func() const
708     {
709         return on_start_func_;
710     }
711 
712     threads::policies::callback_notifier::on_startstop_type
on_stop_func() const713         runtime::on_stop_func() const
714     {
715         return on_stop_func_;
716     }
717 
718     threads::policies::callback_notifier::on_error_type
on_error_func() const719         runtime::on_error_func() const
720     {
721         return on_error_func_;
722     }
723 
724     threads::policies::callback_notifier::on_startstop_type
on_start_func(threads::policies::callback_notifier::on_startstop_type && f)725     runtime::on_start_func(
726         threads::policies::callback_notifier::on_startstop_type&& f)
727     {
728         threads::policies::callback_notifier::on_startstop_type newf =
729             std::move(f);
730         std::swap(on_start_func_, newf);
731         return newf;
732     }
733 
734     threads::policies::callback_notifier::on_startstop_type
on_stop_func(threads::policies::callback_notifier::on_startstop_type && f)735     runtime::on_stop_func(
736         threads::policies::callback_notifier::on_startstop_type&& f)
737     {
738         threads::policies::callback_notifier::on_startstop_type newf =
739             std::move(f);
740         std::swap(on_stop_func_, newf);
741         return newf;
742     }
743 
744     threads::policies::callback_notifier::on_error_type
on_error_func(threads::policies::callback_notifier::on_error_type && f)745     runtime::on_error_func(
746         threads::policies::callback_notifier::on_error_type&& f)
747     {
748         threads::policies::callback_notifier::on_error_type newf =
749             std::move(f);
750         std::swap(on_error_func_, newf);
751         return newf;
752     }
753 
754     ///////////////////////////////////////////////////////////////////////////
755     threads::policies::callback_notifier::on_startstop_type
get_thread_on_start_func()756         get_thread_on_start_func()
757     {
758         runtime* rt = get_runtime_ptr();
759         if (nullptr != rt)
760         {
761             return rt->on_start_func();
762         }
763         else
764         {
765             return global_on_start_func;
766         }
767     }
768 
769     threads::policies::callback_notifier::on_startstop_type
get_thread_on_stop_func()770         get_thread_on_stop_func()
771     {
772         runtime* rt = get_runtime_ptr();
773         if (nullptr != rt)
774         {
775             return rt->on_stop_func();
776         }
777         else
778         {
779             return global_on_stop_func;
780         }
781     }
782 
783     threads::policies::callback_notifier::on_error_type
get_thread_on_error_func()784         get_thread_on_error_func()
785     {
786         runtime* rt = get_runtime_ptr();
787         if (nullptr != rt)
788         {
789             return rt->on_error_func();
790         }
791         else
792         {
793             return global_on_error_func;
794         }
795     }
796 
797     threads::policies::callback_notifier::on_startstop_type
register_thread_on_start_func(threads::policies::callback_notifier::on_startstop_type && f)798     register_thread_on_start_func(
799         threads::policies::callback_notifier::on_startstop_type&& f)
800     {
801         runtime* rt = get_runtime_ptr();
802         if (nullptr != rt)
803         {
804             return rt->on_start_func(std::move(f));
805         }
806 
807         threads::policies::callback_notifier::on_startstop_type newf =
808             std::move(f);
809         std::swap(global_on_start_func, newf);
810         return newf;
811     }
812 
813     threads::policies::callback_notifier::on_startstop_type
register_thread_on_stop_func(threads::policies::callback_notifier::on_startstop_type && f)814     register_thread_on_stop_func(
815         threads::policies::callback_notifier::on_startstop_type&& f)
816     {
817         runtime* rt = get_runtime_ptr();
818         if (nullptr != rt)
819         {
820             return rt->on_stop_func(std::move(f));
821         }
822 
823         threads::policies::callback_notifier::on_startstop_type newf =
824             std::move(f);
825         std::swap(global_on_stop_func, newf);
826         return newf;
827     }
828 
829     threads::policies::callback_notifier::on_error_type
register_thread_on_error_func(threads::policies::callback_notifier::on_error_type && f)830     register_thread_on_error_func(
831         threads::policies::callback_notifier::on_error_type&& f)
832     {
833         runtime* rt = get_runtime_ptr();
834         if (nullptr != rt)
835         {
836             return rt->on_error_func(std::move(f));
837         }
838 
839         threads::policies::callback_notifier::on_error_type newf =
840             std::move(f);
841         std::swap(global_on_error_func, newf);
842         return newf;
843     }
844 
845     ///////////////////////////////////////////////////////////////////////////
get_runtime()846     runtime& get_runtime()
847     {
848         HPX_ASSERT(nullptr != runtime::runtime_.get());   // should have been initialized
849         return **runtime::runtime_;
850     }
851 
get_runtime_ptr()852     runtime* get_runtime_ptr()
853     {
854         runtime** rt = runtime::runtime_.get();
855         return rt ? *rt : nullptr;
856     }
857 
get_locality()858     naming::gid_type const & get_locality()
859     {
860         return get_runtime().get_agas_client().get_local_locality();
861     }
862 
863     /// Register the current kernel thread with HPX, this should be done once
864     /// for each external OS-thread intended to invoke HPX functionality.
865     /// Calling this function more than once will silently fail
866     /// (will return false).
register_thread(runtime * rt,char const * name,error_code & ec)867     bool register_thread(runtime* rt, char const* name, error_code& ec)
868     {
869         HPX_ASSERT(rt);
870         return rt->register_thread(name, 0, true, ec);
871     }
872 
873     /// Unregister the thread from HPX, this should be done once in
874     /// the end before the external thread exists.
unregister_thread(runtime * rt)875     void unregister_thread(runtime* rt)
876     {
877         HPX_ASSERT(rt);
878         rt->unregister_thread();
879     }
880 
report_error(std::size_t num_thread,std::exception_ptr const & e)881     void report_error(std::size_t num_thread, std::exception_ptr const& e)
882     {
883         // Early and late exceptions
884         if (!threads::threadmanager_is(state_running))
885         {
886             hpx::runtime* rt = hpx::get_runtime_ptr();
887             if (rt)
888                 rt->report_error(num_thread, e);
889             else
890                 detail::report_exception_and_terminate(e);
891             return;
892         }
893 
894         hpx::applier::get_applier().get_thread_manager().report_error(num_thread, e);
895     }
896 
report_error(std::exception_ptr const & e)897     void report_error(std::exception_ptr const& e)
898     {
899         // Early and late exceptions
900         if (!threads::threadmanager_is(state_running))
901         {
902             hpx::runtime* rt = hpx::get_runtime_ptr();
903             if (rt)
904                 rt->report_error(std::size_t(-1), e);
905             else
906                 detail::report_exception_and_terminate(e);
907             return;
908         }
909 
910         std::size_t num_thread = hpx::get_worker_thread_num();
911         hpx::applier::get_applier().get_thread_manager().report_error(num_thread, e);
912     }
913 
register_on_exit(util::function_nonser<void ()> const & f)914     bool register_on_exit(util::function_nonser<void()> const& f)
915     {
916         runtime* rt = get_runtime_ptr();
917         if (nullptr == rt)
918             return false;
919 
920         rt->on_exit(f);
921         return true;
922     }
923 
get_runtime_instance_number()924     std::size_t get_runtime_instance_number()
925     {
926         runtime* rt = get_runtime_ptr();
927         return (nullptr == rt) ? 0 : rt->get_instance_number();
928     }
929 
930     ///////////////////////////////////////////////////////////////////////////
get_config_entry(std::string const & key,std::string const & dflt)931     std::string get_config_entry(std::string const& key, std::string const& dflt)
932     {
933         //! FIXME runtime_configuration should probs be a member of
934         // hpx::runtime only, not command_line_handling
935         //! FIXME change functions in this section accordingly
936         if (get_runtime_ptr() != nullptr)
937         {
938             return get_runtime().get_config().get_entry(key, dflt);
939         }
940         if (!resource::is_partitioner_valid())
941         {
942             return dflt;
943         }
944         return resource::get_partitioner()
945             .get_command_line_switches().rtcfg_.get_entry(key, dflt);
946     }
947 
get_config_entry(std::string const & key,std::size_t dflt)948     std::string get_config_entry(std::string const& key, std::size_t dflt)
949     {
950         if (get_runtime_ptr() != nullptr)
951         {
952             return get_runtime().get_config().get_entry(key, dflt);
953         }
954         if (!resource::is_partitioner_valid())
955         {
956             return std::to_string(dflt);
957         }
958         return resource::get_partitioner()
959             .get_command_line_switches().rtcfg_.get_entry(key, dflt);
960     }
961 
962     // set entries
set_config_entry(std::string const & key,std::string const & value)963     void set_config_entry(std::string const& key, std::string const& value)
964     {
965         if (get_runtime_ptr() != nullptr)
966         {
967             get_runtime_ptr()->get_config().add_entry(key, value);
968             return;
969         }
970         if (resource::is_partitioner_valid())
971         {
972             resource::get_partitioner()
973                 .get_command_line_switches().rtcfg_.add_entry(key, value);
974             return;
975         }
976     }
977 
set_config_entry(std::string const & key,std::size_t value)978     void set_config_entry(std::string const& key, std::size_t value)
979     {
980         if (get_runtime_ptr() != nullptr)
981         {
982             get_runtime_ptr()->get_config().add_entry(
983                 key, std::to_string(value));
984             return;
985         }
986         if (resource::is_partitioner_valid())
987         {
988             resource::get_partitioner()
989                 .get_command_line_switches().rtcfg_.
990                     add_entry(key, std::to_string(value));
991             return;
992         }
993     }
994 
set_config_entry_callback(std::string const & key,util::function_nonser<void (std::string const &,std::string const &)> const & callback)995     void set_config_entry_callback(std::string const& key,
996         util::function_nonser<void(
997             std::string const&, std::string const&)> const& callback)
998     {
999         if (get_runtime_ptr() != nullptr)
1000         {
1001             get_runtime_ptr()->get_config().add_notification_callback(
1002                 key, callback);
1003             return;
1004         }
1005         if (resource::is_partitioner_valid())
1006         {
1007             resource::get_partitioner()
1008                 .get_command_line_switches()
1009                 .rtcfg_.add_notification_callback(key, callback);
1010             return;
1011         }
1012     }
1013 
1014     ///////////////////////////////////////////////////////////////////////////
1015     // Helpers
find_here(error_code & ec)1016     naming::id_type find_here(error_code& ec)
1017     {
1018         if (nullptr == hpx::applier::get_applier_ptr())
1019         {
1020             HPX_THROWS_IF(ec, invalid_status, "hpx::find_here",
1021                 "the runtime system is not available at this time");
1022             return naming::invalid_id;
1023         }
1024 
1025         return naming::id_type(hpx::applier::get_applier().get_raw_locality(ec),
1026             naming::id_type::unmanaged);
1027     }
1028 
find_root_locality(error_code & ec)1029     naming::id_type find_root_locality(error_code& ec)
1030     {
1031         runtime* rt = hpx::get_runtime_ptr();
1032         if (nullptr == rt)
1033         {
1034             HPX_THROWS_IF(ec, invalid_status, "hpx::find_root_locality",
1035                 "the runtime system is not available at this time");
1036             return naming::invalid_id;
1037         }
1038 
1039         naming::gid_type console_locality;
1040         if (!rt->get_agas_client().get_console_locality(console_locality))
1041         {
1042             HPX_THROWS_IF(ec, invalid_status, "hpx::find_root_locality",
1043                 "the root locality is not available at this time");
1044             return naming::invalid_id;
1045         }
1046 
1047         if (&ec != &throws)
1048             ec = make_success_code();
1049 
1050         return naming::id_type(console_locality, naming::id_type::unmanaged);
1051     }
1052 
1053     std::vector<naming::id_type>
find_all_localities(components::component_type type,error_code & ec)1054     find_all_localities(components::component_type type, error_code& ec)
1055     {
1056         std::vector<naming::id_type> locality_ids;
1057         if (nullptr == hpx::applier::get_applier_ptr())
1058         {
1059             HPX_THROWS_IF(ec, invalid_status, "hpx::find_all_localities",
1060                 "the runtime system is not available at this time");
1061             return locality_ids;
1062         }
1063 
1064         hpx::applier::get_applier().get_localities(locality_ids, type, ec);
1065         return locality_ids;
1066     }
1067 
find_all_localities(error_code & ec)1068     std::vector<naming::id_type> find_all_localities(error_code& ec)
1069     {
1070         std::vector<naming::id_type> locality_ids;
1071         if (nullptr == hpx::applier::get_applier_ptr())
1072         {
1073             HPX_THROWS_IF(ec, invalid_status, "hpx::find_all_localities",
1074                 "the runtime system is not available at this time");
1075             return locality_ids;
1076         }
1077 
1078         hpx::applier::get_applier().get_localities(locality_ids, ec);
1079         return locality_ids;
1080     }
1081 
1082     std::vector<naming::id_type>
find_remote_localities(components::component_type type,error_code & ec)1083     find_remote_localities(components::component_type type, error_code& ec)
1084     {
1085         std::vector<naming::id_type> locality_ids;
1086         if (nullptr == hpx::applier::get_applier_ptr())
1087         {
1088             HPX_THROWS_IF(ec, invalid_status, "hpx::find_remote_localities",
1089                 "the runtime system is not available at this time");
1090             return locality_ids;
1091         }
1092 
1093         hpx::applier::get_applier().get_remote_localities(locality_ids, type, ec);
1094         return locality_ids;
1095     }
1096 
find_remote_localities(error_code & ec)1097     std::vector<naming::id_type> find_remote_localities(error_code& ec)
1098     {
1099         std::vector<naming::id_type> locality_ids;
1100         if (nullptr == hpx::applier::get_applier_ptr())
1101         {
1102             HPX_THROWS_IF(ec, invalid_status, "hpx::find_remote_localities",
1103                 "the runtime system is not available at this time");
1104             return locality_ids;
1105         }
1106 
1107         hpx::applier::get_applier().get_remote_localities(locality_ids,
1108             components::component_invalid, ec);
1109 
1110         return locality_ids;
1111     }
1112 
1113     // find a locality supporting the given component
find_locality(components::component_type type,error_code & ec)1114     naming::id_type find_locality(components::component_type type, error_code& ec)
1115     {
1116         if (nullptr == hpx::applier::get_applier_ptr())
1117         {
1118             HPX_THROWS_IF(ec, invalid_status, "hpx::find_locality",
1119                 "the runtime system is not available at this time");
1120             return naming::invalid_id;
1121         }
1122 
1123         std::vector<naming::id_type> locality_ids;
1124         hpx::applier::get_applier().get_localities(locality_ids, type, ec);
1125 
1126         if (ec || locality_ids.empty())
1127             return naming::invalid_id;
1128 
1129         // chose first locality to host the object
1130         return locality_ids.front();
1131     }
1132 
1133     /// \brief Return the number of localities which are currently registered
1134     ///        for the running application.
get_num_localities(hpx::launch::sync_policy,error_code & ec)1135     std::uint32_t get_num_localities(hpx::launch::sync_policy, error_code& ec)
1136     {
1137         if (nullptr == hpx::get_runtime_ptr())
1138             return 0;
1139 
1140         return get_runtime().get_agas_client().get_num_localities(ec);
1141     }
1142 
get_initial_num_localities()1143     std::uint32_t get_initial_num_localities()
1144     {
1145         if (nullptr == hpx::get_runtime_ptr())
1146             return 0;
1147 
1148         return get_runtime().get_config().get_num_localities();
1149     }
1150 
get_num_localities(hpx::launch::sync_policy,components::component_type type,error_code & ec)1151     std::uint32_t get_num_localities(hpx::launch::sync_policy,
1152         components::component_type type, error_code& ec)
1153     {
1154         if (nullptr == hpx::get_runtime_ptr())
1155             return 0;
1156 
1157         return get_runtime().get_agas_client().get_num_localities(type, ec);
1158     }
1159 
get_num_localities()1160     lcos::future<std::uint32_t> get_num_localities()
1161     {
1162         if (nullptr == hpx::get_runtime_ptr())
1163             return lcos::make_ready_future<std::uint32_t>(0);
1164 
1165         return get_runtime().get_agas_client().get_num_localities_async();
1166     }
1167 
get_num_localities(components::component_type type)1168     lcos::future<std::uint32_t> get_num_localities(
1169         components::component_type type)
1170     {
1171         if (nullptr == hpx::get_runtime_ptr())
1172             return lcos::make_ready_future<std::uint32_t>(0);
1173 
1174         return get_runtime().get_agas_client().get_num_localities_async(type);
1175     }
1176 
1177     ///////////////////////////////////////////////////////////////////////////
1178     namespace detail
1179     {
get_next_id(std::size_t count)1180         naming::gid_type get_next_id(std::size_t count)
1181         {
1182             if (nullptr == get_runtime_ptr())
1183                 return naming::invalid_gid;
1184 
1185             return get_runtime().get_next_id(count);
1186         }
1187 
1188         ///////////////////////////////////////////////////////////////////////////
dijkstra_make_black()1189         void dijkstra_make_black()
1190         {
1191             get_runtime_support_ptr()->dijkstra_make_black();
1192         }
1193     }
1194 
1195     ///////////////////////////////////////////////////////////////////////////
get_os_thread_count()1196     std::size_t get_os_thread_count()
1197     {
1198         runtime* rt = get_runtime_ptr();
1199         if (nullptr == rt)
1200         {
1201             HPX_THROW_EXCEPTION(
1202                 invalid_status,
1203                 "hpx::get_os_thread_count()",
1204                 "the runtime system has not been initialized yet");
1205             return std::size_t(0);
1206         }
1207         return rt->get_config().get_os_thread_count();
1208     }
1209 
get_os_thread_count(threads::executor const & exec)1210     std::size_t get_os_thread_count(threads::executor const& exec)
1211     {
1212         runtime* rt = get_runtime_ptr();
1213         if (nullptr == rt)
1214         {
1215             HPX_THROW_EXCEPTION(
1216                 invalid_status,
1217                 "hpx::get_os_thread_count(exec)",
1218                 "the runtime system has not been initialized yet");
1219             return std::size_t(0);
1220         }
1221 
1222         if (!exec)
1223             return rt->get_config().get_os_thread_count();
1224 
1225         error_code ec(lightweight);
1226         return exec.executor_data_->get_policy_element(
1227             threads::detail::current_concurrency, ec);
1228     }
1229 
get_worker_thread_num()1230     std::size_t get_worker_thread_num()
1231     {
1232         return get_worker_thread_num(throws);
1233     }
1234 
get_worker_thread_num(error_code & ec)1235     std::size_t get_worker_thread_num(error_code& ec)
1236     {
1237         runtime* rt = get_runtime_ptr();
1238         if (nullptr == rt)
1239         {
1240             HPX_THROWS_IF(
1241                 ec, invalid_status,
1242                 "hpx::get_worker_thread_num",
1243                 "the runtime system has not been initialized yet");
1244             return std::size_t(-1);
1245         }
1246         return rt->get_thread_manager().get_worker_thread_num();
1247     }
1248 
get_num_worker_threads()1249     std::size_t get_num_worker_threads()
1250     {
1251         runtime* rt = get_runtime_ptr();
1252         if (nullptr == rt)
1253         {
1254             HPX_THROW_EXCEPTION(
1255                 invalid_status,
1256                 "hpx::get_num_worker_threads",
1257                 "the runtime system has not been initialized yet");
1258             return std::size_t(0);
1259         }
1260 
1261         error_code ec(lightweight);
1262         return static_cast<std::size_t>(
1263             rt->get_agas_client().get_num_overall_threads(ec));
1264     }
1265 
is_scheduler_numa_sensitive()1266     bool is_scheduler_numa_sensitive()
1267     {
1268         runtime* rt = get_runtime_ptr();
1269         if (nullptr == rt)
1270         {
1271             HPX_THROW_EXCEPTION(
1272                 invalid_status,
1273                 "hpx::is_scheduler_numa_sensitive",
1274                 "the runtime system has not been initialized yet");
1275             return false;
1276         }
1277 
1278         bool numa_sensitive = false;
1279         if (std::size_t(-1) !=
1280             rt->get_thread_manager().get_worker_thread_num(&numa_sensitive))
1281             return numa_sensitive;
1282         return false;
1283     }
1284 
1285     ///////////////////////////////////////////////////////////////////////////
get_runtime_support_ptr()1286     components::server::runtime_support* get_runtime_support_ptr()
1287     {
1288         return reinterpret_cast<components::server::runtime_support*>(
1289             get_runtime().get_runtime_support_lva());
1290     }
1291 
1292     ///////////////////////////////////////////////////////////////////////////
is_running()1293     bool is_running()
1294     {
1295         runtime* rt = get_runtime_ptr();
1296         if (nullptr != rt)
1297             return rt->get_state() == state_running;
1298         return false;
1299     }
1300 
is_stopped()1301     bool is_stopped()
1302     {
1303         runtime* rt = get_runtime_ptr();
1304         if (nullptr != rt)
1305             return rt->get_state() == state_stopped;
1306         return true;        // assume stopped
1307     }
1308 
is_stopped_or_shutting_down()1309     bool is_stopped_or_shutting_down()
1310     {
1311         runtime* rt = get_runtime_ptr();
1312         if (nullptr != rt)
1313         {
1314             state st = rt->get_state();
1315             return st >= state_shutdown;
1316         }
1317         return true;        // assume stopped
1318     }
1319 
tolerate_node_faults()1320     bool HPX_EXPORT tolerate_node_faults()
1321     {
1322 #ifdef HPX_HAVE_FAULT_TOLERANCE
1323         return true;
1324 #else
1325         return false;
1326 #endif
1327     }
1328 
is_starting()1329     bool HPX_EXPORT is_starting()
1330     {
1331         runtime* rt = get_runtime_ptr();
1332         return nullptr != rt ? rt->get_state() <= state_startup : true;
1333     }
1334 
is_pre_startup()1335     bool HPX_EXPORT is_pre_startup()
1336     {
1337         runtime* rt = get_runtime_ptr();
1338         return nullptr != rt ? rt->get_state() < state_startup : true;
1339     }
1340 }
1341 
1342 ///////////////////////////////////////////////////////////////////////////////
1343 namespace hpx { namespace util
1344 {
expand(std::string const & in)1345     std::string expand(std::string const& in)
1346     {
1347         return get_runtime().get_config().expand(in);
1348     }
1349 
expand(std::string & in)1350     void expand(std::string& in)
1351     {
1352         get_runtime().get_config().expand(in, std::string::size_type(-1));
1353     }
1354 }}
1355 
1356 ///////////////////////////////////////////////////////////////////////////////
1357 namespace hpx { namespace naming
1358 {
1359     // shortcut for get_runtime().get_agas_client()
get_agas_client()1360     resolver_client& get_agas_client()
1361     {
1362         return get_runtime().get_agas_client();
1363     }
1364 }}
1365 
1366 ///////////////////////////////////////////////////////////////////////////////
1367 namespace hpx { namespace parcelset
1368 {
do_background_work(std::size_t num_thread)1369     bool do_background_work(std::size_t num_thread)
1370     {
1371         return get_runtime().get_parcel_handler().do_background_work(num_thread);
1372     }
1373 }}
1374 
1375 ///////////////////////////////////////////////////////////////////////////////
1376 namespace hpx { namespace threads
1377 {
1378     // shortcut for get_applier().get_thread_manager()
get_thread_manager()1379     threadmanager& get_thread_manager()
1380     {
1381         return get_runtime().get_thread_manager();
1382     }
1383 
1384     // shortcut for runtime_configuration::get_default_stack_size
get_default_stack_size()1385     std::ptrdiff_t get_default_stack_size()
1386     {
1387         return get_runtime().get_config().get_default_stack_size();
1388     }
1389 
1390     // shortcut for runtime_configuration::get_stack_size
get_stack_size(threads::thread_stacksize stacksize)1391     std::ptrdiff_t get_stack_size(threads::thread_stacksize stacksize)
1392     {
1393         if (stacksize == threads::thread_stacksize_current)
1394             return threads::get_self_stacksize();
1395 
1396         return get_runtime().get_config().get_stack_size(stacksize);
1397     }
1398 
reset_thread_distribution()1399     HPX_API_EXPORT void reset_thread_distribution()
1400     {
1401         get_runtime().get_thread_manager().reset_thread_distribution();
1402     }
1403 
set_scheduler_mode(threads::policies::scheduler_mode m)1404     HPX_API_EXPORT void set_scheduler_mode(threads::policies::scheduler_mode m)
1405     {
1406         get_runtime().get_thread_manager().set_scheduler_mode(m);
1407     }
1408 
1409 }}
1410 
1411 ///////////////////////////////////////////////////////////////////////////////
1412 namespace hpx
1413 {
get_locality_id(error_code & ec)1414     std::uint32_t get_locality_id(error_code& ec)
1415     {
1416         return agas::get_locality_id(ec);
1417     }
1418 
get_thread_name()1419     std::string get_thread_name()
1420     {
1421         return runtime::get_thread_name();
1422     }
1423 
get_system_uptime()1424     std::uint64_t get_system_uptime()
1425     {
1426         return runtime::get_system_uptime();
1427     }
1428 
get_config()1429     util::runtime_configuration const& get_config()
1430     {
1431         return get_runtime().get_config();
1432     }
1433 
get_thread_pool(char const * name,char const * name_suffix)1434     hpx::util::io_service_pool* get_thread_pool(
1435         char const* name, char const* name_suffix)
1436     {
1437         std::string full_name(name);
1438         full_name += name_suffix;
1439         return get_runtime().get_thread_pool(full_name.c_str());
1440     }
1441 
1442     ///////////////////////////////////////////////////////////////////////////
start_active_counters(error_code & ec)1443     void start_active_counters(error_code& ec)
1444     {
1445         runtime* rt = get_runtime_ptr();
1446         if (nullptr != rt) {
1447             rt->start_active_counters(ec);
1448         }
1449         else {
1450             HPX_THROWS_IF(ec, invalid_status, "start_active_counters",
1451                 "the runtime system is not available at this time");
1452         }
1453     }
1454 
stop_active_counters(error_code & ec)1455     void stop_active_counters(error_code& ec)
1456     {
1457         runtime* rt = get_runtime_ptr();
1458         if (nullptr != rt) {
1459             rt->stop_active_counters(ec);
1460         }
1461         else {
1462             HPX_THROWS_IF(ec, invalid_status, "stop_active_counters",
1463                 "the runtime system is not available at this time");
1464         }
1465     }
1466 
reset_active_counters(error_code & ec)1467     void reset_active_counters(error_code& ec)
1468     {
1469         runtime* rt = get_runtime_ptr();
1470         if (nullptr != rt) {
1471             rt->reset_active_counters(ec);
1472         }
1473         else {
1474             HPX_THROWS_IF(ec, invalid_status, "reset_active_counters",
1475                 "the runtime system is not available at this time");
1476         }
1477     }
1478 
reinit_active_counters(bool reset,error_code & ec)1479     void reinit_active_counters(bool reset, error_code& ec)
1480     {
1481         runtime* rt = get_runtime_ptr();
1482         if (nullptr != rt) {
1483             rt->reinit_active_counters(reset, ec);
1484         }
1485         else {
1486             HPX_THROWS_IF(ec, invalid_status, "reinit_active_counters",
1487                 "the runtime system is not available at this time");
1488         }
1489     }
1490 
evaluate_active_counters(bool reset,char const * description,error_code & ec)1491     void evaluate_active_counters(bool reset, char const* description, error_code& ec)
1492     {
1493         runtime* rt = get_runtime_ptr();
1494         if (nullptr != rt) {
1495             rt->evaluate_active_counters(reset, description, ec);
1496         }
1497         else {
1498             HPX_THROWS_IF(ec, invalid_status, "evaluate_active_counters",
1499                 "the runtime system is not available at this time");
1500         }
1501     }
1502 
1503     ///////////////////////////////////////////////////////////////////////////
1504     // Create an instance of a message handler plugin
register_message_handler(char const * message_handler_type,char const * action,error_code & ec)1505     void register_message_handler(char const* message_handler_type,
1506         char const* action, error_code& ec)
1507     {
1508         runtime* rt = get_runtime_ptr();
1509         if (nullptr != rt) {
1510             return rt->register_message_handler(message_handler_type, action, ec);
1511         }
1512 
1513         // store the request for later
1514         message_handler_registrations.push_back(
1515             hpx::util::make_tuple(message_handler_type, action));
1516     }
1517 
create_message_handler(char const * message_handler_type,char const * action,parcelset::parcelport * pp,std::size_t num_messages,std::size_t interval,error_code & ec)1518     parcelset::policies::message_handler* create_message_handler(
1519         char const* message_handler_type, char const* action,
1520         parcelset::parcelport* pp, std::size_t num_messages,
1521         std::size_t interval, error_code& ec)
1522     {
1523         runtime* rt = get_runtime_ptr();
1524         if (nullptr != rt) {
1525             return rt->create_message_handler(message_handler_type, action,
1526                 pp, num_messages, interval, ec);
1527         }
1528 
1529         HPX_THROWS_IF(ec, invalid_status, "create_message_handler",
1530             "the runtime system is not available at this time");
1531         return nullptr;
1532     }
1533 
1534     ///////////////////////////////////////////////////////////////////////////
1535     // Create an instance of a binary filter plugin
create_binary_filter(char const * binary_filter_type,bool compress,serialization::binary_filter * next_filter,error_code & ec)1536     serialization::binary_filter* create_binary_filter(char const* binary_filter_type,
1537         bool compress, serialization::binary_filter* next_filter, error_code& ec)
1538     {
1539         runtime* rt = get_runtime_ptr();
1540         if (nullptr != rt)
1541             return rt->create_binary_filter
1542                     (binary_filter_type, compress, next_filter, ec);
1543 
1544         HPX_THROWS_IF(ec, invalid_status, "create_binary_filter",
1545             "the runtime system is not available at this time");
1546         return nullptr;
1547     }
1548 
1549     // helper function to stop evaluating counters during shutdown
stop_evaluating_counters()1550     void stop_evaluating_counters()
1551     {
1552         runtime* rt = get_runtime_ptr();
1553         if (nullptr != rt) rt->stop_evaluating_counters();
1554     }
1555 }
1556