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