• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #881

05 Feb 2023 11:26PM UTC coverage: 86.546% (+0.6%) from 85.952%
#881

push

StellarBot
Merge #6157

6157: Improve index_queue_spawning r=hkaiser a=hkaiser

- synchronous for_each_partitioner now binds tasks to cores
- add scheduling properties: get_first_core and with_first_core
- index_queue_spawning now supports first_core
- adapt rotate to use first_core for partitions


Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

416 of 416 new or added lines in 18 files covered. (100.0%)

174866 of 202049 relevant lines covered (86.55%)

1824233.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.0
/libs/core/runtime_local/src/runtime_local.cpp
1
//  Copyright (c) 2007-2022 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#include <hpx/assert.hpp>
10
#include <hpx/command_line_handling_local/late_command_line_handling_local.hpp>
11
#include <hpx/command_line_handling_local/parse_command_line_local.hpp>
12
#include <hpx/coroutines/coroutine.hpp>
13
#include <hpx/coroutines/signal_handler_debugging.hpp>
14
#include <hpx/debugging/backtrace.hpp>
15
#include <hpx/execution_base/this_thread.hpp>
16
#include <hpx/functional/bind.hpp>
17
#include <hpx/functional/function.hpp>
18
#include <hpx/itt_notify/thread_name.hpp>
19
#include <hpx/modules/errors.hpp>
20
#include <hpx/modules/logging.hpp>
21
#include <hpx/modules/threadmanager.hpp>
22
#include <hpx/runtime_local/config_entry.hpp>
23
#include <hpx/runtime_local/custom_exception_info.hpp>
24
#include <hpx/runtime_local/debugging.hpp>
25
#include <hpx/runtime_local/os_thread_type.hpp>
26
#include <hpx/runtime_local/runtime_local.hpp>
27
#include <hpx/runtime_local/runtime_local_fwd.hpp>
28
#include <hpx/runtime_local/shutdown_function.hpp>
29
#include <hpx/runtime_local/startup_function.hpp>
30
#include <hpx/runtime_local/state.hpp>
31
#include <hpx/runtime_local/thread_hooks.hpp>
32
#include <hpx/runtime_local/thread_mapper.hpp>
33
#include <hpx/static_reinit/static_reinit.hpp>
34
#include <hpx/thread_support/set_thread_name.hpp>
35
#include <hpx/threading_base/external_timer.hpp>
36
#include <hpx/threading_base/scheduler_mode.hpp>
37
#include <hpx/timing/high_resolution_clock.hpp>
38
#include <hpx/topology/topology.hpp>
39
#include <hpx/util/from_string.hpp>
40
#include <hpx/version.hpp>
41

42
#include <atomic>
43
#include <condition_variable>
44
#include <cstddef>
45
#include <cstdint>
46
#include <cstring>
47
#include <exception>
48
#include <functional>
49
#include <iomanip>
50
#include <iostream>
51
#include <list>
52
#include <memory>
53
#include <mutex>
54
#include <sstream>
55
#include <string>
56
#include <thread>
57
#include <utility>
58

59
///////////////////////////////////////////////////////////////////////////////
60
// Make sure the system gets properly shut down while handling Ctrl-C and other
61
// system signals
62
#if defined(HPX_WINDOWS)
63

64
namespace hpx {
65
    ///////////////////////////////////////////////////////////////////////////
66
    void handle_termination(char const* reason)
67
    {
68
        if (hpx::threads::coroutines::attach_debugger_on_sigv)
69
        {
70
            util::attach_debugger();
71
        }
72

73
        if (hpx::threads::coroutines::diagnostics_on_terminate)
74
        {
75
            int const verbosity = hpx::threads::coroutines::exception_verbosity;
76

77
            if (verbosity >= 2)
78
            {
79
                std::cerr << full_build_string() << "\n";
80
            }
81

82
#if defined(HPX_HAVE_STACKTRACES)
83
            if (verbosity >= 1)
84
            {
85
                std::size_t const trace_depth =
86
                    util::from_string<std::size_t>(get_config_entry(
87
                        "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
88
                std::cerr << "{stack-trace}: " << hpx::util::trace(trace_depth)
89
                          << "\n";
90
            }
91
#endif
92

93
            std::cerr << "{what}: " << (reason ? reason : "Unknown reason")
94
                      << "\n";
95
        }
96
    }
97

98
    HPX_CORE_EXPORT BOOL WINAPI termination_handler(DWORD ctrl_type)
99
    {
100
        switch (ctrl_type)
101
        {
102
        case CTRL_C_EVENT:
103
            handle_termination("Ctrl-C");
104
            break;
105

106
        case CTRL_BREAK_EVENT:
107
            handle_termination("Ctrl-Break");
108
            break;
109

110
        case CTRL_CLOSE_EVENT:
111
            handle_termination("Ctrl-Close");
112
            break;
113

114
        case CTRL_LOGOFF_EVENT:
115
            handle_termination("Logoff");
116
            break;
117

118
        case CTRL_SHUTDOWN_EVENT:
119
            handle_termination("Shutdown");
120
            break;
121

122
        default:
123
            break;
124
        }
125
        return FALSE;
126
    }
127
}    // namespace hpx
128

129
#else
130

131
#include <signal.h>
132
#include <stdlib.h>
133
#include <string.h>
134

135
namespace hpx {
136
    ///////////////////////////////////////////////////////////////////////////
137
    [[noreturn]] HPX_CORE_EXPORT void termination_handler(int signum)
×
138
    {
139
        if (signum != SIGINT &&
×
140
            hpx::threads::coroutines::attach_debugger_on_sigv)
×
141
        {
142
            util::attach_debugger();
×
143
        }
×
144

145
        if (hpx::threads::coroutines::diagnostics_on_terminate)
×
146
        {
147
            int const verbosity = hpx::threads::coroutines::exception_verbosity;
×
148
            char* reason = strsignal(signum);
×
149

150
            if (verbosity >= 2)
×
151
            {
152
                std::cerr << full_build_string() << "\n";
×
153
            }
×
154

155
#if defined(HPX_HAVE_STACKTRACES)
156
            if (verbosity >= 1)
×
157
            {
158
                std::size_t const trace_depth =
×
159
                    util::from_string<std::size_t>(get_config_entry(
×
160
                        "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
×
161
                std::cerr << "{stack-trace}: " << hpx::util::trace(trace_depth)
×
162
                          << "\n";
×
163
            }
×
164
#endif
165

166
            std::cerr << "{what}: " << (reason ? reason : "Unknown reason")
×
167
                      << "\n";
×
168
        }
×
169
        std::abort();
×
170
    }
×
171
}    // namespace hpx
172

173
#endif
174

175
///////////////////////////////////////////////////////////////////////////////
176
namespace hpx {
177

178
    ///////////////////////////////////////////////////////////////////////////
179
    HPX_CORE_EXPORT void HPX_CDECL new_handler()
×
180
    {
181
        HPX_THROW_EXCEPTION(hpx::error::out_of_memory, "new_handler",
×
182
            "new allocator failed to allocate memory");
183
    }
×
184

185
    ///////////////////////////////////////////////////////////////////////////
186
    namespace detail {
187
        // Sometimes the HPX library gets simply unloaded as a result of some
188
        // extreme error handling. Avoid hangs in the end by setting a flag.
189
        static bool exit_called = false;
190

191
        void on_exit() noexcept
1,225✔
192
        {
193
            exit_called = true;
1,225✔
194
        }
1,225✔
195

196
        void on_abort(int) noexcept
1✔
197
        {
198
            exit_called = true;
×
199
            std::exit(-1);
×
200
        }
201
    }    // namespace detail
202

203
    ///////////////////////////////////////////////////////////////////////////
204
    void set_error_handlers()
1,225✔
205
    {
206
        // initialize global variables
207
        hpx::threads::coroutines::attach_debugger_on_sigv =
1,225✔
208
            get_config_entry("hpx.attach_debugger", "") == "exception";
1,225✔
209
        hpx::threads::coroutines::diagnostics_on_terminate =
1,225✔
210
            get_config_entry("hpx.diagnostics_on_terminate", "1") == "1";
1,225✔
211
        hpx::threads::coroutines::exception_verbosity = util::from_string<int>(
1,225✔
212
            get_config_entry("hpx.exception_verbosity", "2"));
1,225✔
213
        hpx::threads::coroutines::exception_verbosity = 0;
1,225✔
214
#if defined(HPX_HAVE_STACKTRACES) && defined(HPX_HAVE_THREAD_BACKTRACE_DEPTH)
215
        hpx::threads::coroutines::exception_verbosity =
1,225✔
216
            util::from_string<int>(get_config_entry(
1,225✔
217
                "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
1,225✔
218
#endif
219

220
#if defined(HPX_WINDOWS)
221
        // Set console control handler to allow server to be stopped.
222
        SetConsoleCtrlHandler(hpx::termination_handler, TRUE);
223
#else
224
        if (util::from_string<int>(get_config_entry("hpx.handle_signals", 1)))
1,225✔
225
        {
226
            struct sigaction new_action;
227
            new_action.sa_handler = hpx::termination_handler;
1,225✔
228
            sigemptyset(&new_action.sa_mask);
1,225✔
229
            new_action.sa_flags = 0;
1,225✔
230

231
            sigaction(SIGINT, &new_action, nullptr);    // Interrupted
1,225✔
232
            sigaction(SIGBUS, &new_action, nullptr);    // Bus error
1,225✔
233
            sigaction(
1,225✔
234
                SIGFPE, &new_action, nullptr);    // Floating point exception
235
            sigaction(SIGILL, &new_action, nullptr);     // Illegal instruction
1,225✔
236
            sigaction(SIGPIPE, &new_action, nullptr);    // Bad pipe
1,225✔
237
            sigaction(SIGSEGV, &new_action, nullptr);    // Segmentation fault
1,225✔
238
            sigaction(SIGSYS, &new_action, nullptr);     // Bad syscall
1,225✔
239

240
            hpx::threads::coroutines::register_signal_handler = false;
1,225✔
241
        }
1,225✔
242
        else
243
        {
244
            hpx::threads::coroutines::register_signal_handler = true;
×
245
        }
246
#endif
247

248
        std::set_new_handler(hpx::new_handler);
1,225✔
249
    }
1,225✔
250

251
    ///////////////////////////////////////////////////////////////////////////
252
    namespace strings {
253
        inline constexpr char const* const runtime_state_names[] = {
254
            "state::invalid",         // -1
255
            "state::initialized",     // 0
256
            "state::pre_startup",     // 1
257
            "state::startup",         // 2
258
            "state::pre_main",        // 3
259
            "state::starting",        // 4
260
            "state::running",         // 5
261
            "state::suspended",       // 6
262
            "state::pre_sleep",       // 7
263
            "state::sleeping",        // 8
264
            "state::pre_shutdown",    // 9
265
            "state::shutdown",        // 10
266
            "state::stopping",        // 11
267
            "state::terminating",     // 12
268
            "state::stopped"          // 13
269
        };
270
    }
271

272
    char const* get_runtime_state_name(state s)
2,534✔
273
    {
274
        if (s < state::invalid || s >= state::last_valid_runtime_state)
2,534✔
275
        {
276
            return "invalid (value out of bounds)";
×
277
        }
278
        return strings::runtime_state_names[static_cast<int>(s) + 1];
2,534✔
279
    }
2,534✔
280

281
    ///////////////////////////////////////////////////////////////////////////
282
    threads::policies::callback_notifier::on_startstop_type
283
        global_on_start_func;
1,255✔
284
    threads::policies::callback_notifier::on_startstop_type global_on_stop_func;
1,255✔
285
    threads::policies::callback_notifier::on_error_type global_on_error_func;
1,255✔
286

287
    ///////////////////////////////////////////////////////////////////////////
288
    runtime::runtime(hpx::util::runtime_configuration& rtcfg, bool initialize)
2,508✔
289
      : rtcfg_(rtcfg)
627✔
290
      , instance_number_(++instance_number_counter_)
627✔
291
      , thread_support_(new util::thread_mapper)
627✔
292
      , topology_(resource::get_partitioner().get_topology())
627✔
293
      , state_(state::invalid)
627✔
294
      , on_start_func_(global_on_start_func)
627✔
295
      , on_stop_func_(global_on_stop_func)
627✔
296
      , on_error_func_(global_on_error_func)
627✔
297
      , result_(0)
627✔
298
      , main_pool_notifier_()
627✔
299
      , main_pool_(main_pool_notifier_, "main_pool")
627✔
300
#ifdef HPX_HAVE_IO_POOL
301
      , io_pool_notifier_()
627✔
302
      , io_pool_(io_pool_notifier_, "io_pool")
627✔
303
#endif
304
#ifdef HPX_HAVE_TIMER_POOL
305
      , timer_pool_notifier_()
627✔
306
      , timer_pool_(timer_pool_notifier_, "timer_pool")
627✔
307
#endif
308
      , notifier_()
627✔
309
      , thread_manager_()
627✔
310
      , stop_called_(false)
627✔
311
      , stop_done_(false)
627✔
312
    {
627✔
313
        LPROGRESS_;
627✔
314

315
        // set notification policies only after the object was completely
316
        // initialized
317
        runtime::set_notification_policies(
627✔
318
            runtime::get_notification_policy(
627✔
319
                "worker-thread", runtime_local::os_thread_type::worker_thread),
320
#ifdef HPX_HAVE_IO_POOL
321
            runtime::get_notification_policy(
627✔
322
                "io-thread", runtime_local::os_thread_type::io_thread),
323
#endif
324
#ifdef HPX_HAVE_TIMER_POOL
325
            runtime::get_notification_policy(
627✔
326
                "timer-thread", runtime_local::os_thread_type::timer_thread),
327
#endif
328
            threads::detail::network_background_callback_type{});
627✔
329

330
        init_global_data();
627✔
331
        util::reinit_construct();
627✔
332

333
        if (initialize)
627✔
334
        {
335
            runtime::init();
627✔
336
        }
627✔
337
    }
627✔
338

339
    // this constructor is called by the distributed runtime only
340
    runtime::runtime(hpx::util::runtime_configuration& rtcfg)
2,380✔
341
      : rtcfg_(rtcfg)
595✔
342
      , instance_number_(++instance_number_counter_)
595✔
343
      , thread_support_(new util::thread_mapper)
595✔
344
      , topology_(resource::get_partitioner().get_topology())
595✔
345
      , state_(state::invalid)
595✔
346
      , on_start_func_(global_on_start_func)
595✔
347
      , on_stop_func_(global_on_stop_func)
595✔
348
      , on_error_func_(global_on_error_func)
595✔
349
      , result_(0)
595✔
350
      , main_pool_notifier_()
595✔
351
      , main_pool_(main_pool_notifier_, "main_pool")
595✔
352
#ifdef HPX_HAVE_IO_POOL
353
      , io_pool_notifier_()
595✔
354
      , io_pool_(io_pool_notifier_, "io_pool")
595✔
355
#endif
356
#ifdef HPX_HAVE_TIMER_POOL
357
      , timer_pool_notifier_()
595✔
358
      , timer_pool_(timer_pool_notifier_, "timer_pool")
595✔
359
#endif
360
      , notifier_()
595✔
361
      , thread_manager_()
595✔
362
      , stop_called_(false)
595✔
363
      , stop_done_(false)
595✔
364
    {
595✔
365
        init_global_data();
595✔
366
        util::reinit_construct();
595✔
367

368
        LPROGRESS_;
595✔
369
    }
595✔
370

371
    void runtime::set_notification_policies(notification_policy_type&& notifier,
1,222✔
372
#ifdef HPX_HAVE_IO_POOL
373
        notification_policy_type&& io_pool_notifier,
374
#endif
375
#ifdef HPX_HAVE_TIMER_POOL
376
        notification_policy_type&& timer_pool_notifier,
377
#endif
378
        threads::detail::network_background_callback_type
379
            network_background_callback)
380
    {
381
        notifier_ = HPX_MOVE(notifier);
1,222✔
382

383
        main_pool_.init(1);
1,222✔
384
#ifdef HPX_HAVE_IO_POOL
385
        io_pool_notifier_ = HPX_MOVE(io_pool_notifier);
1,222✔
386
        io_pool_.init(rtcfg_.get_thread_pool_size("io_pool"));
1,222✔
387
#endif
388
#ifdef HPX_HAVE_TIMER_POOL
389
        timer_pool_notifier_ = HPX_MOVE(timer_pool_notifier);
1,222✔
390
        timer_pool_.init(rtcfg_.get_thread_pool_size("timer_pool"));
1,222✔
391
#endif
392

393
        thread_manager_.reset(new hpx::threads::threadmanager(rtcfg_,
1,222✔
394
#ifdef HPX_HAVE_TIMER_POOL
395
            timer_pool_,
1,222✔
396
#endif
397
            notifier_, network_background_callback));
1,222✔
398
    }
1,222✔
399

400
    void runtime::init()
1,222✔
401
    {
402
        LPROGRESS_;
1,222✔
403

404
        try
405
        {
406
            // now create all threadmanager pools
407
            thread_manager_->create_pools();
1,222✔
408

409
            // this initializes the used_processing_units_ mask
410
            thread_manager_->init();
1,222✔
411

412
            // copy over all startup functions registered so far
413
            for (startup_function_type& f :
1,222✔
414
                detail::global_pre_startup_functions())
1,222✔
415
            {
416
                add_pre_startup_function(HPX_MOVE(f));
×
417
            }
418
            detail::global_pre_startup_functions().clear();
1,222✔
419

420
            for (startup_function_type& f : detail::global_startup_functions())
1,813✔
421
            {
422
                add_startup_function(HPX_MOVE(f));
591✔
423
            }
424
            detail::global_startup_functions().clear();
1,222✔
425

426
            for (shutdown_function_type& f :
1,222✔
427
                detail::global_pre_shutdown_functions())
1,222✔
428
            {
429
                add_pre_shutdown_function(HPX_MOVE(f));
×
430
            }
431
            detail::global_pre_shutdown_functions().clear();
1,222✔
432

433
            for (shutdown_function_type& f :
1,222✔
434
                detail::global_shutdown_functions())
1,222✔
435
            {
436
                add_shutdown_function(HPX_MOVE(f));
×
437
            }
438
            detail::global_shutdown_functions().clear();
1,222✔
439
        }
1,222✔
440
        catch (std::exception const& e)
441
        {
442
            // errors at this point need to be reported directly
443
            detail::report_exception_and_terminate(e);
×
444
        }
×
445
        catch (...)
446
        {
447
            // errors at this point need to be reported directly
448
            detail::report_exception_and_terminate(std::current_exception());
×
449
        }
×
450

451
        // set state to initialized
452
        set_state(state::initialized);
1,222✔
453
    }
1,222✔
454

455
    runtime::~runtime()
1,844✔
456
    {
1,844✔
457
        LRT_(debug).format("~runtime_local(entering)");
1,219✔
458

459
        // stop all services
460
        thread_manager_->stop();    // stops timer_pool_ as well
1,219✔
461
#ifdef HPX_HAVE_IO_POOL
462
        io_pool_.stop();
1,219✔
463
#endif
464
        LRT_(debug).format("~runtime_local(finished)");
1,219✔
465

466
        LPROGRESS_;
1,219✔
467

468
        // allow to reuse instance number if this was the only instance
469
        if (0 == instance_number_counter_)
1,219✔
470
            --instance_number_counter_;
1,219✔
471

472
        util::reinit_destruct();
1,219✔
473
        resource::detail::delete_partitioner();
1,219✔
474
    }
1,844✔
475

476
    void runtime::on_exit(hpx::function<void()> const& f)
×
477
    {
478
        std::lock_guard<std::mutex> l(mtx_);
×
479
        on_exit_functions_.push_back(f);
×
480
    }
×
481

482
    void runtime::starting()
1,222✔
483
    {
484
        state_.store(hpx::state::pre_main);
1,222✔
485
    }
1,222✔
486

487
    void runtime::stopping()
1,220✔
488
    {
489
        state_.store(hpx::state::stopped);
1,220✔
490

491
        std::lock_guard<std::mutex> l(mtx_);
1,220✔
492
        for (auto const& f : on_exit_functions_)
1,220✔
493
            f();
×
494
    }
1,220✔
495

496
    bool runtime::stopped() const
×
497
    {
498
        return state_.load() == hpx::state::stopped;
×
499
    }
500

501
    hpx::util::runtime_configuration& runtime::get_config()
1,654,348✔
502
    {
503
        return rtcfg_;
1,654,344✔
504
    }
505

506
    hpx::util::runtime_configuration const& runtime::get_config() const
67,872✔
507
    {
508
        return rtcfg_;
67,872✔
509
    }
510

511
    std::size_t runtime::get_instance_number() const
2✔
512
    {
513
        return static_cast<std::size_t>(instance_number_);
2✔
514
    }
515

516
    state runtime::get_state() const
93,424,653✔
517
    {
518
        return state_.load();
93,425,735✔
519
    }
520

521
    threads::topology const& runtime::get_topology() const
5✔
522
    {
523
        return topology_;
5✔
524
    }
525

526
    void runtime::set_state(state s)
6,909✔
527
    {
528
        LPROGRESS_ << get_runtime_state_name(s);
6,909✔
529
        state_.store(s);
6,909✔
530
    }
6,909✔
531

532
    ///////////////////////////////////////////////////////////////////////////
533
    std::atomic<int> runtime::instance_number_counter_(-1);
534

535
    ///////////////////////////////////////////////////////////////////////////
536
    namespace {
537
        std::uint64_t& runtime_uptime()
2,532✔
538
        {
539
            static std::uint64_t uptime = 0;
540
            return uptime;
2,532✔
541
        }
542
    }    // namespace
543

544
    void runtime::init_global_data()
1,222✔
545
    {
546
        runtime*& runtime_ = get_runtime_ptr();
1,222✔
547
        HPX_ASSERT(!runtime_);
1,222✔
548
        HPX_ASSERT(nullptr == threads::thread_self::get_self());
1,222✔
549

550
        runtime_ = this;
1,222✔
551
        runtime_uptime() = hpx::chrono::high_resolution_clock::now();
1,222✔
552
    }
1,222✔
553

554
    void runtime::deinit_global_data()
1,220✔
555
    {
556
        runtime*& runtime_ = get_runtime_ptr();
1,220✔
557
        HPX_ASSERT(runtime_);
1,220✔
558
        runtime_uptime() = 0;
1,220✔
559
        runtime_ = nullptr;
1,220✔
560
    }
1,220✔
561

562
    std::uint64_t runtime::get_system_uptime()
90✔
563
    {
564
        std::int64_t diff =
90✔
565
            hpx::chrono::high_resolution_clock::now() - runtime_uptime();
90✔
566
        return diff < 0LL ? 0ULL : static_cast<std::uint64_t>(diff);
90✔
567
    }
568

569
    threads::policies::callback_notifier::on_startstop_type
570
    runtime::on_start_func() const
×
571
    {
572
        return on_start_func_;
×
573
    }
574

575
    threads::policies::callback_notifier::on_startstop_type
576
    runtime::on_stop_func() const
×
577
    {
578
        return on_stop_func_;
×
579
    }
580

581
    threads::policies::callback_notifier::on_error_type runtime::on_error_func()
×
582
        const
583
    {
584
        return on_error_func_;
×
585
    }
586

587
    threads::policies::callback_notifier::on_startstop_type
588
    runtime::on_start_func(
×
589
        threads::policies::callback_notifier::on_startstop_type&& f)
590
    {
591
        threads::policies::callback_notifier::on_startstop_type newf =
×
592
            HPX_MOVE(f);
×
593
        std::swap(on_start_func_, newf);
×
594
        return newf;
×
595
    }
×
596

597
    threads::policies::callback_notifier::on_startstop_type
598
    runtime::on_stop_func(
×
599
        threads::policies::callback_notifier::on_startstop_type&& f)
600
    {
601
        threads::policies::callback_notifier::on_startstop_type newf =
×
602
            HPX_MOVE(f);
×
603
        std::swap(on_stop_func_, newf);
×
604
        return newf;
×
605
    }
×
606

607
    threads::policies::callback_notifier::on_error_type runtime::on_error_func(
×
608
        threads::policies::callback_notifier::on_error_type&& f)
609
    {
610
        threads::policies::callback_notifier::on_error_type newf = HPX_MOVE(f);
×
611
        std::swap(on_error_func_, newf);
×
612
        return newf;
×
613
    }
×
614

615
    std::uint32_t runtime::get_locality_id(error_code& /* ec */) const
24,565,393✔
616
    {
617
        return 0;
24,566,194✔
618
    }
619

620
    std::size_t runtime::get_num_worker_threads() const
1,129✔
621
    {
622
        HPX_ASSERT(thread_manager_);
1,129✔
623
        return thread_manager_->get_os_thread_count();
1,129✔
624
    }
625

626
    std::uint32_t runtime::get_num_localities(
1✔
627
        hpx::launch::sync_policy, error_code& /* ec */) const
628
    {
629
        return 1;
1✔
630
    }
631

632
    std::uint32_t runtime::get_initial_num_localities() const
×
633
    {
634
        return 1;
×
635
    }
636

637
    hpx::future<std::uint32_t> runtime::get_num_localities() const
×
638
    {
639
        return make_ready_future(std::uint32_t(1));
×
640
    }
641

642
    std::string runtime::get_locality_name() const
×
643
    {
644
        return "console";
×
645
    }
×
646

647
    ///////////////////////////////////////////////////////////////////////////
648
    threads::policies::callback_notifier::on_startstop_type
649
    get_thread_on_start_func()
×
650
    {
651
        runtime* rt = get_runtime_ptr();
×
652
        if (nullptr != rt)
×
653
        {
654
            return rt->on_start_func();
×
655
        }
656
        else
657
        {
658
            return global_on_start_func;
×
659
        }
660
    }
×
661

662
    threads::policies::callback_notifier::on_startstop_type
663
    get_thread_on_stop_func()
×
664
    {
665
        runtime* rt = get_runtime_ptr();
×
666
        if (nullptr != rt)
×
667
        {
668
            return rt->on_stop_func();
×
669
        }
670
        else
671
        {
672
            return global_on_stop_func;
×
673
        }
674
    }
×
675

676
    threads::policies::callback_notifier::on_error_type
677
    get_thread_on_error_func()
×
678
    {
679
        runtime* rt = get_runtime_ptr();
×
680
        if (nullptr != rt)
×
681
        {
682
            return rt->on_error_func();
×
683
        }
684
        else
685
        {
686
            return global_on_error_func;
×
687
        }
688
    }
×
689

690
    threads::policies::callback_notifier::on_startstop_type
691
    register_thread_on_start_func(
1✔
692
        threads::policies::callback_notifier::on_startstop_type&& f)
693
    {
694
        runtime* rt = get_runtime_ptr();
1✔
695
        if (nullptr != rt)
1✔
696
        {
697
            return rt->on_start_func(HPX_MOVE(f));
×
698
        }
699

700
        threads::policies::callback_notifier::on_startstop_type newf =
701
            HPX_MOVE(f);
1✔
702
        std::swap(global_on_start_func, newf);
1✔
703
        return newf;
1✔
704
    }
1✔
705

706
    threads::policies::callback_notifier::on_startstop_type
707
    register_thread_on_stop_func(
1✔
708
        threads::policies::callback_notifier::on_startstop_type&& f)
709
    {
710
        runtime* rt = get_runtime_ptr();
1✔
711
        if (nullptr != rt)
1✔
712
        {
713
            return rt->on_stop_func(HPX_MOVE(f));
×
714
        }
715

716
        threads::policies::callback_notifier::on_startstop_type newf =
717
            HPX_MOVE(f);
1✔
718
        std::swap(global_on_stop_func, newf);
1✔
719
        return newf;
1✔
720
    }
1✔
721

722
    threads::policies::callback_notifier::on_error_type
723
    register_thread_on_error_func(
1✔
724
        threads::policies::callback_notifier::on_error_type&& f)
725
    {
726
        runtime* rt = get_runtime_ptr();
1✔
727
        if (nullptr != rt)
1✔
728
        {
729
            return rt->on_error_func(HPX_MOVE(f));
×
730
        }
731

732
        threads::policies::callback_notifier::on_error_type newf = HPX_MOVE(f);
1✔
733
        std::swap(global_on_error_func, newf);
1✔
734
        return newf;
1✔
735
    }
1✔
736

737
    ///////////////////////////////////////////////////////////////////////////
738
    runtime& get_runtime()
1,797,270✔
739
    {
740
        HPX_ASSERT(get_runtime_ptr() != nullptr);
1,797,270✔
741
        return *get_runtime_ptr();
1,797,267✔
742
    }
743

744
    runtime*& get_runtime_ptr()
100,627,583✔
745
    {
746
        static runtime* runtime_ = nullptr;
747
        return runtime_;
100,627,583✔
748
    }
749

750
    std::string get_thread_name()
5✔
751
    {
752
        std::string& thread_name = detail::thread_name();
5✔
753
        if (thread_name.empty())
5✔
754
            return "<unknown>";
×
755
        return thread_name;
5✔
756
    }
5✔
757

758
    // Register the current kernel thread with HPX, this should be done once
759
    // for each external OS-thread intended to invoke HPX functionality.
760
    // Calling this function more than once will silently fail
761
    // (will return false).
762
    bool register_thread(runtime* rt, char const* name, error_code& ec)
4✔
763
    {
764
        HPX_ASSERT(rt);
4✔
765
        return rt->register_thread(name, 0, true, ec);
4✔
766
    }
767

768
    // Unregister the thread from HPX, this should be done once in
769
    // the end before the external thread exists.
770
    void unregister_thread(runtime* rt)
4✔
771
    {
772
        HPX_ASSERT(rt);
4✔
773
        rt->unregister_thread();
4✔
774
    }
4✔
775

776
    // Access data for a given OS thread that was previously registered by
777
    // \a register_thread. This function must be called from a thread that was
778
    // previously registered with the runtime.
779
    runtime_local::os_thread_data get_os_thread_data(std::string const& label)
×
780
    {
781
        return get_runtime().get_os_thread_data(label);
×
782
    }
783

784
    /// Enumerate all OS threads that have registered with the runtime.
785
    bool enumerate_os_threads(
4✔
786
        hpx::function<bool(os_thread_data const&)> const& f)
787
    {
788
        return get_runtime().enumerate_os_threads(f);
4✔
789
    }
790

791
    ///////////////////////////////////////////////////////////////////////////
792
    void report_error(std::size_t num_thread, std::exception_ptr const& e)
×
793
    {
794
        // Early and late exceptions
795
        if (!threads::threadmanager_is(hpx::state::running))
×
796
        {
797
            hpx::runtime* rt = hpx::get_runtime_ptr();
×
798
            if (rt)
×
799
                rt->report_error(num_thread, e);
×
800
            else
801
                detail::report_exception_and_terminate(e);
×
802
            return;
×
803
        }
804

805
        get_runtime().get_thread_manager().report_error(num_thread, e);
×
806
    }
×
807

808
    void report_error(std::exception_ptr const& e)
×
809
    {
810
        // Early and late exceptions
811
        if (!threads::threadmanager_is(hpx::state::running))
×
812
        {
813
            hpx::runtime* rt = hpx::get_runtime_ptr();
×
814
            if (rt)
×
815
                rt->report_error(std::size_t(-1), e);
×
816
            else
817
                detail::report_exception_and_terminate(e);
×
818
            return;
×
819
        }
820

821
        std::size_t num_thread = hpx::get_worker_thread_num();
×
822
        get_runtime().get_thread_manager().report_error(num_thread, e);
×
823
    }
×
824

825
    bool register_on_exit(hpx::function<void()> const& f)
×
826
    {
827
        runtime* rt = get_runtime_ptr();
×
828
        if (nullptr == rt)
×
829
            return false;
×
830

831
        rt->on_exit(f);
×
832
        return true;
×
833
    }
×
834

835
    std::size_t get_runtime_instance_number()
×
836
    {
837
        runtime* rt = get_runtime_ptr();
×
838
        return (nullptr == rt) ? 0 : rt->get_instance_number();
×
839
    }
840

841
    ///////////////////////////////////////////////////////////////////////////
842
    std::string get_config_entry(
9,696✔
843
        std::string const& key, std::string const& dflt)
844
    {
845
        if (get_runtime_ptr() != nullptr)
9,696✔
846
        {
847
            return get_runtime().get_config().get_entry(key, dflt);
6,021✔
848
        }
849

850
        return dflt;
3,675✔
851
    }
9,696✔
852

853
    std::string get_config_entry(std::string const& key, std::size_t dflt)
23,787✔
854
    {
855
        if (get_runtime_ptr() != nullptr)
23,787✔
856
        {
857
            return get_runtime().get_config().get_entry(key, dflt);
21,337✔
858
        }
859

860
        return std::to_string(dflt);
2,450✔
861
    }
23,787✔
862

863
    // set entries
864
    void set_config_entry(std::string const& key, std::string const& value)
4✔
865
    {
866
        if (get_runtime_ptr() != nullptr)
4✔
867
        {
868
            get_runtime_ptr()->get_config().add_entry(key, value);
4✔
869
            return;
4✔
870
        }
871
    }
4✔
872

873
    void set_config_entry(std::string const& key, std::size_t value)
×
874
    {
875
        set_config_entry(key, std::to_string(value));
×
876
    }
×
877

878
    void set_config_entry_callback(std::string const& key,
574✔
879
        hpx::function<void(std::string const&, std::string const&)> const&
880
            callback)
881
    {
882
        if (get_runtime_ptr() != nullptr)
574✔
883
        {
884
            get_runtime_ptr()->get_config().add_notification_callback(
1,148✔
885
                key, callback);
574✔
886
            return;
574✔
887
        }
888
    }
574✔
889

890
    namespace util {
891

892
        ///////////////////////////////////////////////////////////////////////////
893
        // retrieve the command line arguments for the current locality
894
        bool retrieve_commandline_arguments(
1✔
895
            hpx::program_options::options_description const& app_options,
896
            hpx::program_options::variables_map& vm)
897
        {
898
            // The command line for this application instance is available from
899
            // this configuration section:
900
            //
901
            //     [hpx]
902
            //     cmd_line=....
903
            //
904
            std::string cmdline;
1✔
905

906
            hpx::util::section& cfg = hpx::get_runtime().get_config();
1✔
907
            if (cfg.has_entry("hpx.cmd_line"))
1✔
908
                cmdline = cfg.get_entry("hpx.cmd_line");
1✔
909

910
            return hpx::local::detail::parse_commandline(cfg, app_options,
2✔
911
                cmdline, vm, util::commandline_error_mode::allow_unregistered);
1✔
912
        }
1✔
913

914
        ///////////////////////////////////////////////////////////////////////////
915
        // retrieve the command line arguments for the current locality
916
        bool retrieve_commandline_arguments(
×
917
            std::string const& appname, hpx::program_options::variables_map& vm)
918
        {
919
            using hpx::program_options::options_description;
920

921
            options_description desc_commandline(
×
922
                "Usage: " + appname + " [options]");
×
923

924
            return retrieve_commandline_arguments(desc_commandline, vm);
×
925
        }
×
926
    }    // namespace util
927

928
    ///////////////////////////////////////////////////////////////////////////
929
    std::size_t get_os_thread_count()
1,453✔
930
    {
931
        runtime* rt = get_runtime_ptr();
1,453✔
932
        if (nullptr == rt)
1,453✔
933
        {
934
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
935
                "hpx::get_os_thread_count()",
936
                "the runtime system has not been initialized yet");
937
            return std::size_t(0);
938
        }
939
        return rt->get_config().get_os_thread_count();
1,453✔
940
    }
×
941

942
    bool is_scheduler_numa_sensitive()
×
943
    {
944
        runtime* rt = get_runtime_ptr();
×
945
        if (nullptr == rt)
×
946
        {
947
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
948
                "hpx::is_scheduler_numa_sensitive",
949
                "the runtime system has not been initialized yet");
950
            return false;
951
        }
952

953
        if (std::size_t(-1) != get_worker_thread_num())
×
954
            return false;
×
955
        return false;
×
956
    }
×
957

958
    ///////////////////////////////////////////////////////////////////////////
959
    bool is_running()
1,098✔
960
    {
961
        runtime* rt = get_runtime_ptr();
1,098✔
962
        if (nullptr != rt)
1,098✔
963
            return rt->get_state() == hpx::state::running;
1,098✔
964
        return false;
×
965
    }
1,098✔
966

967
    bool is_stopped()
2,749✔
968
    {
969
        if (!detail::exit_called)
2,749✔
970
        {
971
            runtime* rt = get_runtime_ptr();
2,749✔
972
            if (nullptr != rt)
2,749✔
973
                return rt->get_state() == hpx::state::stopped;
2,749✔
974
        }
×
975
        return true;    // assume stopped
×
976
    }
2,749✔
977

978
    bool is_stopped_or_shutting_down()
474,546✔
979
    {
980
        runtime* rt = get_runtime_ptr();
474,546✔
981
        if (!detail::exit_called && nullptr != rt)
474,546✔
982
        {
983
            state st = rt->get_state();
474,546✔
984
            return st >= hpx::state::shutdown;
474,546✔
985
        }
986
        return true;    // assume stopped
×
987
    }
474,546✔
988

989
    bool tolerate_node_faults()
×
990
    {
991
#ifdef HPX_HAVE_FAULT_TOLERANCE
992
        return true;
993
#else
994
        return false;
×
995
#endif
996
    }
997

998
    bool is_starting()
183,419✔
999
    {
1000
        runtime* rt = get_runtime_ptr();
183,419✔
1001
        return nullptr != rt ? rt->get_state() <= hpx::state::startup : true;
183,419✔
1002
    }
1003

1004
    bool is_pre_startup()
×
1005
    {
1006
        runtime* rt = get_runtime_ptr();
×
1007
        return nullptr != rt ? rt->get_state() < hpx::state::startup : true;
×
1008
    }
1009
}    // namespace hpx
1010

1011
///////////////////////////////////////////////////////////////////////////////
1012
namespace hpx::util {
1013

1014
    std::string expand(std::string const& in)
×
1015
    {
1016
        return get_runtime().get_config().expand(in);
×
1017
    }
1018

1019
    void expand(std::string& in)
1✔
1020
    {
1021
        get_runtime().get_config().expand(in, std::string::size_type(-1));
1✔
1022
    }
1✔
1023
}    // namespace hpx::util
1024

1025
///////////////////////////////////////////////////////////////////////////////
1026
namespace hpx::threads {
1027

1028
    threadmanager& get_thread_manager()
50,609✔
1029
    {
1030
        return get_runtime().get_thread_manager();
50,609✔
1031
    }
1032

1033
    // shortcut for runtime_configuration::get_default_stack_size
1034
    std::ptrdiff_t get_default_stack_size()
×
1035
    {
1036
        return get_runtime().get_config().get_default_stack_size();
×
1037
    }
1038

1039
    // shortcut for runtime_configuration::get_stack_size
1040
    std::ptrdiff_t get_stack_size(threads::thread_stacksize stacksize)
1,595,169✔
1041
    {
1042
        if (stacksize == threads::thread_stacksize::current)
1,595,170✔
1043
            return threads::get_self_stacksize();
×
1044

1045
        return get_runtime().get_config().get_stack_size(stacksize);
1,595,156✔
1046
    }
1,595,156✔
1047

1048
    void reset_thread_distribution()
×
1049
    {
1050
        get_runtime().get_thread_manager().reset_thread_distribution();
×
1051
    }
×
1052

1053
    void set_scheduler_mode(threads::policies::scheduler_mode m)
×
1054
    {
1055
        get_runtime().get_thread_manager().set_scheduler_mode(m);
×
1056
    }
×
1057

1058
    void add_scheduler_mode(threads::policies::scheduler_mode m)
×
1059
    {
1060
        get_runtime().get_thread_manager().add_scheduler_mode(m);
×
1061
    }
×
1062

1063
    void add_remove_scheduler_mode(
×
1064
        threads::policies::scheduler_mode to_add_mode,
1065
        threads::policies::scheduler_mode to_remove_mode)
1066
    {
1067
        get_runtime().get_thread_manager().add_remove_scheduler_mode(
×
1068
            to_add_mode, to_remove_mode);
×
1069
    }
×
1070

1071
    void remove_scheduler_mode(threads::policies::scheduler_mode m)
×
1072
    {
1073
        get_runtime().get_thread_manager().remove_scheduler_mode(m);
×
1074
    }
×
1075

1076
    topology const& get_topology()
2✔
1077
    {
1078
        hpx::runtime* rt = hpx::get_runtime_ptr();
2✔
1079
        if (rt == nullptr)
2✔
1080
        {
1081
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1082
                "hpx::threads::get_topology",
1083
                "the hpx runtime system has not been initialized yet");
1084
        }
1085
        return rt->get_topology();
2✔
1086
    }
×
1087
}    // namespace hpx::threads
1088

1089
///////////////////////////////////////////////////////////////////////////////
1090
namespace hpx {
1091
    std::uint64_t get_system_uptime()
90✔
1092
    {
1093
        return runtime::get_system_uptime();
90✔
1094
    }
1095

1096
    hpx::util::runtime_configuration const& get_config()
16,906✔
1097
    {
1098
        return get_runtime().get_config();
16,906✔
1099
    }
1100

1101
    hpx::util::io_service_pool* get_thread_pool(
19,289✔
1102
        char const* name, char const* name_suffix)
1103
    {
1104
        std::string full_name(name);
19,289✔
1105
        full_name += name_suffix;
19,289✔
1106
        return get_runtime().get_thread_pool(full_name.c_str());
19,289✔
1107
    }
19,289✔
1108

1109
    ///////////////////////////////////////////////////////////////////////////
1110
    /// Return true if networking is enabled.
1111
    bool is_networking_enabled()
2,250✔
1112
    {
1113
        runtime* rt = get_runtime_ptr();
2,250✔
1114
        if (nullptr != rt)
2,250✔
1115
        {
1116
            return rt->is_networking_enabled();
1,192✔
1117
        }
1118
        return true;    // be on the safe side, enable networking
1,058✔
1119
    }
2,250✔
1120
}    // namespace hpx
1121

1122
#if defined(_WIN64) && defined(HPX_DEBUG) &&                                   \
1123
    !defined(HPX_HAVE_FIBER_BASED_COROUTINES)
1124
#include <io.h>
1125
#endif
1126

1127
namespace hpx {
1128
    namespace detail {
1129
        ///////////////////////////////////////////////////////////////////////
1130
        // There is no need to protect these global from thread concurrent
1131
        // access as they are access during early startup only.
1132
        std::list<startup_function_type>& global_pre_startup_functions()
2,444✔
1133
        {
1134
            static std::list<startup_function_type>
2,444✔
1135
                global_pre_startup_functions_;
1,056✔
1136
            return global_pre_startup_functions_;
2,444✔
1137
        }
1138

1139
        std::list<startup_function_type>& global_startup_functions()
3,035✔
1140
        {
1141
            static std::list<startup_function_type> global_startup_functions_;
3,035✔
1142
            return global_startup_functions_;
3,035✔
1143
        }
1144

1145
        std::list<shutdown_function_type>& global_pre_shutdown_functions()
2,444✔
1146
        {
1147
            static std::list<shutdown_function_type>
2,444✔
1148
                global_pre_shutdown_functions_;
1,056✔
1149
            return global_pre_shutdown_functions_;
2,444✔
1150
        }
1151

1152
        std::list<shutdown_function_type>& global_shutdown_functions()
2,444✔
1153
        {
1154
            static std::list<shutdown_function_type> global_shutdown_functions_;
2,444✔
1155
            return global_shutdown_functions_;
2,444✔
1156
        }
1157
    }    // namespace detail
1158

1159
    ///////////////////////////////////////////////////////////////////////////
1160
    void register_pre_startup_function(startup_function_type f)
×
1161
    {
1162
        runtime* rt = get_runtime_ptr();
×
1163
        if (nullptr != rt)
×
1164
        {
1165
            if (rt->get_state() > hpx::state::pre_startup)
×
1166
            {
1167
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1168
                    "register_pre_startup_function",
1169
                    "Too late to register a new pre-startup function.");
1170
                return;
1171
            }
1172
            rt->add_pre_startup_function(HPX_MOVE(f));
×
1173
        }
×
1174
        else
1175
        {
1176
            detail::global_pre_startup_functions().push_back(HPX_MOVE(f));
×
1177
        }
1178
    }
×
1179

1180
    void register_startup_function(startup_function_type f)
591✔
1181
    {
1182
        runtime* rt = get_runtime_ptr();
591✔
1183
        if (nullptr != rt)
591✔
1184
        {
1185
            if (rt->get_state() > hpx::state::startup)
×
1186
            {
1187
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1188
                    "register_startup_function",
1189
                    "Too late to register a new startup function.");
1190
                return;
1191
            }
1192
            rt->add_startup_function(HPX_MOVE(f));
×
1193
        }
×
1194
        else
1195
        {
1196
            detail::global_startup_functions().push_back(HPX_MOVE(f));
591✔
1197
        }
1198
    }
591✔
1199

1200
    void register_pre_shutdown_function(shutdown_function_type f)
599✔
1201
    {
1202
        runtime* rt = get_runtime_ptr();
599✔
1203
        if (nullptr != rt)
599✔
1204
        {
1205
            if (rt->get_state() > hpx::state::pre_shutdown)
599✔
1206
            {
1207
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1208
                    "register_pre_shutdown_function",
1209
                    "Too late to register a new pre-shutdown function.");
1210
                return;
1211
            }
1212
            rt->add_pre_shutdown_function(HPX_MOVE(f));
599✔
1213
        }
599✔
1214
        else
1215
        {
1216
            detail::global_pre_shutdown_functions().push_back(HPX_MOVE(f));
×
1217
        }
1218
    }
599✔
1219

1220
    void register_shutdown_function(shutdown_function_type f)
598✔
1221
    {
1222
        runtime* rt = get_runtime_ptr();
598✔
1223
        if (nullptr != rt)
598✔
1224
        {
1225
            if (rt->get_state() > hpx::state::shutdown)
598✔
1226
            {
1227
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1228
                    "register_shutdown_function",
1229
                    "Too late to register a new shutdown function.");
1230
                return;
1231
            }
1232
            rt->add_shutdown_function(HPX_MOVE(f));
598✔
1233
        }
598✔
1234
        else
1235
        {
1236
            detail::global_shutdown_functions().push_back(HPX_MOVE(f));
×
1237
        }
1238
    }
598✔
1239

1240
    void runtime::call_startup_functions(bool pre_startup)
1,252✔
1241
    {
1242
        if (pre_startup)
1,252✔
1243
        {
1244
            set_state(hpx::state::pre_startup);
626✔
1245
            for (startup_function_type& f : pre_startup_functions_)
626✔
1246
            {
1247
                f();
×
1248
            }
1249
        }
626✔
1250
        else
1251
        {
1252
            set_state(hpx::state::startup);
626✔
1253
            for (startup_function_type& f : startup_functions_)
630✔
1254
            {
1255
                f();
4✔
1256
            }
1257
        }
1258
    }
1,252✔
1259

1260
    namespace detail {
1261
        void handle_print_bind(std::size_t num_threads)
×
1262
        {
1263
            threads::topology& top = threads::create_topology();
×
1264
            auto const& rp = hpx::resource::get_partitioner();
×
1265
            auto const& tm = get_runtime().get_thread_manager();
×
1266

1267
            {
1268
                // make sure all output is kept together
1269
                std::ostringstream strm;
×
1270

1271
                strm << std::string(79, '*') << '\n';
×
1272
                strm << "locality: " << hpx::get_locality_id() << '\n';
×
1273
                for (std::size_t i = 0; i != num_threads; ++i)
×
1274
                {
1275
                    // print the mask for the current PU
1276
                    threads::mask_cref_type pu_mask = rp.get_pu_mask(i);
×
1277

1278
                    if (!threads::any(pu_mask))
×
1279
                    {
1280
                        strm << std::setw(4) << i    //-V112
×
1281
                             << ": thread binding disabled" << std::endl;
×
1282
                    }
×
1283
                    else
1284
                    {
1285
                        std::string pool_name = tm.get_pool(i).get_pool_name();
×
1286
                        top.print_affinity_mask(strm, i, pu_mask, pool_name);
×
1287
                    }
×
1288

1289
                    // Make sure the mask does not contradict the CPU bindings
1290
                    // returned by the system (see #973: Would like option to
1291
                    // report HWLOC bindings).
1292
                    error_code ec(throwmode::lightweight);
×
1293
                    std::thread& blob = tm.get_os_thread_handle(i);
×
1294
                    threads::mask_type boundcpu =
1295
                        top.get_cpubind_mask(blob, ec);
×
1296

1297
                    // The masks reported by HPX must be the same as the ones
1298
                    // reported from HWLOC.
1299
                    if (!ec && threads::any(boundcpu) &&
×
1300
                        !threads::equal(boundcpu, pu_mask, num_threads))
×
1301
                    {
1302
                        std::string boundcpu_str = threads::to_string(boundcpu);
×
1303
                        std::string pu_mask_str = threads::to_string(pu_mask);
×
1304
                        HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1305
                            "handle_print_bind",
1306
                            hpx::util::format(
1307
                                "unexpected mismatch between locality {1}: "
1308
                                "binding reported from HWLOC({2}) and HPX({3}) "
1309
                                "on thread {4}",
1310
                                hpx::get_locality_id(), boundcpu_str,
1311
                                pu_mask_str, i));
1312
                    }
×
1313
                }
×
1314

1315
                std::cout << strm.str();
×
1316
            }
×
1317
        }
×
1318
    }    // namespace detail
1319

1320
    threads::thread_result_type runtime::run_helper(
1,222✔
1321
        hpx::function<runtime::hpx_main_function_type> const& func, int& result,
1322
        bool call_startup, void (*handle_print_bind)(std::size_t))
1323
    {
1324
        bool caught_exception = false;
1,222✔
1325
        try
1326
        {
1327
            // no need to do late command line handling if this is called from
1328
            // the distributed runtime
1329
            if (handle_print_bind != nullptr)
1,222✔
1330
            {
1331
                hpx::program_options::options_description options;
627✔
1332
                result = hpx::local::detail::handle_late_commandline_options(
627✔
1333
                    get_config(), options, handle_print_bind);
627✔
1334
                if (result)
627✔
1335
                {
1336
                    lbt_ << "runtime_local::run_helper: bootstrap "
1✔
1337
                            "aborted, bailing out";
1338

1339
                    set_state(hpx::state::running);
1✔
1340
                    finalize(-1.0);
1✔
1341

1342
                    return threads::thread_result_type(
1✔
1343
                        threads::thread_schedule_state::terminated,
1✔
1344
                        threads::invalid_thread_id);
1345
                }
1346
            }
627✔
1347

1348
            if (call_startup)
1,221✔
1349
            {
1350
                call_startup_functions(true);
626✔
1351
                lbt_ << "(3rd stage) run_helper: ran pre-startup functions";
626✔
1352

1353
                call_startup_functions(false);
626✔
1354
                lbt_ << "(4th stage) run_helper: ran startup functions";
626✔
1355
            }
626✔
1356

1357
            lbt_ << "(4th stage) runtime::run_helper: bootstrap complete";
1,221✔
1358
            set_state(hpx::state::running);
1,221✔
1359

1360
            // Now, execute the user supplied thread function (hpx_main)
1361
            if (!!func)
1,221✔
1362
            {
1363
                lbt_ << "(last stage) runtime::run_helper: about to "
1,087✔
1364
                        "invoke hpx_main";
1365

1366
                // Change our thread description, as we're about to call hpx_main
1367
                threads::set_thread_description(
1,087✔
1368
                    threads::get_self_id(), "hpx_main");
1,087✔
1369

1370
                // Call hpx_main
1371
                result = func();
1,087✔
1372
            }
1,078✔
1373
        }
1,219✔
1374
        catch (...)
1375
        {
1376
            // make sure exceptions thrown in hpx_main don't escape
1377
            // unnoticed
1378
            {
1379
                std::lock_guard<std::mutex> l(mtx_);
7✔
1380
                exception_ = std::current_exception();
7✔
1381
            }
7✔
1382
            result = -1;
7✔
1383
            caught_exception = true;
7✔
1384
        }
7✔
1385

1386
        if (caught_exception)
1,219✔
1387
        {
1388
            HPX_ASSERT(exception_);
7✔
1389
            report_error(exception_, false);
7✔
1390
            finalize(-1.0);    // make sure the application exits
7✔
1391
        }
7✔
1392

1393
        return threads::thread_result_type(
1,219✔
1394
            threads::thread_schedule_state::terminated,
1,219✔
1395
            threads::invalid_thread_id);
1396
    }
1,227✔
1397

1398
    int runtime::start(
627✔
1399
        hpx::function<hpx_main_function_type> const& func, bool blocking)
1400
    {
1401
#if defined(_WIN64) && defined(HPX_DEBUG) &&                                   \
1402
    !defined(HPX_HAVE_FIBER_BASED_COROUTINES)
1403
        // needs to be called to avoid problems at system startup
1404
        // see: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100319
1405
        _isatty(0);
1406
#endif
1407
        // {{{ early startup code - local
1408

1409
        // initialize instrumentation system
1410
#ifdef HPX_HAVE_APEX
1411
        util::external_timer::init(nullptr, 0, 1);
1412
#endif
1413

1414
        LRT_(info).format("cmd_line: {}", get_config().get_cmd_line());
627✔
1415

1416
        lbt_ << "(1st stage) runtime::start: booting locality " << here();
627✔
1417

1418
        // Register this thread with the runtime system to allow calling
1419
        // certain HPX functionality from the main thread. Also calls
1420
        // registered startup callbacks.
1421
        init_tss_helper("main-thread",
627✔
1422
            runtime_local::os_thread_type::main_thread, 0, 0, "", "", false);
1423

1424
#ifdef HPX_HAVE_IO_POOL
1425
        // start the io pool
1426
        io_pool_.run(false);
627✔
1427
        lbt_ << "(1st stage) runtime::start: started the application "
627✔
1428
                "I/O service pool";
1429
#endif
1430
        // start the thread manager
1431
        thread_manager_->run();
627✔
1432
        lbt_ << "(1st stage) runtime::start: started threadmanager";
627✔
1433
        // }}}
1434

1435
        // {{{ launch main
1436
        // register the given main function with the thread manager
1437
        lbt_ << "(1st stage) runtime::start: launching run_helper "
627✔
1438
                "HPX thread";
1439

1440
        threads::thread_init_data data(
627✔
1441
            hpx::bind(&runtime::run_helper, this, func, std::ref(result_), true,
1,254✔
1442
                &detail::handle_print_bind),
627✔
1443
            "run_helper", threads::thread_priority::normal,
627✔
1444
            threads::thread_schedule_hint(0), threads::thread_stacksize::large);
627✔
1445

1446
        this->runtime::starting();
627✔
1447
        threads::thread_id_ref_type id = threads::invalid_thread_id;
627✔
1448
        thread_manager_->register_thread(data, id);
627✔
1449
        // }}}
1450

1451
        // block if required
1452
        if (blocking)
627✔
1453
        {
1454
            return wait();    // wait for the shutdown_action to be executed
×
1455
        }
1456
        else
1457
        {
1458
            // wait for at least hpx::state::running
1459
            util::yield_while(
627✔
1460
                [this]() { return get_state() < hpx::state::running; },
73,438✔
1461
                "runtime::start");
1462
        }
1463

1464
        return 0;    // return zero as we don't know the outcome of hpx_main yet
627✔
1465
    }
627✔
1466

1467
    int runtime::start(bool blocking)
16✔
1468
    {
1469
        hpx::function<hpx_main_function_type> empty_main;
16✔
1470
        return start(empty_main, blocking);
16✔
1471
    }
16✔
1472

1473
    ///////////////////////////////////////////////////////////////////////////
1474
    void runtime::notify_finalize()
625✔
1475
    {
1476
        std::unique_lock<std::mutex> l(mtx_);
625✔
1477
        if (!stop_called_)
625✔
1478
        {
1479
            stop_called_ = true;
625✔
1480
            stop_done_ = true;
625✔
1481
            wait_condition_.notify_all();
625✔
1482
        }
625✔
1483
    }
625✔
1484

1485
    void runtime::wait_finalize()
627✔
1486
    {
1487
        std::unique_lock<std::mutex> l(mtx_);
627✔
1488
        while (!stop_done_)
1,194✔
1489
        {
1490
            LRT_(info).format("runtime: about to enter wait state");
569✔
1491
            wait_condition_.wait(l);    //-V1089
567✔
1492
            LRT_(info).format("runtime: exiting wait state");
569✔
1493
        }
1494
    }
625✔
1495

1496
    void runtime::wait_helper(
627✔
1497
        std::mutex& mtx, std::condition_variable& cond, bool& running)
1498
    {
1499
        // signal successful initialization
1500
        {
1501
            std::lock_guard<std::mutex> lk(mtx);
627✔
1502
            running = true;
627✔
1503
            cond.notify_all();
627✔
1504
        }
627✔
1505

1506
        // register this thread with any possibly active Intel tool
1507
        std::string thread_name("main-thread#wait_helper");
627✔
1508
        HPX_ITT_THREAD_SET_NAME(thread_name.c_str());
625✔
1509

1510
        // set thread name as shown in Visual Studio
1511
        util::set_thread_name(thread_name.c_str());
625✔
1512

1513
#if defined(HPX_HAVE_APEX)
1514
        // not registering helper threads - for now
1515
        //util::external_timer::register_thread(thread_name.c_str());
1516
#endif
1517

1518
        wait_finalize();
625✔
1519

1520
        // stop main thread pool
1521
        main_pool_.stop();
625✔
1522
    }
625✔
1523

1524
    int runtime::wait()
627✔
1525
    {
1526
        LRT_(info).format("runtime_local: about to enter wait state");
627✔
1527

1528
        // start the wait_helper in a separate thread
1529
        std::mutex mtx;
627✔
1530
        std::condition_variable cond;
627✔
1531
        bool running = false;
627✔
1532

1533
        std::thread t(hpx::bind(&runtime::wait_helper, this, std::ref(mtx),
1,254✔
1534
            std::ref(cond), std::ref(running)));
627✔
1535

1536
        // wait for the thread to run
1537
        {
1538
            std::unique_lock<std::mutex> lk(mtx);
627✔
1539
            // NOLINTNEXTLINE(bugprone-infinite-loop)
1540
            while (!running)      //-V776 //-V1044
1,254✔
1541
                cond.wait(lk);    //-V1089
627✔
1542
        }
625✔
1543

1544
        // use main thread to drive main thread pool
1545
        main_pool_.thread_run(0);
625✔
1546

1547
        // block main thread
1548
        t.join();
625✔
1549

1550
        thread_manager_->wait();
625✔
1551

1552
        LRT_(info).format("runtime_local: exiting wait state");
625✔
1553
        return result_;
625✔
1554
    }
625✔
1555

1556
    ///////////////////////////////////////////////////////////////////////////
1557
    // First half of termination process: stop thread manager,
1558
    // schedule a task managed by timer_pool to initiate second part
1559
    void runtime::stop(bool blocking)
625✔
1560
    {
1561
        LRT_(warning).format("runtime_local: about to stop services");
625✔
1562

1563
        // execute all on_exit functions whenever the first thread calls this
1564
        this->runtime::stopping();
625✔
1565

1566
        // stop runtime_local services (threads)
1567
        thread_manager_->stop(false);    // just initiate shutdown
625✔
1568

1569
#ifdef HPX_HAVE_APEX
1570
        util::external_timer::finalize();
1571
#endif
1572

1573
        if (threads::get_self_ptr())
625✔
1574
        {
1575
            // schedule task on separate thread to execute stop_helper() below
1576
            // this is necessary as this function (stop()) might have been called
1577
            // from a HPX thread, so it would deadlock by waiting for the thread
1578
            // manager
1579
            std::mutex mtx;
×
1580
            std::condition_variable cond;
×
1581
            std::unique_lock<std::mutex> l(mtx);
×
1582

1583
            std::thread t(hpx::bind(&runtime::stop_helper, this, blocking,
×
1584
                std::ref(cond), std::ref(mtx)));
×
1585
            cond.wait(l);    //-V1089
×
1586

1587
            t.join();
×
1588
        }
×
1589
        else
1590
        {
1591
            thread_manager_->stop(blocking);    // wait for thread manager
625✔
1592

1593
            deinit_global_data();
625✔
1594

1595
            // this disables all logging from the main thread
1596
            deinit_tss_helper("main-thread", 0);
625✔
1597

1598
            LRT_(info).format("runtime_local: stopped all services");
625✔
1599
        }
1600

1601
#ifdef HPX_HAVE_TIMER_POOL
1602
        LTM_(info).format("stop: stopping timer pool");
625✔
1603
        timer_pool_.stop();
625✔
1604
        if (blocking)
625✔
1605
        {
1606
            timer_pool_.join();
625✔
1607
            timer_pool_.clear();
625✔
1608
        }
625✔
1609
#endif
1610
#ifdef HPX_HAVE_IO_POOL
1611
        LTM_(info).format("stop: stopping io pool");
625✔
1612
        io_pool_.stop();
625✔
1613
        if (blocking)
625✔
1614
        {
1615
            io_pool_.join();
625✔
1616
            io_pool_.clear();
625✔
1617
        }
625✔
1618
#endif
1619
    }
625✔
1620

1621
    // Second step in termination: shut down all services.
1622
    // This gets executed as a task in the timer_pool io_service and not as
1623
    // a HPX thread!
1624
    void runtime::stop_helper(
×
1625
        bool blocking, std::condition_variable& cond, std::mutex& mtx)
1626
    {
1627
        // wait for thread manager to exit
1628
        thread_manager_->stop(blocking);    // wait for thread manager
×
1629

1630
        deinit_global_data();
×
1631

1632
        // this disables all logging from the main thread
1633
        deinit_tss_helper("main-thread", 0);
×
1634

1635
        LRT_(info).format("runtime_local: stopped all services");
×
1636

1637
        std::lock_guard<std::mutex> l(mtx);
×
1638
        cond.notify_all();    // we're done now
×
1639
    }
×
1640

1641
    int runtime::suspend()
118✔
1642
    {
1643
        LRT_(info).format("runtime_local: about to suspend runtime");
118✔
1644

1645
        if (state_.load() == hpx::state::sleeping)
118✔
1646
        {
1647
            return 0;
×
1648
        }
1649

1650
        if (state_.load() != hpx::state::running)
118✔
1651
        {
1652
            HPX_THROW_EXCEPTION(hpx::error::invalid_status, "runtime::suspend",
×
1653
                "Can only suspend runtime from running state");
1654
            return -1;
1655
        }
1656

1657
        thread_manager_->suspend();
118✔
1658

1659
#ifdef HPX_HAVE_TIMER_POOL
1660
        timer_pool_.wait();
118✔
1661
#endif
1662
#ifdef HPX_HAVE_IO_POOL
1663
        io_pool_.wait();
118✔
1664
#endif
1665

1666
        set_state(hpx::state::sleeping);
118✔
1667

1668
        return 0;
118✔
1669
    }
118✔
1670

1671
    int runtime::resume()
118✔
1672
    {
1673
        LRT_(info).format("runtime_local: about to resume runtime");
118✔
1674

1675
        if (state_.load() == hpx::state::running)
118✔
1676
        {
1677
            return 0;
×
1678
        }
1679

1680
        if (state_.load() != hpx::state::sleeping)
118✔
1681
        {
1682
            HPX_THROW_EXCEPTION(hpx::error::invalid_status, "runtime::resume",
×
1683
                "Can only resume runtime from suspended state");
1684
            return -1;
1685
        }
1686

1687
        thread_manager_->resume();
118✔
1688

1689
        set_state(hpx::state::running);
118✔
1690

1691
        return 0;
118✔
1692
    }
118✔
1693

1694
    int runtime::finalize(double /*shutdown_timeout*/)
625✔
1695
    {
1696
        notify_finalize();
625✔
1697
        return 0;
625✔
1698
    }
1699

1700
    bool runtime::is_networking_enabled()
×
1701
    {
1702
        return false;
×
1703
    }
1704

1705
    hpx::threads::threadmanager& runtime::get_thread_manager()
371,290✔
1706
    {
1707
        return *thread_manager_;
371,290✔
1708
    }
1709

1710
    std::string runtime::here() const
1,576✔
1711
    {
1712
        return "127.0.0.1";
1,576✔
1713
    }
×
1714

1715
    ///////////////////////////////////////////////////////////////////////////
1716
    bool runtime::report_error(std::size_t num_thread,
5✔
1717
        std::exception_ptr const& e, bool /*terminate_all*/)
1718
    {
1719
        // call thread-specific user-supplied on_error handler
1720
        bool report_exception = true;
5✔
1721
        if (on_error_func_)
5✔
1722
        {
1723
            report_exception = on_error_func_(num_thread, e);
1✔
1724
        }
1✔
1725

1726
        // Early and late exceptions, errors outside of HPX-threads
1727
        if (!threads::get_self_ptr() ||
5✔
1728
            !threads::threadmanager_is(hpx::state::running))
5✔
1729
        {
1730
            // report the error to the local console
1731
            if (report_exception)
×
1732
            {
1733
                detail::report_exception_and_continue(e);
×
1734
            }
×
1735

1736
            // store the exception to be able to rethrow it later
1737
            {
1738
                std::lock_guard<std::mutex> l(mtx_);
×
1739
                exception_ = e;
×
1740
            }
×
1741

1742
            notify_finalize();
×
1743
            stop(false);
×
1744

1745
            return report_exception;
×
1746
        }
1747

1748
        return report_exception;
5✔
1749
    }
5✔
1750

1751
    bool runtime::report_error(std::exception_ptr const& e, bool terminate_all)
5✔
1752
    {
1753
        return report_error(hpx::get_worker_thread_num(), e, terminate_all);
5✔
1754
    }
1755

1756
    void runtime::rethrow_exception()
1,220✔
1757
    {
1758
        if (state_.load() > hpx::state::running)
1,220✔
1759
        {
1760
            std::lock_guard<std::mutex> l(mtx_);
1,220✔
1761
            if (exception_)
1,220✔
1762
            {
1763
                std::exception_ptr e = exception_;
6✔
1764
                exception_ = std::exception_ptr();
6✔
1765
                std::rethrow_exception(e);
7✔
1766
            }
6✔
1767
        }
1,219✔
1768
    }
1,219✔
1769

1770
    ///////////////////////////////////////////////////////////////////////////
1771
    int runtime::run(hpx::function<hpx_main_function_type> const& func)
610✔
1772
    {
1773
        // start the main thread function
1774
        start(func);
610✔
1775

1776
        // now wait for everything to finish
1777
        wait();
610✔
1778
        stop();
610✔
1779

1780
        rethrow_exception();
610✔
1781
        return result_;
610✔
1782
    }
1783

1784
    ///////////////////////////////////////////////////////////////////////////
1785
    int runtime::run()
×
1786
    {
1787
        // start the main thread function
1788
        start();
×
1789

1790
        // now wait for everything to finish
1791
        int result = wait();
×
1792
        stop();
×
1793

1794
        rethrow_exception();
×
1795
        return result;
×
1796
    }
1797

1798
    util::thread_mapper& runtime::get_thread_mapper()
×
1799
    {
1800
        return *thread_support_;
×
1801
    }
1802

1803
    ///////////////////////////////////////////////////////////////////////////
1804
    threads::policies::callback_notifier runtime::get_notification_policy(
1,881✔
1805
        char const* prefix, runtime_local::os_thread_type type)
1806
    {
1807
        typedef bool (runtime::*report_error_t)(
1808
            std::size_t, std::exception_ptr const&, bool);
1809

1810
        using placeholders::_1;
1811
        using placeholders::_2;
1812
        using placeholders::_3;
1813
        using placeholders::_4;
1814

1815
        notification_policy_type notifier;
1,881✔
1816

1817
        notifier.add_on_start_thread_callback(
1,881✔
1818
            hpx::bind(&runtime::init_tss_helper, this, prefix, type, _1, _2, _3,
3,762✔
1819
                _4, false));
1,881✔
1820
        notifier.add_on_stop_thread_callback(
1,881✔
1821
            hpx::bind(&runtime::deinit_tss_helper, this, prefix, _1));
1,881✔
1822
        notifier.set_on_error_callback(
1,881✔
1823
            hpx::bind(static_cast<report_error_t>(&runtime::report_error), this,
3,762✔
1824
                _1, _2, true));
1,881✔
1825

1826
        return notifier;
1,881✔
1827
    }
1,881✔
1828

1829
    void runtime::init_tss_helper(char const* context,
5,817✔
1830
        runtime_local::os_thread_type type, std::size_t local_thread_num,
1831
        std::size_t global_thread_num, char const* pool_name,
1832
        char const* postfix, bool service_thread)
1833
    {
1834
        error_code ec(throwmode::lightweight);
5,845✔
1835
        return init_tss_ex(context, type, local_thread_num, global_thread_num,
11,634✔
1836
            pool_name, postfix, service_thread, ec);
5,845✔
1837
    }
5,845✔
1838

1839
    void runtime::init_tss_ex(char const* context,
5,828✔
1840
        runtime_local::os_thread_type type, std::size_t local_thread_num,
1841
        std::size_t global_thread_num, char const* pool_name,
1842
        char const* postfix, bool service_thread, error_code& ec)
1843
    {
1844
        // set the thread's name, if it's not already set
1845
        HPX_ASSERT(detail::thread_name().empty());
5,828✔
1846

1847
        std::string fullname;
5,844✔
1848
        fullname += context;
5,844✔
1849
        if (postfix && *postfix)
5,844✔
1850
            fullname += postfix;
×
1851
        fullname += "#" + std::to_string(global_thread_num);
5,842✔
1852
        detail::thread_name() = HPX_MOVE(fullname);
5,821✔
1853

1854
        char const* name = detail::thread_name().c_str();
5,820✔
1855

1856
        // initialize thread mapping for external libraries (i.e. PAPI)
1857
        thread_support_->register_thread(name, type);
5,846✔
1858

1859
        // register this thread with any possibly active Intel tool
1860
        HPX_ITT_THREAD_SET_NAME(name);
5,846✔
1861

1862
        // set thread name as shown in Visual Studio
1863
        util::set_thread_name(name);
5,846✔
1864

1865
#if defined(HPX_HAVE_APEX)
1866
        if (std::strstr(name, "worker") != nullptr)
1867
            util::external_timer::register_thread(name);
1868
#endif
1869

1870
        // call thread-specific user-supplied on_start handler
1871
        if (on_start_func_)
5,846✔
1872
        {
1873
            on_start_func_(
×
1874
                local_thread_num, global_thread_num, pool_name, context);
×
1875
        }
×
1876

1877
        // if this is a service thread, set its service affinity
1878
        if (service_thread)
5,846✔
1879
        {
1880
            // FIXME: We don't set the affinity of the service threads on BG/Q,
1881
            // as this is causing a hang (needs to be investigated)
1882
#if !defined(__bgq__)
1883
            threads::mask_cref_type used_processing_units =
1✔
1884
                thread_manager_->get_used_processing_units();
1✔
1885

1886
            // --hpx:bind=none  should disable all affinity definitions
1887
            if (threads::any(used_processing_units))
1✔
1888
            {
1889
                this->topology_.set_thread_affinity_mask(
1✔
1890
                    this->topology_.get_service_affinity_mask(
2✔
1891
                        used_processing_units),
1✔
1892
                    ec);
1✔
1893

1894
                // comment this out for now as on CircleCI this is causing
1895
                // unending grief
1896
                //if (ec)
1897
                //{
1898
                //    HPX_THROW_EXCEPTION(hpx::error::kernel_error,
1899
                //        "runtime::init_tss_ex",
1900
                //        "failed to set thread affinity mask ({}) for service "
1901
                //        "thread: {}",
1902
                //        hpx::threads::to_string(used_processing_units),
1903
                //        detail::thread_name());
1904
                //}
1905
            }
1✔
1906
#endif
1907
        }
1✔
1908
    }
5,846✔
1909

1910
    void runtime::deinit_tss_helper(
5,789✔
1911
        char const* context, std::size_t global_thread_num)
1912
    {
1913
        threads::reset_continuation_recursion_count();
5,708✔
1914

1915
        // call thread-specific user-supplied on_stop handler
1916
        if (on_stop_func_)
5,708✔
1917
        {
1918
            on_stop_func_(global_thread_num, global_thread_num, "", context);
×
1919
        }
×
1920

1921
        // reset PAPI support
1922
        thread_support_->unregister_thread();
5,714✔
1923

1924
        // reset thread local storage
1925
        detail::thread_name().clear();
5,714✔
1926
    }
5,714✔
1927

1928
    void runtime::add_pre_startup_function(startup_function_type f)
×
1929
    {
1930
        if (!f.empty())
×
1931
        {
1932
            std::lock_guard<std::mutex> l(mtx_);
×
1933
            pre_startup_functions_.push_back(HPX_MOVE(f));
×
1934
        }
×
1935
    }
×
1936

1937
    void runtime::add_startup_function(startup_function_type f)
4✔
1938
    {
1939
        if (!f.empty())
4✔
1940
        {
1941
            std::lock_guard<std::mutex> l(mtx_);
4✔
1942
            startup_functions_.push_back(HPX_MOVE(f));
4✔
1943
        }
4✔
1944
    }
4✔
1945

1946
    void runtime::add_pre_shutdown_function(shutdown_function_type f)
×
1947
    {
1948
        if (!f.empty())
×
1949
        {
1950
            std::lock_guard<std::mutex> l(mtx_);
×
1951
            pre_shutdown_functions_.push_back(HPX_MOVE(f));
×
1952
        }
×
1953
    }
×
1954

1955
    void runtime::add_shutdown_function(shutdown_function_type f)
1✔
1956
    {
1957
        if (!f.empty())
1✔
1958
        {
1959
            std::lock_guard<std::mutex> l(mtx_);
1✔
1960
            shutdown_functions_.push_back(HPX_MOVE(f));
1✔
1961
        }
1✔
1962
    }
1✔
1963

1964
    hpx::util::io_service_pool* runtime::get_thread_pool(char const* name)
2,905✔
1965
    {
1966
        HPX_ASSERT(name != nullptr);
2,905✔
1967
#ifdef HPX_HAVE_IO_POOL
1968
        if (0 == std::strncmp(name, "io", 2))
2,905✔
1969
            return &io_pool_;
1✔
1970
#endif
1971
#ifdef HPX_HAVE_TIMER_POOL
1972
        if (0 == std::strncmp(name, "timer", 5))
2,904✔
1973
            return &timer_pool_;
2,902✔
1974
#endif
1975
        if (0 == std::strncmp(name, "main", 4))    //-V112
2✔
1976
            return &main_pool_;
2✔
1977

1978
        HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
1979
            "runtime::get_thread_pool", "unknown thread pool requested: {}",
1980
            name);
1981
        return nullptr;
1982
    }
2,905✔
1983

1984
    /// Register an external OS-thread with HPX
1985
    bool runtime::register_thread(char const* name,
1✔
1986
        std::size_t global_thread_num, bool service_thread, error_code& ec)
1987
    {
1988
        std::string thread_name(name);
1✔
1989
        thread_name += "-thread";
1✔
1990

1991
        init_tss_ex(thread_name.c_str(),
2✔
1992
            runtime_local::os_thread_type::custom_thread, global_thread_num,
1✔
1993
            global_thread_num, "", nullptr, service_thread, ec);
1✔
1994

1995
        return !ec ? true : false;
1✔
1996
    }
1✔
1997

1998
    /// Unregister an external OS-thread with HPX
1999
    bool runtime::unregister_thread()
4✔
2000
    {
2001
        deinit_tss_helper(
4✔
2002
            detail::thread_name().c_str(), hpx::get_worker_thread_num());
4✔
2003
        return true;
4✔
2004
    }
2005

2006
    // Access data for a given OS thread that was previously registered by
2007
    // \a register_thread. This function must be called from a thread that was
2008
    // previously registered with the runtime.
2009
    runtime_local::os_thread_data runtime::get_os_thread_data(
×
2010
        std::string const& label) const
2011
    {
2012
        return thread_support_->get_os_thread_data(label);
×
2013
    }
2014

2015
    /// Enumerate all OS threads that have registered with the runtime.
2016
    bool runtime::enumerate_os_threads(
4✔
2017
        hpx::function<bool(os_thread_data const&)> const& f) const
2018
    {
2019
        return thread_support_->enumerate_os_threads(f);
4✔
2020
    }
2021

2022
    ///////////////////////////////////////////////////////////////////////////
2023
    threads::policies::callback_notifier get_notification_policy(
×
2024
        char const* prefix)
2025
    {
2026
        return get_runtime().get_notification_policy(
×
2027
            prefix, runtime_local::os_thread_type::worker_thread);
×
2028
    }
2029

2030
    std::uint32_t get_locality_id(error_code& ec)
56,676,915✔
2031
    {
2032
        runtime* rt = get_runtime_ptr();
56,665,317✔
2033
        if (nullptr == rt || rt->get_state() == state::invalid)
56,676,915✔
2034
        {
2035
            // same as naming::invalid_locality_id
2036
            return ~static_cast<std::uint32_t>(0);
595,936✔
2037
        }
2038

2039
        return rt->get_locality_id(ec);
55,982,149✔
2040
    }
56,578,614✔
2041

2042
    std::size_t get_num_worker_threads()
1,140✔
2043
    {
2044
        runtime* rt = get_runtime_ptr();
1,140✔
2045
        if (nullptr == rt)
1,140✔
2046
        {
2047
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2048
                "hpx::get_num_worker_threads",
2049
                "the runtime system has not been initialized yet");
2050
            return std::size_t(0);
2051
        }
2052

2053
        return rt->get_num_worker_threads();
1,140✔
2054
    }
×
2055

2056
    /// \brief Return the number of localities which are currently registered
2057
    ///        for the running application.
2058
    std::uint32_t get_num_localities(hpx::launch::sync_policy, error_code& ec)
311✔
2059
    {
2060
        runtime* rt = get_runtime_ptr();
311✔
2061
        if (nullptr == rt)
311✔
2062
        {
2063
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2064
                "hpx::get_num_localities",
2065
                "the runtime system has not been initialized yet");
2066
            return std::size_t(0);
2067
        }
2068

2069
        return rt->get_num_localities(hpx::launch::sync, ec);
311✔
2070
    }
×
2071

2072
    std::uint32_t get_initial_num_localities()
67,872✔
2073
    {
2074
        runtime* rt = get_runtime_ptr();
67,872✔
2075
        if (nullptr == rt)
67,872✔
2076
        {
2077
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2078
                "hpx::get_initial_num_localities",
2079
                "the runtime system has not been initialized yet");
2080
            return std::size_t(0);
2081
        }
2082

2083
        return rt->get_initial_num_localities();
67,872✔
2084
    }
×
2085

2086
    hpx::future<std::uint32_t> get_num_localities()
9✔
2087
    {
2088
        runtime* rt = get_runtime_ptr();
9✔
2089
        if (nullptr == rt)
9✔
2090
        {
2091
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2092
                "hpx::get_num_localities",
2093
                "the runtime system has not been initialized yet");
2094
            return make_ready_future(std::uint32_t(0));
2095
        }
2096

2097
        return rt->get_num_localities();
9✔
2098
    }
×
2099

2100
    namespace threads {
2101
        char const* get_stack_size_name(std::ptrdiff_t size)
2✔
2102
        {
2103
            thread_stacksize size_enum = thread_stacksize::unknown;
2✔
2104

2105
            hpx::util::runtime_configuration const& rtcfg = hpx::get_config();
2✔
2106
            if (rtcfg.get_stack_size(thread_stacksize::small_) == size)
2✔
2107
                size_enum = thread_stacksize::small_;
×
2108
            else if (rtcfg.get_stack_size(thread_stacksize::medium) == size)
2✔
2109
                size_enum = thread_stacksize::medium;
×
2110
            else if (rtcfg.get_stack_size(thread_stacksize::large) == size)
2✔
2111
                size_enum = thread_stacksize::large;
2✔
2112
            else if (rtcfg.get_stack_size(thread_stacksize::huge) == size)
×
2113
                size_enum = thread_stacksize::huge;
×
2114
            else if (rtcfg.get_stack_size(thread_stacksize::nostack) == size)
×
2115
                size_enum = thread_stacksize::nostack;
×
2116

2117
            return get_stack_size_enum_name(size_enum);
2✔
2118
        }
2119
    }    // namespace threads
2120
}    // namespace hpx
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc