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