Skip to content

Commit 7d35f5f

Browse files
committed
Added self thread attribute control interface to reflect the point below raised at RTWG.
>It would be interesting to have some rcpputils functions to configure real-time attributes for an existing thread. Signed-off-by: Shoji Morita <s-morita@esol.co.jp>
1 parent e70ec85 commit 7d35f5f

11 files changed

Lines changed: 276 additions & 66 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
3636
target_sources(${PROJECT_NAME} PRIVATE
3737
src/thread/detail/posix/thread.cpp
3838
src/thread/detail/posix/thread_attribute.cpp
39-
src/thread/detail/posix/linux/cpu_set.cpp)
39+
src/thread/detail/posix/linux/cpu_set.cpp
40+
src/thread/detail/posix/linux/thread.cpp)
4041
endif()
4142
if(WIN32)
4243
target_compile_definitions(${PROJECT_NAME}

include/rcpputils/thread/detail/posix/linux/cpu_set.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@
2727
namespace rcpputils
2828
{
2929

30+
namespace thread
31+
{
32+
namespace detail
33+
{
34+
35+
struct CpuSetDeleter
36+
{
37+
void operator()(cpu_set_t * p) const;
38+
};
39+
using UniqueNativeCpuSet = std::unique_ptr<cpu_set_t, CpuSetDeleter>;
40+
41+
} // namespace detail
42+
} // namespace thread
43+
3044
struct CpuSet
3145
{
3246
using NativeCpuSetType = cpu_set_t *;
@@ -54,11 +68,7 @@ struct CpuSet
5468
void init_cpu_set();
5569
void valid_cpu(std::size_t cpu) const;
5670
static std::size_t alloc_size();
57-
struct CpuSetDeleter
58-
{
59-
void operator()(NativeCpuSetType cpu_set) const;
60-
};
61-
std::unique_ptr<cpu_set_t, CpuSetDeleter> cpu_set_;
71+
thread::detail::UniqueNativeCpuSet cpu_set_;
6272
};
6373

6474
inline void swap(CpuSet & a, CpuSet & b)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2024 eSOL Co.,Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_OPTIONS_HPP_
16+
#define RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_OPTIONS_HPP_
17+
18+
#include <optional>
19+
#include <utility>
20+
21+
#include "rcpputils/thread/detail/posix/cpu_set.hpp"
22+
#include "rcpputils/thread/detail/posix/sched_policy.hpp"
23+
#include "rcpputils/visibility_control.hpp"
24+
25+
namespace rcpputils
26+
{
27+
28+
struct SchedOptions
29+
{
30+
void swap(SchedOptions & other)
31+
{
32+
using std::swap;
33+
swap(policy, other.policy);
34+
swap(priority, other.priority);
35+
swap(core_affinity, other.core_affinity);
36+
}
37+
38+
std::optional<int> priority;
39+
std::optional<SchedPolicy> policy;
40+
std::optional<CpuSet> core_affinity;
41+
};
42+
43+
inline void swap(SchedOptions & a, SchedOptions & b)
44+
{
45+
a.swap(b);
46+
}
47+
48+
} // namespace rcpputils
49+
50+
#endif // RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_OPTIONS_HPP_
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2024 eSOL Co.,Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_POLICY_HPP_
16+
#define RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_POLICY_HPP_
17+
18+
#include <sched.h>
19+
20+
#include "rcutils/thread_attr.h"
21+
22+
#include "rcpputils/visibility_control.hpp"
23+
24+
namespace rcpputils
25+
{
26+
27+
namespace thread
28+
{
29+
namespace detail
30+
{
31+
32+
constexpr unsigned int sched_policy_explicit_bit = 0x8000'0000;
33+
34+
} // namespace detail
35+
} // namespace thread
36+
37+
enum struct SchedPolicy : unsigned int
38+
{
39+
inherit,
40+
other = thread::detail::sched_policy_explicit_bit | SCHED_OTHER,
41+
#ifdef SCHED_FIFO
42+
fifo = thread::detail::sched_policy_explicit_bit | SCHED_FIFO,
43+
#endif
44+
#ifdef SCHED_RR
45+
rr = thread::detail::sched_policy_explicit_bit | SCHED_RR,
46+
#endif
47+
#ifdef SCHED_IDLE
48+
idle = thread::detail::sched_policy_explicit_bit | SCHED_IDLE,
49+
#endif
50+
#ifdef SCHED_BATCH
51+
batch = thread::detail::sched_policy_explicit_bit | SCHED_BATCH,
52+
#endif
53+
#ifdef SCHED_SPORADIC
54+
sporadic = thread::detail::sched_policy_explicit_bit | SCHED_SPORADIC,
55+
#endif
56+
// #if __linux__
57+
// linux deadline scheduler requires more parameter, not supported now
58+
// #ifdef SCHED_DEADLINE
59+
// deadline = SCHED_DEADLINE,
60+
// #endif
61+
// #endif
62+
};
63+
64+
SchedPolicy from_rcutils_thread_scheduling_policy(
65+
rcutils_thread_scheduling_policy_t rcutils_sched_policy);
66+
67+
} // namespace rcpputils
68+
69+
#endif // RCPPUTILS__THREAD__DETAIL__POSIX__SCHED_POLICY_HPP_

include/rcpputils/thread/detail/posix/thread.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <utility>
2929

3030
#include "rcpputils/thread/detail/thread_id.hpp"
31+
#include "rcpputils/thread/detail/posix/sched_options.hpp"
3132
#include "rcpputils/thread/detail/posix/thread_attribute.hpp"
3233
#include "rcpputils/thread/detail/posix/thread_func.hpp"
3334
#include "rcpputils/thread/detail/posix/utilities.hpp"
@@ -185,6 +186,8 @@ inline void yield() noexcept
185186
sched_yield();
186187
}
187188

189+
void apply_sched_options(SchedOptions const & options);
190+
188191
} // namespace this_thread
189192

190193
} // namespace rcpputils

include/rcpputils/thread/detail/posix/thread_attribute.hpp

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,12 @@
2222
#include "rcutils/thread_attr.h"
2323

2424
#include "rcpputils/thread/detail/posix/cpu_set.hpp"
25+
#include "rcpputils/thread/detail/posix/sched_policy.hpp"
2526
#include "rcpputils/visibility_control.hpp"
2627

2728
namespace rcpputils
2829
{
2930

30-
namespace thread
31-
{
32-
namespace detail
33-
{
34-
35-
constexpr unsigned int sched_policy_explicit_bit = 0x8000'0000;
36-
37-
}
38-
}
39-
40-
enum struct SchedPolicy : unsigned int
41-
{
42-
inherit,
43-
other = thread::detail::sched_policy_explicit_bit | SCHED_OTHER,
44-
#ifdef SCHED_FIFO
45-
fifo = thread::detail::sched_policy_explicit_bit | SCHED_FIFO,
46-
#endif
47-
#ifdef SCHED_RR
48-
rr = thread::detail::sched_policy_explicit_bit | SCHED_RR,
49-
#endif
50-
#ifdef SCHED_IDLE
51-
idle = thread::detail::sched_policy_explicit_bit | SCHED_IDLE,
52-
#endif
53-
#ifdef SCHED_BATCH
54-
batch = thread::detail::sched_policy_explicit_bit | SCHED_BATCH,
55-
#endif
56-
#ifdef SCHED_SPORADIC
57-
sporadic = thread::detail::sched_policy_explicit_bit | SCHED_SPORADIC,
58-
#endif
59-
// #if __linux__
60-
// linux deadline scheduler requires more parameter, not supported now
61-
// #ifdef SCHED_DEADLINE
62-
// deadline = SCHED_DEADLINE,
63-
// #endif
64-
// #endif
65-
};
66-
67-
SchedPolicy from_rcutils_thread_scheduling_policy(
68-
rcutils_thread_scheduling_policy_t rcutils_sched_policy);
69-
7031
struct ThreadAttribute
7132
{
7233
ThreadAttribute();

include/rcpputils/thread/detail/posix/utilities.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
#ifndef RCPPUTILS__THREAD__DETAIL__POSIX__UTILITIES_HPP_
1616
#define RCPPUTILS__THREAD__DETAIL__POSIX__UTILITIES_HPP_
1717

18+
#include <memory>
1819
#include <system_error>
1920

21+
#include "rcpputils/thread/detail/posix/sched_policy.hpp"
22+
2023
namespace rcpputils
2124
{
2225
namespace thread
@@ -31,6 +34,18 @@ inline void throw_if_error(int r, char const * msg)
3134
}
3235
}
3336

37+
using thread::detail::sched_policy_explicit_bit;
38+
39+
inline bool is_explicit_sched_policy(int native_policy)
40+
{
41+
return (static_cast<unsigned>(native_policy) & sched_policy_explicit_bit) != 0;
42+
}
43+
44+
inline int to_native_sched_policy(rcpputils::SchedPolicy policy)
45+
{
46+
return static_cast<unsigned>(policy) & ~sched_policy_explicit_bit;
47+
}
48+
3449
} // namespace detail
3550
} // namespace thread
3651
} // namespace rcpputils

src/thread/detail/posix/linux/cpu_set.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void CpuSet::init_cpu_set()
175175
}
176176
auto p = CPU_ALLOC(num_processors());
177177
CPU_ZERO_S(alloc_size(), p);
178-
cpu_set_ = std::unique_ptr<cpu_set_t, CpuSetDeleter>(p);
178+
cpu_set_ = thread::detail::UniqueNativeCpuSet(p);
179179
}
180180

181181
void CpuSet::valid_cpu(std::size_t cpu) const
@@ -191,9 +191,17 @@ std::size_t CpuSet::alloc_size()
191191
return CPU_ALLOC_SIZE(num_processors());
192192
}
193193

194-
void CpuSet::CpuSetDeleter::operator()(NativeCpuSetType cpu_set) const
194+
195+
namespace thread
196+
{
197+
namespace detail
198+
{
199+
200+
void CpuSetDeleter::operator()(cpu_set_t * cpu_set) const
195201
{
196202
CPU_FREE(cpu_set);
197203
}
198204

205+
} // namespace detail
206+
} // namespace thread
199207
} // namespace rcpputils
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2024 eSOL Co.,Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <sys/types.h>
16+
#include <sched.h>
17+
18+
#include <stdexcept>
19+
#include <iostream>
20+
21+
#include "rcpputils/thread/detail/posix/thread.hpp"
22+
#include "rcpputils/thread/detail/posix/utilities.hpp"
23+
#include "./thread_impl.hpp"
24+
25+
namespace rcpputils
26+
{
27+
28+
namespace this_thread
29+
{
30+
31+
using thread::detail::UniqueNativeCpuSet;
32+
using thread::detail::make_unique_native_cpu_set;
33+
using thread::detail::throw_if_error;
34+
using thread::detail::to_native_sched_policy;
35+
36+
void apply_sched_options(SchedOptions const & options)
37+
{
38+
pid_t tid = gettid();
39+
if (options.policy) {
40+
int native_sched_policy = to_native_sched_policy(*options.policy);
41+
sched_param param;
42+
int r;
43+
if (options.priority) {
44+
param.sched_priority = *options.priority;
45+
} else {
46+
r = sched_getparam(tid, &param);
47+
throw_if_error(r, "error in sched_getparam");
48+
}
49+
r = sched_setscheduler(tid, native_sched_policy, &param);
50+
throw_if_error(r, "error in sched_setscheduler");
51+
} else if (options.priority) {
52+
sched_param param;
53+
param.sched_priority = *options.priority;
54+
int r = sched_setparam(tid, &param);
55+
throw_if_error(r, "error in sched_setparam");
56+
}
57+
if (options.core_affinity) {
58+
UniqueNativeCpuSet native_cpu_set = make_unique_native_cpu_set(*options.core_affinity);
59+
std::size_t sz = CPU_ALLOC_SIZE(options.core_affinity->count());
60+
int r = sched_setaffinity(tid, sz, native_cpu_set.get());
61+
throw_if_error(r, "error in sched_setaffinity");
62+
}
63+
}
64+
65+
} // namespace this_thread
66+
} // namespace rcpputils
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2024 eSOL Co.,Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef THREAD__DETAIL__POSIX__LINUX__THREAD_IMPL_HPP_
16+
#define THREAD__DETAIL__POSIX__LINUX__THREAD_IMPL_HPP_
17+
18+
#include <memory>
19+
20+
#include "rcpputils/thread/detail/posix/linux/cpu_set.hpp"
21+
22+
namespace rcpputils
23+
{
24+
namespace thread
25+
{
26+
namespace detail
27+
{
28+
29+
inline UniqueNativeCpuSet make_unique_native_cpu_set(CpuSet const & cpu_set)
30+
{
31+
return UniqueNativeCpuSet{cpu_set.native_cpu_set()};
32+
}
33+
34+
} // namespace detail
35+
} // namespace thread
36+
} // namespace rcpputils
37+
38+
#endif // THREAD__DETAIL__POSIX__LINUX__THREAD_IMPL_HPP_

0 commit comments

Comments
 (0)