1 //  Copyright (c) 2005-2017 Hartmut Kaiser
2 //  Copyright (c)      2011 Bryce Adelstein-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/util/runtime_configuration.hpp>
8 
9 #include <hpx/config/defaults.hpp>
10 // TODO: move parcel ports into plugins
11 #include <hpx/runtime/parcelset/parcelhandler.hpp>
12 #include <hpx/util/assert.hpp>
13 #include <hpx/util/detail/pp/expand.hpp>
14 #include <hpx/util/detail/pp/stringize.hpp>
15 #include <hpx/util/filesystem_compatibility.hpp>
16 #include <hpx/util/find_prefix.hpp>
17 #include <hpx/util/init_ini_data.hpp>
18 #include <hpx/util/itt_notify.hpp>
19 #include <hpx/util/register_locks.hpp>
20 #include <hpx/util/register_locks_globally.hpp>
21 #include <hpx/util/safe_lexical_cast.hpp>
22 #include <hpx/version.hpp>
23 
24 #include <boost/detail/endian.hpp>
25 #include <boost/spirit/include/qi_parse.hpp>
26 #include <boost/spirit/include/qi_string.hpp>
27 #include <boost/spirit/include/qi_numeric.hpp>
28 #include <boost/spirit/include/qi_alternative.hpp>
29 #include <boost/spirit/include/qi_sequence.hpp>
30 #include <boost/tokenizer.hpp>
31 
32 #include <algorithm>
33 #include <cstddef>
34 #include <cstdint>
35 #include <iterator>
36 #include <map>
37 #include <memory>
38 #include <set>
39 #include <string>
40 #include <utility>
41 #include <vector>
42 
43 #if defined(HPX_WINDOWS)
44 #  include <process.h>
45 #elif defined(HPX_HAVE_UNISTD_H)
46 #  include <unistd.h>
47 #endif
48 
49 #if (defined(__linux) || defined(linux) || defined(__linux__))
50 #include <ifaddrs.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <sys/types.h>
54 #endif
55 
56 #if !defined(HPX_WINDOWS)
57 #  if defined(HPX_DEBUG)
58 #    define HPX_DLL_STRING  "libhpxd" HPX_SHARED_LIB_EXTENSION
59 #  else
60 #    define HPX_DLL_STRING  "libhpx" HPX_SHARED_LIB_EXTENSION
61 #  endif
62 #elif defined(HPX_DEBUG)
63 #  define HPX_DLL_STRING   "hpxd" HPX_SHARED_LIB_EXTENSION
64 #else
65 #  define HPX_DLL_STRING   "hpx" HPX_SHARED_LIB_EXTENSION
66 #endif
67 
68 #include <limits>
69 
70 ///////////////////////////////////////////////////////////////////////////////
71 #if defined(__linux) || defined(linux) || defined(__linux__)\
72          || defined(__FreeBSD__) || defined(__APPLE__)
73 namespace hpx { namespace threads { namespace coroutines { namespace detail
74 {
75     namespace posix
76     {
77         ///////////////////////////////////////////////////////////////////////
78         // this global (urghhh) variable is used to control whether guard pages
79         // will be used or not
80         HPX_EXPORT bool use_guard_pages = true;
81     }
82 }}}}
83 #endif
84 
85 namespace hpx { namespace threads { namespace policies
86 {
87 #ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
88     ///////////////////////////////////////////////////////////////////////////
89     // We globally control whether to do minimal deadlock detection using this
90     // global bool variable. It will be set once by the runtime configuration
91     // startup code
92     HPX_EXPORT bool minimal_deadlock_detection = true;
93 #endif
94 }}}
95 
96 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
97 namespace hpx { namespace util { namespace detail
98 {
99     ///////////////////////////////////////////////////////////////////////////
100     // We globally control whether to do minimal deadlock detection in
101     // spin-locks using this global bool variable. It will be set once by the
102     // runtime configuration startup code
103     bool spinlock_break_on_deadlock = false;
104     std::size_t spinlock_deadlock_detection_limit =
105         HPX_SPINLOCK_DEADLOCK_DETECTION_LIMIT;
106 }}}
107 #endif
108 
109 ///////////////////////////////////////////////////////////////////////////////
110 namespace hpx { namespace util
111 {
112     // pre-initialize entries with compile time based values
pre_initialize_ini()113     void runtime_configuration::pre_initialize_ini()
114     {
115         if (!need_to_call_pre_initialize)
116             return;
117 
118         std::vector<std::string> lines = {
119             // create an empty application section
120             "[application]",
121 
122             // create system and application instance specific entries
123             "[system]",
124             "pid = " + std::to_string(getpid()),
125             "prefix = " + find_prefix(),
126 #if defined(__linux) || defined(linux) || defined(__linux__)
127             "executable_prefix = " + get_executable_prefix(argv0),
128 #else
129             "executable_prefix = " + get_executable_prefix(),
130 #endif
131             // create default installation location and logging settings
132             "[hpx]",
133             "location = ${HPX_LOCATION:$[system.prefix]}",
134             "component_path = $[hpx.location]"
135                 HPX_INI_PATH_DELIMITER "$[system.executable_prefix]",
136             "component_path_suffixes = /lib/hpx" HPX_INI_PATH_DELIMITER
137                                       "/bin/hpx",
138             "master_ini_path = $[hpx.location]" HPX_INI_PATH_DELIMITER
139                               "$[system.executable_prefix]/",
140             "master_ini_path_suffixes = /share/" HPX_BASE_DIR_NAME
141                 HPX_INI_PATH_DELIMITER "/../share/" HPX_BASE_DIR_NAME,
142 #ifdef HPX_HAVE_ITTNOTIFY
143             "use_itt_notify = ${HPX_HAVE_ITTNOTIFY:0}",
144 #endif
145             "finalize_wait_time = ${HPX_FINALIZE_WAIT_TIME:-1.0}",
146             "shutdown_timeout = ${HPX_SHUTDOWN_TIMEOUT:-1.0}",
147 #ifdef HPX_HAVE_VERIFY_LOCKS
148 #if defined(HPX_DEBUG)
149             "lock_detection = ${HPX_LOCK_DETECTION:1}",
150 #else
151             "lock_detection = ${HPX_LOCK_DETECTION:0}",
152 #endif
153             "throw_on_held_lock = ${HPX_THROW_ON_HELD_LOCK:1}",
154 #endif
155 #ifdef HPX_HAVE_VERIFY_LOCKS_GLOBALLY
156 #if defined(HPX_DEBUG)
157             "global_lock_detection = ${HPX_GLOBAL_LOCK_DETECTION:1}",
158 #else
159             "global_lock_detection = ${HPX_GLOBAL_LOCK_DETECTION:0}",
160 #endif
161 #endif
162 #ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
163 #ifdef HPX_DEBUG
164             "minimal_deadlock_detection = ${HPX_MINIMAL_DEADLOCK_DETECTION:1}",
165 #else
166             "minimal_deadlock_detection = ${HPX_MINIMAL_DEADLOCK_DETECTION:0}",
167 #endif
168 #endif
169 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
170 #ifdef HPX_DEBUG
171             "spinlock_deadlock_detection = ${HPX_SPINLOCK_DEADLOCK_DETECTION:1}",
172 #else
173             "spinlock_deadlock_detection = ${HPX_SPINLOCK_DEADLOCK_DETECTION:0}",
174 #endif
175             "spinlock_deadlock_detection_limit = "
176                 "${HPX_SPINLOCK_DEADLOCK_DETECTION_LIMIT:1000000}",
177 #endif
178             "expect_connecting_localities = ${HPX_EXPECT_CONNECTING_LOCALITIES:0}",
179 
180             // add placeholders for keys to be added by command line handling
181             "os_threads = cores",
182             "cores = all",
183             "localities = 1",
184             "first_pu = 0",
185             "runtime_mode = console",
186             "scheduler = local-priority-fifo",
187             "affinity = core",
188             "pu_step = 1",
189             "pu_offset = 0",
190             "numa_sensitive = 0",
191             "max_background_threads = "
192                 "${HPX_MAX_BACKGROUND_THREADS:$[hpx.os_threads]}",
193 
194             "max_idle_loop_count = ${HPX_MAX_IDLE_LOOP_COUNT:"
195                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_IDLE_LOOP_COUNT_MAX)) "}",
196             "max_busy_loop_count = ${HPX_MAX_BUSY_LOOP_COUNT:"
197                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_BUSY_LOOP_COUNT_MAX)) "}",
198 #if defined(HPX_HAVE_THREAD_MANAGER_IDLE_BACKOFF)
199             "max_idle_backoff_time = ${HPX_MAX_IDLE_BACKOFF_TIME:"
200             HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_IDLE_BACKOFF_TIME_MAX)) "}",
201 #endif
202 
203             /// If HPX_HAVE_ATTACH_DEBUGGER_ON_TEST_FAILURE is set,
204             /// then apply the test-failure value as default.
205 #if defined(HPX_HAVE_ATTACH_DEBUGGER_ON_TEST_FAILURE)
206             "attach-debugger = ${HPX_ATTACH_DEBUGGER:test-failure}",
207 #else
208             "attach-debugger = ${HPX_ATTACH_DEBUGGER}",
209 #endif
210 
211             // arity for collective operations implemented in a tree fashion
212             "[hpx.lcos.collectives]",
213             "arity = ${HPX_LCOS_COLLECTIVES_ARITY:32}",
214             "cut_off = ${HPX_LCOS_COLLECTIVES_CUT_OFF:-1}",
215 
216             // connect back to the given latch if specified
217             "[hpx.on_startup]",
218             "wait_on_latch = ${HPX_ON_STARTUP_WAIT_ON_LATCH}",
219 
220 #if defined(HPX_HAVE_NETWORKING)
221             // by default, enable networking
222             "[hpx.parcel]",
223             "enable = 1",
224 #endif
225 
226             "[hpx.stacks]",
227             "small_size = ${HPX_SMALL_STACK_SIZE:"
228                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_SMALL_STACK_SIZE)) "}",
229             "medium_size = ${HPX_MEDIUM_STACK_SIZE:"
230                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_MEDIUM_STACK_SIZE)) "}",
231             "large_size = ${HPX_LARGE_STACK_SIZE:"
232                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_LARGE_STACK_SIZE)) "}",
233             "huge_size = ${HPX_HUGE_STACK_SIZE:"
234                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_HUGE_STACK_SIZE)) "}",
235 #if defined(__linux) || defined(linux) || defined(__linux__) || defined(__FreeBSD__)
236             "use_guard_pages = ${HPX_USE_GUARD_PAGES:1}",
237 #endif
238 
239             "[hpx.threadpools]",
240 #if defined(HPX_HAVE_IO_POOL)
241             "io_pool_size = ${HPX_NUM_IO_POOL_SIZE:"
242                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_NUM_IO_POOL_SIZE)) "}",
243 #endif
244 #if defined(HPX_HAVE_NETWORKING)
245             "parcel_pool_size = ${HPX_NUM_PARCEL_POOL_SIZE:"
246                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_NUM_PARCEL_POOL_SIZE)) "}",
247 #endif
248 #if defined(HPX_HAVE_TIMER_POOL)
249             "timer_pool_size = ${HPX_NUM_TIMER_POOL_SIZE:"
250                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_NUM_TIMER_POOL_SIZE)) "}",
251 #endif
252 
253             "[hpx.thread_queue]",
254             "min_tasks_to_steal_pending = "
255                 "${HPX_THREAD_QUEUE_MIN_TASKS_TO_STEAL_PENDING:0}",
256             "min_tasks_to_steal_staged = "
257                 "${HPX_THREAD_QUEUE_MIN_TASKS_TO_STEAL_STAGED:10}",
258             "min_add_new_count = ${HPX_THREAD_QUEUE_MIN_ADD_NEW_COUNT:10}",
259             "max_add_new_count = ${HPX_THREAD_QUEUE_MAX_ADD_NEW_COUNT:10}",
260             "max_delete_count = ${HPX_THREAD_QUEUE_MAX_DELETE_COUNT:1000}",
261             "max_terminated_threads = ${HPX_SCHEDULER_MAX_TERMINATED_THREADS:"
262               HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_SCHEDULER_MAX_TERMINATED_THREADS)) "}",
263 
264             "[hpx.commandline]",
265             // enable aliasing
266             "aliasing = ${HPX_COMMANDLINE_ALIASING:1}",
267 
268             // allow for unknown options to be passed through
269             "allow_unknown = ${HPX_COMMANDLINE_ALLOW_UNKNOWN:0}",
270 
271             // predefine command line aliases
272             "[hpx.commandline.aliases]",
273             "-a = --hpx:agas",
274             "-c = --hpx:console",
275             "-h = --hpx:help",
276             "-I = --hpx:ini",
277             "-l = --hpx:localities",
278             "-p = --hpx:app-config",
279             "-q = --hpx:queuing",
280             "-r = --hpx:run-agas-server",
281             "-t = --hpx:threads",
282             "-v = --hpx:version",
283             "-w = --hpx:worker",
284             "-x = --hpx:hpx",
285             "-0 = --hpx:node=0",
286             "-1 = --hpx:node=1",
287             "-2 = --hpx:node=2",
288             "-3 = --hpx:node=3",
289             "-4 = --hpx:node=4",
290             "-5 = --hpx:node=5",
291             "-6 = --hpx:node=6",
292             "-7 = --hpx:node=7",
293             "-8 = --hpx:node=8",
294             "-9 = --hpx:node=9",
295 
296             "[hpx.agas]",
297             // 'address' has deliberately no default, see
298             // command_line_handling.cpp
299             "address = ${HPX_AGAS_SERVER_ADDRESS}",
300             "port = ${HPX_AGAS_SERVER_PORT:"
301                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_INITIAL_IP_PORT)) "}",
302             "max_pending_refcnt_requests = "
303                 "${HPX_AGAS_MAX_PENDING_REFCNT_REQUESTS:"
304                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(
305                     HPX_INITIAL_AGAS_MAX_PENDING_REFCNT_REQUESTS))
306                 "}",
307             "service_mode = hosted",
308             "local_cache_size = ${HPX_AGAS_LOCAL_CACHE_SIZE:"
309                 HPX_PP_STRINGIZE(HPX_PP_EXPAND(HPX_AGAS_LOCAL_CACHE_SIZE)) "}",
310             "use_range_caching = ${HPX_AGAS_USE_RANGE_CACHING:1}",
311             "use_caching = ${HPX_AGAS_USE_CACHING:1}",
312 
313             "[hpx.components]",
314             "load_external = ${HPX_LOAD_EXTERNAL_COMPONENTS:1}",
315 
316             "[hpx.components.barrier]",
317             "name = hpx",
318             "path = $[hpx.location]/bin/" HPX_DLL_STRING,
319             "enabled = 1",
320 
321             "[hpx.components.hpx_lcos_server_latch]",
322             "name = hpx",
323             "path = $[hpx.location]/bin/" HPX_DLL_STRING,
324             "enabled = 1",
325 
326             "[hpx.components.raw_counter]",
327             "name = hpx",
328             "path = $[hpx.location]/bin/" HPX_DLL_STRING,
329             "enabled = 1",
330 
331             "[hpx.components.average_count_counter]",
332             "name = hpx",
333             "path = $[hpx.location]/bin/" HPX_DLL_STRING,
334             "enabled = 1",
335 
336             "[hpx.components.elapsed_time_counter]",
337             "name = hpx",
338             "path = $[hpx.location]/bin/" HPX_DLL_STRING,
339             "enabled = 1"
340         };
341 
342         std::vector<std::string> lines_pp =
343             hpx::parcelset::parcelhandler::load_runtime_configuration();
344 
345         lines.insert(lines.end(), lines_pp.begin(), lines_pp.end());
346 
347         // don't overload user overrides
348         this->parse("<static defaults>", lines, false, false, false);
349 
350         need_to_call_pre_initialize = false;
351     }
352 
post_initialize_ini(std::string & hpx_ini_file_,std::vector<std::string> const & cmdline_ini_defs_)353     void runtime_configuration::post_initialize_ini(
354         std::string& hpx_ini_file_,
355         std::vector<std::string> const& cmdline_ini_defs_)
356     {
357         util::init_ini_data_base(*this, hpx_ini_file_);
358         need_to_call_pre_initialize = true;
359 
360         // let the command line override the config file.
361         if (!cmdline_ini_defs_.empty()) {
362             // do not weed out comments
363             this->parse("<command line definitions>", cmdline_ini_defs_,
364                 true, false);
365             need_to_call_pre_initialize = true;
366         }
367     }
368 
369     ///////////////////////////////////////////////////////////////////////////
370     // load information about statically known components
load_components_static(std::vector<components::static_factory_load_data_type> const & static_modules)371     void runtime_configuration::load_components_static(std::vector<
372         components::static_factory_load_data_type> const& static_modules)
373     {
374         std::vector<std::shared_ptr<components::component_registry_base>> registries;
375         for (components::static_factory_load_data_type const& d : static_modules)
376         {
377             auto new_registries =
378                 util::load_component_factory_static(*this, d.name, d.get_factory);
379             registries.reserve(registries.size() + new_registries.size());
380             std::copy(new_registries.begin(), new_registries.end(),
381                 std::back_inserter(registries));
382         }
383 
384         // read system and user ini files _again_, to allow the user to
385         // overwrite the settings from the default component ini's.
386         util::init_ini_data_base(*this, hpx_ini_file);
387 
388         // let the command line override the config file.
389         if (!cmdline_ini_defs.empty())
390             parse("<command line definitions>", cmdline_ini_defs, true, false);
391 
392         // merge all found ini files of all components
393         util::merge_component_inis(*this);
394 
395         need_to_call_pre_initialize = true;
396 
397         // invoke last reconfigure
398         reconfigure();
399         for (auto& registry: registries)
400         {
401             registry->register_component_type();
402         }
403     }
404 
405     // load information about dynamically discovered plugins
406     std::vector<std::shared_ptr<plugins::plugin_registry_base> >
load_modules()407     runtime_configuration::load_modules()
408     {
409         typedef std::vector<std::shared_ptr<plugins::plugin_registry_base> >
410             plugin_list_type;
411 
412         namespace fs = boost::filesystem;
413 
414         // try to build default ini structure from shared libraries in default
415         // installation location, this allows to install simple components
416         // without the need to install an ini file
417         // split of the separate paths from the given path list
418         typedef boost::tokenizer<boost::char_separator<char> > tokenizer_type;
419 
420         std::string component_path(
421             get_entry("hpx.component_path", HPX_DEFAULT_COMPONENT_PATH));
422 
423         std::string component_path_suffixes(
424             get_entry("hpx.component_path_suffixes", "/lib/hpx"));
425 
426         // protect against duplicate paths
427         std::set<std::string> component_paths;
428 
429         // list of base names avoiding to load a module more than once
430         std::map<std::string, fs::path> basenames;
431 
432         boost::char_separator<char> sep (HPX_INI_PATH_DELIMITER);
433         tokenizer_type tok_path(component_path, sep);
434         tokenizer_type tok_suffixes(component_path_suffixes, sep);
435         tokenizer_type::iterator end_path = tok_path.end();
436         tokenizer_type::iterator end_suffixes = tok_suffixes.end();
437         plugin_list_type plugin_registries;
438 
439         for (tokenizer_type::iterator it = tok_path.begin(); it != end_path; ++it)
440         {
441             std::string p = *it;
442             for(tokenizer_type::iterator jt = tok_suffixes.begin();
443                 jt != end_suffixes; ++jt)
444             {
445                 std::string path(p);
446                 path += *jt;
447 
448                 if (!path.empty()) {
449                     fs::path this_p(path);
450                     boost::system::error_code fsec;
451                     fs::path canonical_p = util::canonical_path(this_p, fsec);
452                     if (fsec)
453                         canonical_p = this_p;
454 
455                     std::pair<std::set<std::string>::iterator, bool> p =
456                         component_paths.insert(
457                             util::native_file_string(canonical_p));
458 
459                     if (p.second) {
460                         // have all path elements, now find ini files in there...
461                         fs::path this_path (hpx::util::create_path(*p.first));
462                         if (fs::exists(this_path, fsec) && !fsec) {
463                             plugin_list_type tmp_regs =
464                                 util::init_ini_data_default(
465                                     this_path.string(), *this, basenames, modules_);
466 
467                             std::copy(tmp_regs.begin(), tmp_regs.end(),
468                                 std::back_inserter(plugin_registries));
469                         }
470                     }
471                 }
472             }
473         }
474 
475         // read system and user ini files _again_, to allow the user to
476         // overwrite the settings from the default component ini's.
477         util::init_ini_data_base(*this, hpx_ini_file);
478 
479         // let the command line override the config file.
480         if (!cmdline_ini_defs.empty())
481             parse("<command line definitions>", cmdline_ini_defs, true, false);
482 
483         // merge all found ini files of all components
484         util::merge_component_inis(*this);
485 
486         need_to_call_pre_initialize = true;
487 
488         // invoke reconfigure
489         reconfigure();
490 
491         return plugin_registries;
492     }
493 
494     ///////////////////////////////////////////////////////////////////////////
runtime_configuration(char const * argv0_,runtime_mode mode)495     runtime_configuration::runtime_configuration(char const* argv0_, runtime_mode mode)
496       : mode_(mode),
497         num_localities(0),
498         small_stacksize(HPX_SMALL_STACK_SIZE),
499         medium_stacksize(HPX_MEDIUM_STACK_SIZE),
500         large_stacksize(HPX_LARGE_STACK_SIZE),
501         huge_stacksize(HPX_HUGE_STACK_SIZE),
502         need_to_call_pre_initialize(true)
503 #if defined(__linux) || defined(linux) || defined(__linux__)
504         , argv0(argv0_)
505 #endif
506     {
507         pre_initialize_ini();
508 
509         // set global config options
510 #if HPX_HAVE_ITTNOTIFY != 0
511         use_ittnotify_api = get_itt_notify_mode();
512 #endif
513         HPX_ASSERT(init_small_stack_size() >= HPX_SMALL_STACK_SIZE);
514 
515         small_stacksize = init_small_stack_size();
516         medium_stacksize = init_medium_stack_size();
517         large_stacksize = init_large_stack_size();
518         HPX_ASSERT(init_huge_stack_size() <= HPX_HUGE_STACK_SIZE);
519         huge_stacksize = init_huge_stack_size();
520 
521 #if defined(__linux) || defined(linux) || defined(__linux__) || defined(__FreeBSD__)
522         threads::coroutines::detail::posix::use_guard_pages =
523             init_use_stack_guard_pages();
524 #endif
525 #ifdef HPX_HAVE_VERIFY_LOCKS
526         if (enable_lock_detection())
527             util::enable_lock_detection();
528 #endif
529 #ifdef HPX_HAVE_VERIFY_LOCKS_GLOBALLY
530         if (enable_global_lock_detection())
531             util::enable_global_lock_detection();
532 #endif
533 #ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
534         threads::policies::minimal_deadlock_detection =
535             enable_minimal_deadlock_detection();
536 #endif
537 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
538         util::detail::spinlock_break_on_deadlock =
539             enable_spinlock_deadlock_detection();
540         util::detail::spinlock_deadlock_detection_limit =
541             get_spinlock_deadlock_detection_limit();
542 #endif
543     }
544 
545     ///////////////////////////////////////////////////////////////////////////
reconfigure(std::string const & hpx_ini_file_)546     void runtime_configuration::reconfigure(
547         std::string const& hpx_ini_file_)
548     {
549         hpx_ini_file = hpx_ini_file_;
550         reconfigure();
551     }
552 
reconfigure(std::vector<std::string> const & cmdline_ini_defs_)553     void runtime_configuration::reconfigure(
554         std::vector<std::string> const& cmdline_ini_defs_)
555     {
556         cmdline_ini_defs = cmdline_ini_defs_;
557         reconfigure();
558     }
559 
reconfigure()560     void runtime_configuration::reconfigure()
561     {
562         pre_initialize_ini();
563 
564         std::vector<std::string> const& prefill =
565             util::detail::get_logging_data();
566         if (!prefill.empty())
567             this->parse("<static prefill defaults>", prefill, false, false);
568 
569         post_initialize_ini(hpx_ini_file, cmdline_ini_defs);
570 
571         // set global config options
572 #if HPX_HAVE_ITTNOTIFY != 0
573         use_ittnotify_api = get_itt_notify_mode();
574 #endif
575         HPX_ASSERT(init_small_stack_size() >= HPX_SMALL_STACK_SIZE);
576 
577         small_stacksize = init_small_stack_size();
578         medium_stacksize = init_medium_stack_size();
579         large_stacksize = init_large_stack_size();
580         huge_stacksize = init_huge_stack_size();
581 
582 #if defined(__linux) || defined(linux) || defined(__linux__) || defined(__FreeBSD__)
583         threads::coroutines::detail::posix::use_guard_pages =
584             init_use_stack_guard_pages();
585 #endif
586 #ifdef HPX_HAVE_VERIFY_LOCKS
587         if (enable_lock_detection())
588             util::enable_lock_detection();
589 #endif
590 #ifdef HPX_HAVE_VERIFY_LOCKS_GLOBALLY
591         if (enable_global_lock_detection())
592             util::enable_global_lock_detection();
593 #endif
594 #ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
595         threads::policies::minimal_deadlock_detection =
596             enable_minimal_deadlock_detection();
597 #endif
598 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
599         util::detail::spinlock_break_on_deadlock =
600             enable_spinlock_deadlock_detection();
601         util::detail::spinlock_deadlock_detection_limit =
602             get_spinlock_deadlock_detection_limit();
603 #endif
604     }
605 
get_ipc_data_buffer_cache_size() const606     std::size_t runtime_configuration::get_ipc_data_buffer_cache_size() const
607     {
608         if (has_section("hpx.parcel"))
609         {
610             util::section const * sec = get_section("hpx.parcel.ipc");
611             if(nullptr != sec)
612             {
613                 return hpx::util::get_entry_as<std::size_t>(
614                     *sec, "data_buffer_cache_size",
615                     HPX_PARCEL_IPC_DATA_BUFFER_CACHE_SIZE);
616             }
617         }
618         return HPX_PARCEL_IPC_DATA_BUFFER_CACHE_SIZE;
619     }
620 
get_agas_service_mode() const621     agas::service_mode runtime_configuration::get_agas_service_mode() const
622     {
623         // load all components as described in the configuration information
624         if (has_section("hpx.agas"))
625         {
626             util::section const* sec = get_section("hpx.agas");
627             if (nullptr != sec)
628             {
629                 std::string const m = sec->get_entry("service_mode", "hosted");
630 
631                 if (m == "hosted")
632                     return agas::service_mode_hosted;
633                 else if (m == "bootstrap")
634                     return agas::service_mode_bootstrap;
635                 else {
636                     // REVIEW: exception type is overused
637                     HPX_THROW_EXCEPTION(bad_parameter,
638                         "runtime_configuration::get_agas_service_mode",
639                         std::string("invalid AGAS router mode \"") + m + "\"");
640                 }
641             }
642         }
643         return agas::service_mode_hosted;
644     }
645 
get_num_localities() const646     std::uint32_t runtime_configuration::get_num_localities() const
647     {
648         if (num_localities == 0) {
649             if (has_section("hpx")) {
650                 util::section const* sec = get_section("hpx");
651                 if (nullptr != sec) {
652                     num_localities = hpx::util::get_entry_as<std::uint32_t>(
653                         *sec, "localities", 1);
654                 }
655             }
656         }
657 
658         HPX_ASSERT(num_localities != 0);
659         return num_localities;
660     }
661 
set_num_localities(std::uint32_t num_localities_)662     void runtime_configuration::set_num_localities(std::uint32_t num_localities_)
663     {
664         // this function should not be called on the AGAS server
665         HPX_ASSERT(agas::service_mode_bootstrap != get_agas_service_mode());
666         num_localities = num_localities_;
667 
668         if (has_section("hpx")) {
669             util::section* sec = get_section("hpx");
670             if (nullptr != sec) {
671                 sec->add_entry("localities",
672                     std::to_string(num_localities));
673             }
674         }
675     }
676 
get_first_used_core() const677     std::uint32_t runtime_configuration::get_first_used_core() const
678     {
679         if (has_section("hpx")) {
680             util::section const* sec = get_section("hpx");
681             if (nullptr != sec) {
682                 return hpx::util::get_entry_as<std::uint32_t>(
683                     *sec, "first_used_core", 0);
684             }
685         }
686         return 0;
687     }
688 
set_first_used_core(std::uint32_t first_used_core)689     void runtime_configuration::set_first_used_core(
690         std::uint32_t first_used_core)
691     {
692         if (has_section("hpx")) {
693             util::section* sec = get_section("hpx");
694             if (nullptr != sec) {
695                 sec->add_entry("first_used_core",
696                     std::to_string(first_used_core));
697             }
698         }
699     }
700 
get_agas_local_cache_size(std::size_t dflt) const701     std::size_t runtime_configuration::get_agas_local_cache_size(std::size_t dflt) const
702     {
703         std::size_t cache_size = dflt;
704 
705         if (has_section("hpx.agas")) {
706             util::section const* sec = get_section("hpx.agas");
707             if (nullptr != sec) {
708                 cache_size = hpx::util::get_entry_as<std::size_t>(
709                     *sec, "local_cache_size", cache_size);
710             }
711         }
712 
713         if (cache_size != std::size_t(~0x0ul) && cache_size < 16ul)
714             cache_size = 16;      // limit lower bound
715         return cache_size;
716     }
717 
get_agas_caching_mode() const718     bool runtime_configuration::get_agas_caching_mode() const
719     {
720         if (has_section("hpx.agas")) {
721             util::section const* sec = get_section("hpx.agas");
722             if (nullptr != sec) {
723                 return hpx::util::get_entry_as<int>(
724                     *sec, "use_caching", "1") != 0;
725             }
726         }
727         return false;
728     }
729 
get_agas_range_caching_mode() const730     bool runtime_configuration::get_agas_range_caching_mode() const
731     {
732         if (has_section("hpx.agas")) {
733             util::section const* sec = get_section("hpx.agas");
734             if (nullptr != sec) {
735                 return hpx::util::get_entry_as<int>(
736                     *sec, "use_range_caching", "1") != 0;
737             }
738         }
739         return false;
740     }
741 
742     std::size_t
get_agas_max_pending_refcnt_requests() const743     runtime_configuration::get_agas_max_pending_refcnt_requests() const
744     {
745         if (has_section("hpx.agas")) {
746             util::section const* sec = get_section("hpx.agas");
747             if (nullptr != sec) {
748                 return hpx::util::get_entry_as<std::size_t>(
749                     *sec, "max_pending_refcnt_requests",
750                     HPX_INITIAL_AGAS_MAX_PENDING_REFCNT_REQUESTS);
751             }
752         }
753         return HPX_INITIAL_AGAS_MAX_PENDING_REFCNT_REQUESTS;
754     }
755 
get_itt_notify_mode() const756     bool runtime_configuration::get_itt_notify_mode() const
757     {
758 #if HPX_HAVE_ITTNOTIFY != 0
759         if (has_section("hpx")) {
760             util::section const* sec = get_section("hpx");
761             if (nullptr != sec) {
762                 return hpx::util::get_entry_as<int>(
763                     *sec, "use_itt_notify", "0") != 0;
764             }
765         }
766 #endif
767         return false;
768     }
769 
770     // Enable lock detection during suspension
enable_lock_detection() const771     bool runtime_configuration::enable_lock_detection() const
772     {
773 #ifdef HPX_HAVE_VERIFY_LOCKS
774         if (has_section("hpx")) {
775             util::section const* sec = get_section("hpx");
776             if (nullptr != sec) {
777                 return hpx::util::get_entry_as<int>(
778                     *sec, "lock_detection", "0") != 0;
779             }
780         }
781 #endif
782         return false;
783     }
784 
785     // Enable global lock tracking
enable_global_lock_detection() const786     bool runtime_configuration::enable_global_lock_detection() const
787     {
788 #ifdef HPX_HAVE_VERIFY_LOCKS_GLOBALLY
789         if (has_section("hpx")) {
790             util::section const* sec = get_section("hpx");
791             if (nullptr != sec) {
792                 return hpx::util::get_entry_as<int>(
793                     *sec, "global_lock_detection", "0") != 0;
794             }
795         }
796 #endif
797         return false;
798     }
799 
800     // Enable minimal deadlock detection for HPX threads
enable_minimal_deadlock_detection() const801     bool runtime_configuration::enable_minimal_deadlock_detection() const
802     {
803 #ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
804         if (has_section("hpx")) {
805             util::section const* sec = get_section("hpx");
806             if (nullptr != sec) {
807 #ifdef HPX_DEBUG
808                 return hpx::util::get_entry_as<int>(
809                     *sec, "minimal_deadlock_detection", "1") != 0;
810 #else
811                 return hpx::util::get_entry_as<int>(
812                     *sec, "minimal_deadlock_detection", "0") != 0;
813 #endif
814             }
815         }
816 
817 #ifdef HPX_DEBUG
818         return true;
819 #else
820         return false;
821 #endif
822 
823 #else
824         return false;
825 #endif
826     }
827 
828     ///////////////////////////////////////////////////////////////////////////
enable_spinlock_deadlock_detection() const829     bool runtime_configuration::enable_spinlock_deadlock_detection() const
830     {
831 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
832         if (has_section("hpx")) {
833             util::section const* sec = get_section("hpx");
834             if (nullptr != sec) {
835 #ifdef HPX_DEBUG
836                 return hpx::util::get_entry_as<int>(
837                     *sec, "spinlock_deadlock_detection", "1") != 0;
838 #else
839                 return hpx::util::get_entry_as<int>(
840                     *sec, "spinlock_deadlock_detection", "0") != 0;
841 #endif
842             }
843         }
844 
845 #ifdef HPX_DEBUG
846         return true;
847 #else
848         return false;
849 #endif
850 
851 #else
852         return false;
853 #endif
854     }
855 
856     ///////////////////////////////////////////////////////////////////////////
get_spinlock_deadlock_detection_limit() const857     std::size_t runtime_configuration::get_spinlock_deadlock_detection_limit() const
858     {
859 #ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
860         if (has_section("hpx")) {
861             util::section const* sec = get_section("hpx");
862             if (nullptr != sec) {
863                 return hpx::util::get_entry_as<std::size_t>(
864                     *sec, "spinlock_deadlock_detection_limit", "1000000");
865             }
866         }
867         return HPX_SPINLOCK_DEADLOCK_DETECTION_LIMIT;
868 #else
869         return std::size_t(-1);
870 #endif
871     }
872 
get_os_thread_count() const873     std::size_t runtime_configuration::get_os_thread_count() const
874     {
875         if (has_section("hpx")) {
876             util::section const* sec = get_section("hpx");
877             if (nullptr != sec) {
878                 return hpx::util::get_entry_as<std::size_t>(
879                     *sec, "os_threads", 1);
880             }
881         }
882         return 1;
883     }
884 
get_cmd_line() const885     std::string runtime_configuration::get_cmd_line() const
886     {
887         if (has_section("hpx")) {
888             util::section const* sec = get_section("hpx");
889             if (nullptr != sec) {
890                 return sec->get_entry("cmd_line", "");
891             }
892         }
893         return "";
894     }
895 
896     // Return the configured sizes of any of the know thread pools
get_thread_pool_size(char const * poolname) const897     std::size_t runtime_configuration::get_thread_pool_size(char const* poolname) const
898     {
899         if (has_section("hpx.threadpools")) {
900             util::section const* sec = get_section("hpx.threadpools");
901             if (nullptr != sec) {
902                 return hpx::util::get_entry_as<std::size_t>(
903                     *sec, std::string(poolname) + "_size", "2");
904             }
905         }
906         return 2;     // the default size for all pools is 2
907     }
908 
909     // Return the endianess to be used for out-serialization
get_endian_out() const910     std::string runtime_configuration::get_endian_out() const
911     {
912         if (has_section("hpx.parcel")) {
913             util::section const* sec = get_section("hpx.parcel");
914             if (nullptr != sec) {
915 #ifdef BOOST_BIG_ENDIAN
916                 return sec->get_entry("endian_out", "big");
917 #else
918                 return sec->get_entry("endian_out", "little");
919 #endif
920             }
921         }
922 #ifdef BOOST_BIG_ENDIAN
923         return "big";
924 #else
925         return "little";
926 #endif
927     }
928 
929     // Will return the stack size to use for all HPX-threads.
init_stack_size(char const * entryname,char const * defaultvaluestr,std::ptrdiff_t defaultvalue) const930     std::ptrdiff_t runtime_configuration::init_stack_size(
931         char const* entryname, char const* defaultvaluestr,
932         std::ptrdiff_t defaultvalue) const
933     {
934         if (has_section("hpx")) {
935             util::section const* sec = get_section("hpx.stacks");
936             if (nullptr != sec) {
937                 std::string entry = sec->get_entry(entryname, defaultvaluestr);
938                 std::ptrdiff_t val = defaultvalue;
939 
940                 namespace qi = boost::spirit::qi;
941                 qi::parse(entry.begin(), entry.end(),
942                     "0x" >> qi::hex | "0" >> qi::oct | qi::int_, val);
943                 return val;
944             }
945         }
946         return defaultvalue;
947     }
948 
949 #if defined(__linux) || defined(linux) || defined(__linux__) || defined(__FreeBSD__)
init_use_stack_guard_pages() const950     bool runtime_configuration::init_use_stack_guard_pages() const
951     {
952         if (has_section("hpx")) {
953             util::section const* sec = get_section("hpx.stacks");
954             if (nullptr != sec) {
955                 return hpx::util::get_entry_as<int>(
956                     *sec, "use_guard_pages", "1") != 0;
957             }
958         }
959         return true;    // default is true
960     }
961 #endif
962 
init_small_stack_size() const963     std::ptrdiff_t runtime_configuration::init_small_stack_size() const
964     {
965         return init_stack_size("small_size",
966             HPX_PP_STRINGIZE(HPX_SMALL_STACK_SIZE), HPX_SMALL_STACK_SIZE);
967     }
968 
init_medium_stack_size() const969     std::ptrdiff_t runtime_configuration::init_medium_stack_size() const
970     {
971         return init_stack_size("medium_size",
972             HPX_PP_STRINGIZE(HPX_MEDIUM_STACK_SIZE), HPX_MEDIUM_STACK_SIZE);
973     }
974 
init_large_stack_size() const975     std::ptrdiff_t runtime_configuration::init_large_stack_size() const
976     {
977         return init_stack_size("large_size",
978             HPX_PP_STRINGIZE(HPX_LARGE_STACK_SIZE), HPX_LARGE_STACK_SIZE);
979     }
980 
init_huge_stack_size() const981     std::ptrdiff_t runtime_configuration::init_huge_stack_size() const
982     {
983         return init_stack_size("huge_size",
984             HPX_PP_STRINGIZE(HPX_HUGE_STACK_SIZE), HPX_HUGE_STACK_SIZE);
985     }
986 
987     ///////////////////////////////////////////////////////////////////////////
988     // Return maximally allowed message size
get_max_inbound_message_size() const989     std::uint64_t runtime_configuration::get_max_inbound_message_size() const
990     {
991         if (has_section("hpx")) {
992             util::section const* sec = get_section("hpx.parcel");
993             if (nullptr != sec) {
994                 std::uint64_t maxsize =
995                     hpx::util::get_entry_as<std::uint64_t>(
996                         *sec, "max_message_size", HPX_PARCEL_MAX_MESSAGE_SIZE);
997                 if (maxsize > 0)
998                     return maxsize;
999             }
1000         }
1001         return HPX_PARCEL_MAX_MESSAGE_SIZE;    // default is 1GByte
1002     }
1003 
get_max_outbound_message_size() const1004     std::uint64_t runtime_configuration::get_max_outbound_message_size() const
1005     {
1006         if (has_section("hpx")) {
1007             util::section const* sec = get_section("hpx.parcel");
1008             if (nullptr != sec) {
1009                 std::uint64_t maxsize =
1010                     hpx::util::get_entry_as<std::uint64_t>(
1011                         *sec, "max_outbound_message_size",
1012                         HPX_PARCEL_MAX_OUTBOUND_MESSAGE_SIZE);
1013                 if (maxsize > 0)
1014                     return maxsize;
1015             }
1016         }
1017         return HPX_PARCEL_MAX_OUTBOUND_MESSAGE_SIZE;    // default is 1GByte
1018     }
1019 
1020     ///////////////////////////////////////////////////////////////////////////
load_application_configuration(char const * filename,error_code & ec)1021     bool runtime_configuration::load_application_configuration(
1022         char const* filename, error_code& ec)
1023     {
1024         try {
1025             section appcfg(filename);
1026             section applroot;
1027             applroot.add_section("application", appcfg);
1028             this->section::merge(applroot);
1029         }
1030         catch (hpx::exception const& e) {
1031             // file doesn't exist or is ill-formed
1032             if (&ec == &throws)
1033                 throw;
1034             ec = make_error_code(e.get_error(), e.what(), hpx::rethrow);
1035             return false;
1036         }
1037         return true;
1038     }
1039 
1040     ///////////////////////////////////////////////////////////////////////////
get_stack_size(threads::thread_stacksize stacksize) const1041     std::ptrdiff_t runtime_configuration::get_stack_size(
1042         threads::thread_stacksize stacksize) const
1043     {
1044         switch (stacksize) {
1045         case threads::thread_stacksize_medium:
1046             return medium_stacksize;
1047 
1048         case threads::thread_stacksize_large:
1049             return large_stacksize;
1050 
1051         case threads::thread_stacksize_huge:
1052             return huge_stacksize;
1053 
1054         default:
1055         case threads::thread_stacksize_small:
1056             break;
1057         }
1058         return small_stacksize;
1059     }
1060 }}
1061 
1062