• 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

34.0
/libs/core/runtime_local/src/thread_mapper.cpp
1
//  Copyright (c) 2012 Maciej Brodowicz
2
//
3
//  SPDX-License-Identifier: BSL-1.0
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/modules/errors.hpp>
8
#include <hpx/modules/functional.hpp>
9
#include <hpx/runtime_local/os_thread_type.hpp>
10
#include <hpx/runtime_local/thread_mapper.hpp>
11

12
#include <cstddef>
13
#include <cstdint>
14
#include <mutex>
15
#include <string>
16
#include <thread>
17

18
#if defined(HPX_WINDOWS)
19
#include <windows.h>
20
#else
21
#include <pthread.h>
22
#endif
23

24
#if defined(HPX_HAVE_PAPI) && defined(__linux__) && !defined(__ANDROID) &&     \
25
    !defined(ANDROID)
26
#include <sys/syscall.h>
27
#include <unistd.h>
28
#endif
29

30
namespace hpx::util {
31

32
    namespace detail {
33

34
        ///////////////////////////////////////////////////////////////////////
35
        std::uint64_t get_system_thread_id()
×
36
        {
37
#if defined(HPX_WINDOWS)
38
            return static_cast<std::uint64_t>(::GetCurrentThreadId());
39
#else
40
            return std::uint64_t(::pthread_self());
942✔
41
#endif
42
        }
43

44
        // thread-specific data
45
        os_thread_data::os_thread_data(
471✔
46
            std::string const& label, runtime_local::os_thread_type type)
471✔
47
          : label_(label)
471✔
48
          , id_(std::this_thread::get_id())
471✔
49
          , tid_(get_system_thread_id())
471✔
50
#if defined(HPX_HAVE_PAPI) && defined(__linux__) && !defined(__ANDROID) &&     \
51
    !defined(ANDROID)
52
          , linux_tid_(syscall(SYS_gettid))
53
#endif
54
          , type_(type)
55
        {
471✔
56
        }
57

471✔
58
        void os_thread_data::invalidate()
59
        {
471✔
60
            tid_ = thread_mapper::invalid_tid;
61
            cleanup_.reset();
471✔
62
        }
63

471✔
64
        bool os_thread_data::is_valid() const
65
        {
×
66
            return tid_ != thread_mapper::invalid_tid;
67
        }
×
68
    }    // namespace detail
69

70
    ///////////////////////////////////////////////////////////////////////////
71
    thread_mapper::thread_mapper() = default;
72

64✔
73
    thread_mapper::~thread_mapper()
74
    {
64✔
75
        std::lock_guard<mutex_type> m(mtx_);
76

64✔
77
        std::uint32_t i = 0;
78
        for (auto&& tinfo : thread_map_)
79
        {
535✔
80
            if (tinfo.cleanup_)
81
            {
471✔
82
                tinfo.cleanup_(i++);
83
            }
×
84
        }
85
    }
86

64✔
87
    std::uint32_t thread_mapper::register_thread(
88
        char const* name, runtime_local::os_thread_type type)
471✔
89
    {
90
        std::lock_guard<mutex_type> m(mtx_);
91

471✔
92
        auto const tid = detail::get_system_thread_id();
93
        for (auto&& tinfo : thread_map_)
94
        {
2,045✔
95
            if (tinfo.tid_ == tid)
96
            {
1,574✔
97
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
98
                    "thread_mapper::register_thread",
×
99
                    "thread already registered");
100
            }
101
        }
102

103
        // create mappings
104
        thread_map_.emplace_back(name, type);
105

471✔
106
        std::size_t const idx = thread_map_.size() - 1;
107
        label_map_[name] = idx;
471✔
108

471✔
109
        return static_cast<std::uint32_t>(idx);
110
    }
471✔
111

112
    bool thread_mapper::unregister_thread()
113
    {
471✔
114
        std::lock_guard<mutex_type> m(mtx_);
115

471✔
116
        std::uint32_t i = 0;
117
        auto const tid = detail::get_system_thread_id();
118
        for (auto&& tinfo : thread_map_)
119
        {
2,045✔
120
            if (tinfo.tid_ == tid)
121
            {
2,045✔
122
                label_map_.erase(tinfo.label_);
123
                if (tinfo.cleanup_)
471✔
124
                {
471✔
125
                    [[maybe_unused]] auto _ = tinfo.cleanup_(i);
126
                }
×
127

128
                std::size_t const size = thread_map_.size();
129
                if (static_cast<std::size_t>(i) == size)
130
                {
471✔
131
                    thread_map_.resize(size - 1);
132
                }
×
133
                else
134
                {
135
                    tinfo.invalidate();
136
                }
471✔
137
                return true;
138
            }
139
            ++i;
140
        }
1,574✔
141
        return false;
142
    }
143

144
    bool thread_mapper::register_callback(
145
        std::uint32_t tix, callback_type const& cb)
×
146
    {
147
        std::lock_guard<mutex_type> m(mtx_);
148

×
149
        auto const idx = static_cast<std::size_t>(tix);
150
        if (idx >= thread_map_.size() ||
×
151
            !thread_map_[tix].is_valid())    //-V108
×
152
        {
×
153
            return false;
154
        }
×
155

156
        thread_map_[tix].cleanup_ = cb;    //-V108
157
        return true;
158
    }
159

160
    bool thread_mapper::revoke_callback(std::uint32_t tix)
161
    {
×
162
        std::lock_guard<mutex_type> m(mtx_);
163

×
164
        auto const idx = static_cast<std::size_t>(tix);
165
        if (idx >= thread_map_.size() ||
×
166
            !thread_map_[tix].is_valid())    //-V108
×
167
        {
×
168
            return false;
169
        }
×
170

171
        thread_map_[tix].cleanup_.reset();    //-V108
172
        return true;
173
    }
×
174

175
    std::thread::id thread_mapper::get_thread_id(std::uint32_t tix) const
176
    {
×
177
        std::lock_guard<mutex_type> m(mtx_);
178

×
179
        auto const idx = static_cast<std::size_t>(tix);
180
        if (idx >= thread_map_.size())
×
181
        {
×
182
            return std::thread::id{};
183
        }
×
184
        return thread_map_[idx].id_;
185
    }
×
186

187
    std::uint64_t thread_mapper::get_thread_native_handle(
188
        std::uint32_t tix) const
×
189
    {
190
        std::lock_guard<mutex_type> m(mtx_);
191

×
192
        auto const idx = static_cast<std::size_t>(tix);
193
        if (idx >= thread_map_.size())
×
194
        {
×
195
            return thread_mapper::invalid_tid;
196
        }
197
        return thread_map_[idx].tid_;
198
    }
×
199

200
#if defined(HPX_HAVE_PAPI) && defined(__linux__) && !defined(__ANDROID) &&     \
201
    !defined(ANDROID)
202
    pid_t thread_mapper::get_linux_thread_id(std::uint32_t tix) const
203
    {
204
        std::lock_guard<mutex_type> m(mtx_);
205

206
        auto idx = static_cast<std::size_t>(tix);
207
        if (idx >= thread_map_.size())
208
        {
209
            return -1;
210
        }
211
        return thread_map_[idx].linux_tid_;
212
    }
213
#endif
214

215
    std::string const& thread_mapper::get_thread_label(std::uint32_t tix) const
216
    {
×
217
        std::lock_guard<mutex_type> m(mtx_);
218

×
219
        auto const idx = static_cast<std::size_t>(tix);
220
        if (idx >= thread_map_.size())
×
221
        {
×
222
            static std::string invalid_label;
223
            return invalid_label;
×
224
        }
×
225
        return thread_map_[idx].label_;
226
    }
×
227

228
    runtime_local::os_thread_type thread_mapper::get_thread_type(
229
        std::uint32_t tix) const
×
230
    {
231
        std::lock_guard<mutex_type> m(mtx_);
232

×
233
        auto const idx = static_cast<std::size_t>(tix);
234
        if (idx >= thread_map_.size())
×
235
        {
×
236
            return runtime_local::os_thread_type::unknown;
237
        }
238
        return thread_map_[idx].type_;
239
    }
×
240

241
    std::uint32_t thread_mapper::get_thread_index(
242
        std::string const& label) const
×
243
    {
244
        std::lock_guard<mutex_type> m(mtx_);
245

×
246
        auto const it = label_map_.find(label);
247
        if (it == label_map_.end())
248
        {
×
249
            return invalid_index;
250
        }
251
        return static_cast<std::uint32_t>(it->second);
252
    }
×
253

254
    std::uint32_t thread_mapper::get_thread_count() const
255
    {
×
256
        std::lock_guard<mutex_type> m(mtx_);
257

×
258
        return static_cast<std::uint32_t>(label_map_.size());
259
    }
×
260

261
    // retrieve all data stored for a given thread
262
    os_thread_data thread_mapper::get_os_thread_data(
263
        std::string const& label) const
×
264
    {
265
        std::lock_guard<mutex_type> m(mtx_);
266

×
267
        auto const it = label_map_.find(label);
268
        if (it == label_map_.end())
269
        {
×
270
            return runtime_local::os_thread_data{"", std::thread::id{},
271
                thread_mapper::invalid_tid,
×
272
                runtime_local::os_thread_type::unknown};
273
        }
×
274

275
        auto const idx = static_cast<std::size_t>(it->second);
276
        if (idx >= thread_map_.size())
×
277
        {
×
278
            return runtime_local::os_thread_data{"", std::thread::id{},
279
                thread_mapper::invalid_tid,
×
280
                runtime_local::os_thread_type::unknown};
281
        }
×
282

283
        auto const& tinfo = thread_map_[idx];
284
        return runtime_local::os_thread_data{
285
            tinfo.label_, tinfo.id_, tinfo.tid_, tinfo.type_};
×
286
    }
×
287

288
    bool thread_mapper::enumerate_os_threads(
289
        hpx::function<bool(os_thread_data const&)> const& f) const
×
290
    {
291
        std::lock_guard<mutex_type> m(mtx_);
292
        for (auto const& tinfo : thread_map_)
×
293
        {
×
294
            os_thread_data data{
295
                tinfo.label_, tinfo.id_, tinfo.tid_, tinfo.type_};
296
            if (!f(data))
×
297
            {
×
298
                return false;
299
            }
300
        }
301
        return true;
302
    }
303
}    // namespace hpx::util
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