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

STEllAR-GROUP / hpx / #862

10 Jan 2023 05:30PM UTC coverage: 86.582% (-0.05%) from 86.634%
#862

push

StellarBot
Merge #6130

6130: Remove the mutex lock in the critical path of get_partitioner. r=hkaiser a=JiakunYan

Remove the mutex lock in the critical path of hpx::resource::detail::get_partitioner.

The protected variable `partitioner_ref` is only set once during initialization.

Co-authored-by: Jiakun Yan <jiakunyan1998@gmail.com>

6 of 6 new or added lines in 1 file covered. (100.0%)

174767 of 201851 relevant lines covered (86.58%)

2069816.07 hits per line

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

39.55
/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/functional/function.hpp>
8
#include <hpx/modules/errors.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 { namespace util {
31

32
    namespace detail {
33

34
        ///////////////////////////////////////////////////////////////////////
35
        std::uint64_t get_system_thread_id()
33,129✔
36
        {
37
#if defined(HPX_WINDOWS)
38
            return std::uint64_t(::GetCurrentThreadId());
39
#else
40
            return std::uint64_t(::pthread_self());
33,129✔
41
#endif
42
        }
43

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

59
        void os_thread_data::invalidate()
11,035✔
60
        {
61
            tid_ = thread_mapper::invalid_tid;
11,035✔
62
            cleanup_.reset();
11,035✔
63
        }
11,035✔
64

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

71
    ///////////////////////////////////////////////////////////////////////////
72
    thread_mapper::thread_mapper() = default;
1,220✔
73

74
    thread_mapper::~thread_mapper()
1,217✔
75
    {
76
        std::lock_guard<mutex_type> m(mtx_);
1,217✔
77

78
        std::uint32_t i = 0;
1,217✔
79
        for (auto&& tinfo : thread_map_)
12,243✔
80
        {
81
            if (tinfo.cleanup_)
11,026✔
82
            {
83
                tinfo.cleanup_(i++);
×
84
            }
×
85
        }
86
    }
1,217✔
87

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

93
        auto tid = detail::get_system_thread_id();
11,038✔
94
        for (auto&& tinfo : thread_map_)
90,712✔
95
        {
96
            if (tinfo.tid_ == tid)
79,665✔
97
            {
98
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
99
                    "thread_mapper::register_thread",
100
                    "thread already registered");
101
            }
102
        }
103

104
        // create mappings
105
        thread_map_.emplace_back(name, type);
11,047✔
106

107
        std::size_t idx = thread_map_.size() - 1;
11,047✔
108
        label_map_[name] = idx;
11,047✔
109

110
        return static_cast<std::uint32_t>(idx);
11,047✔
111
    }
11,047✔
112

113
    bool thread_mapper::unregister_thread()
10,939✔
114
    {
115
        std::lock_guard<mutex_type> m(mtx_);
11,035✔
116

117
        std::uint32_t i = 0;
11,035✔
118
        auto tid = detail::get_system_thread_id();
10,939✔
119
        for (auto&& tinfo : thread_map_)
90,670✔
120
        {
121
            if (tinfo.tid_ == tid)
90,670✔
122
            {
123
                label_map_.erase(tinfo.label_);
11,035✔
124
                if (tinfo.cleanup_)
11,035✔
125
                {
126
                    tinfo.cleanup_(i);
×
127
                }
×
128

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

289
    bool thread_mapper::enumerate_os_threads(
4✔
290
        hpx::function<bool(os_thread_data const&)> const& f) const
291
    {
292
        std::lock_guard<mutex_type> m(mtx_);
4✔
293
        for (auto const& tinfo : thread_map_)
46✔
294
        {
295
            os_thread_data data{
42✔
296
                tinfo.label_, tinfo.id_, tinfo.tid_, tinfo.type_};
42✔
297
            if (!f(data))
42✔
298
            {
299
                return false;
×
300
            }
301
        }
42✔
302
        return true;
4✔
303
    }
4✔
304

305
}}    // 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