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