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

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

61.11
/libs/core/threading_base/src/execution_agent.cpp
1
//  Copyright (c) 2019 Thomas Heller
2
//  Copyright (c) 2020-2025 Hartmut Kaiser
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/modules/coroutines.hpp>
11
#include <hpx/modules/errors.hpp>
12
#include <hpx/modules/format.hpp>
13
#include <hpx/modules/functional.hpp>
14
#include <hpx/modules/lock_registration.hpp>
15
#include <hpx/modules/logging.hpp>
16
#include <hpx/threading_base/execution_agent.hpp>
17
#include <hpx/threading_base/scheduler_base.hpp>
18
#include <hpx/threading_base/set_thread_state.hpp>
19
#include <hpx/threading_base/thread_data.hpp>
20
#include <hpx/threading_base/thread_description.hpp>
21
#include <hpx/threading_base/thread_num_tss.hpp>
22

23
#ifdef HPX_HAVE_THREAD_DESCRIPTION
24
#include <hpx/threading_base/detail/reset_lco_description.hpp>
25
#endif
26
#ifdef HPX_HAVE_THREAD_BACKTRACE_ON_SUSPENSION
27
#include <hpx/modules/debugging.hpp>
28
#include <hpx/threading_base/detail/reset_backtrace.hpp>
29
#endif
30

31
#include <cstddef>
32
#include <cstdint>
33
#include <string>
34
#include <utility>
35

36
namespace hpx::threads {
37

38
    execution_agent::execution_agent(
8,397✔
39
        coroutines::detail::coroutine_impl* coroutine) noexcept
8,397✔
40
      : self_(coroutine)
8,397✔
41
    {
42
    }
8,397✔
43

44
    std::string execution_agent::description() const
×
45
    {
46
        thread_id_type const id = self_.get_thread_id();
47
        if (HPX_UNLIKELY(!id))
×
48
        {
49
            HPX_THROW_EXCEPTION(hpx::error::null_thread_id,
×
50
                "execution_agent::description",
51
                "null thread id encountered (is this executed on a "
52
                "HPX-thread?)");
53
        }
54

55
        return hpx::util::format(
56
            "{}: {}", id, get_thread_id_data(id)->get_description());
×
57
    }
58

59
    void execution_agent::yield(char const* desc)
686,332✔
60
    {
61
        do_yield(desc, hpx::threads::thread_schedule_state::pending);
686,332✔
62
    }
686,332✔
63

64
    bool execution_agent::yield_k(std::size_t k, char const* desc)
14,207✔
65
    {
66
        if (k < 4)    //-V112
14,207✔
67
        {
68
            return false;
69
        }
70
#if defined(HPX_SMT_PAUSE)
734✔
71
        else if (k < 16)
72
        {
606✔
73
            HPX_SMT_PAUSE;
74
            return false;
75
        }
128✔
76
#endif
77
        else if (k < 32 || k & 1)    //-V112
124✔
78
        {
79
            do_yield(desc, hpx::threads::thread_schedule_state::pending_boost);
80
            return true;
81
        }
4✔
82
        else
83
        {
14,207✔
84
            do_yield(desc, hpx::threads::thread_schedule_state::pending);
85
            return true;
27,770✔
86
        }
87
    }
27,770✔
88

27,770✔
89
    void execution_agent::resume(
90
        hpx::threads::thread_priority priority, char const* desc)
×
91
    {
92
        do_resume(priority, desc, threads::thread_restart_state::signaled);
×
93
    }
×
94

95
    void execution_agent::abort(char const* desc)
27,770✔
96
    {
97
        do_resume(hpx::threads::thread_priority::default_, desc,
27,770✔
98
            threads::thread_restart_state::abort);
27,770✔
99
    }
100

×
101
    void execution_agent::suspend(char const* desc)
102
    {
103
        do_yield(desc, threads::thread_schedule_state::suspended);
×
104
    }
×
105

106
    void execution_agent::sleep_for(
×
107
        hpx::chrono::steady_duration const& sleep_duration, char const* desc)
108
    {
109
        sleep_until(sleep_duration.from_now(), desc);
110
    }
×
111

112
    void execution_agent::sleep_until(
113
        hpx::chrono::steady_time_point const& sleep_time, char const* desc)
114
    {
115
        // Just yield until time has passed by...
116
        auto now = std::chrono::steady_clock::now();
117

118
        // Note: we yield at least once to allow for other threads to make
×
119
        // progress in any case. We also use yield instead of yield_k for the
120
        // same reason.
×
121
        std::size_t k = 0;
122
        do
123
        {
124
            if (k < 32 || k & 1)    //-V112
125
            {
×
126
                do_yield(
127
                    desc, hpx::threads::thread_schedule_state::pending_boost);
×
128
            }
×
129
            else
×
130
            {
×
131
                do_yield(desc, hpx::threads::thread_schedule_state::pending);
132
            }
133
            ++k;
134
            now = std::chrono::steady_clock::now();
135
        } while (now < sleep_time.value());
136
    }
137

138
    hpx::threads::thread_restart_state execution_agent::do_yield(
139
        char const* desc, threads::thread_schedule_state state)
140
    {
141
        thread_id_ref_type id = self_.get_thread_id();    // keep alive
142
        if (HPX_UNLIKELY(!id))
143
        {
144
            HPX_THROW_EXCEPTION(hpx::error::null_thread_id,
145
                "execution_agent::do_yield",
146
                "null thread id encountered (is this executed on a "
147
                "HPX-thread?)");
148
        }
149

150
        // handle interruption, if needed
151
        thread_data* thrd_data = get_thread_id_data(id);
152
        if (HPX_UNLIKELY(thrd_data == nullptr))
153
        {
714,230✔
154
            HPX_THROW_EXCEPTION(hpx::error::null_thread_id,
155
                "execution_agent::do_yield",
156
                "null thread id encountered (is this executed on a "
157
                "HPX-thread?)");
714,230✔
158
        }
159

×
160
        thrd_data->interruption_point();
161

162
        if (thrd_data->get_priority() == thread_priority::bound)
163
        {
164
            auto const num_thread = hpx::get_local_worker_thread_num();
165
            thrd_data->set_last_worker_thread_num(
166
                static_cast<std::uint16_t>(num_thread));
167
        }
168

169
        threads::thread_restart_state statex;
170

171
        {
172
#if defined(HPX_HAVE_THREAD_DESCRIPTION)
173
            [[maybe_unused]] threads::detail::reset_lco_description reset_desc(
174
                id.noref(), threads::thread_description(desc));
175
#endif
714,230✔
176
#if defined(HPX_HAVE_THREAD_BACKTRACE_ON_SUSPENSION)
177
            [[maybe_unused]] threads::detail::reset_backtrace reset_bt(id);
714,230✔
178
#endif
179
#if defined(HPX_HAVE_VERIFY_LOCKS)
180
            [[maybe_unused]] auto held_locks = hpx::experimental::scope_exit(
181
                [data = hpx::util::get_held_locks_data()]() mutable {
182
                    hpx::util::set_held_locks_data(HPX_MOVE(data));
183
                });
184
#endif
185
            HPX_ASSERT(thrd_data != nullptr &&
186
                thrd_data->get_state().state() ==
187
                    thread_schedule_state::active);
188
            HPX_ASSERT(state != thread_schedule_state::active);
189

190
            // actual yield operation
191
            statex = self_.yield(
192
                threads::thread_result_type(state, threads::invalid_thread_id));
193

194
            HPX_ASSERT(thrd_data != nullptr &&
195
                thrd_data->get_state().state() ==
196
                    thread_schedule_state::active);
197
        }
198

714,230✔
199
        // handle interruption, if needed
714,230✔
200
        thrd_data->interruption_point();
201

202
        // handle interrupt and abort
203
        if (statex == threads::thread_restart_state::abort)
204
        {
205
            HPX_THROW_EXCEPTION(hpx::error::yield_aborted, desc,
206
                "thread({}) aborted (yield returned wait_abort)",
207
                description());
714,230✔
208
        }
209

210
        return statex;
714,230✔
211
    }
212

×
213
    void execution_agent::do_resume(hpx::threads::thread_priority priority,
214
        char const* /* desc */, hpx::threads::thread_restart_state statex) const
215
    {
216
        threads::detail::set_thread_state(self_.get_thread_id(),
217
            thread_schedule_state::pending, statex, priority,
714,230✔
218
            thread_schedule_hint{}, false);
219
    }
220
}    // namespace hpx::threads
27,770✔
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