File indexing completed on 2025-05-11 08:24:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #if !defined(_GNU_SOURCE)
0029 #define _GNU_SOURCE
0030 #endif
0031
0032 #include <system_error>
0033
0034 #include <rtems/error.hpp>
0035 #include <rtems/thread.hpp>
0036
0037 #include <pthread.h>
0038
0039 #include <rtems.h>
0040
0041 #if HAVE_GET_SCHEDULER_NAME
0042 extern "C" bool get_scheduler_name(rtems_id sid, char* name);
0043 #endif
0044
0045 #if HAVE_GET_SCHEDULER_NAME
0046 bool get_scheduler_name(rtems_id sid, char* name)
0047 {
0048 name[0] = 'N';
0049 name[1] = 'O';
0050 name[2] = 'P';
0051 name[3] = '\0';
0052 return true;
0053 }
0054 #endif
0055
0056 namespace rtems
0057 {
0058 namespace thread
0059 {
0060 void
0061 system_error_check(int ec, const char* what)
0062 {
0063 if (ec != 0) {
0064 throw std::system_error(ec, std::system_category(), what);
0065 }
0066 }
0067
0068 attributes::attributes()
0069 : priority(-1),
0070 stack_size(RTEMS_MINIMUM_STACK_SIZE),
0071 attr(sched_inherit),
0072 policy(sched_fifo)
0073 {
0074 update();
0075 }
0076
0077 attributes::attributes(const attributes& attr)
0078 : name(attr.name),
0079 priority(attr.priority),
0080 stack_size(attr.stack_size),
0081 scheduler(attr.scheduler),
0082 attr(attr.attr),
0083 policy(attr.policy)
0084 {
0085 }
0086
0087 void
0088 attributes::set_name(const std::string& name_)
0089 {
0090 name = name_;
0091 }
0092
0093 void
0094 attributes::set_name(const char* name_)
0095 {
0096 name = name_;
0097 }
0098
0099 const std::string&
0100 attributes::get_name() const
0101 {
0102 return name;
0103 }
0104
0105 void
0106 attributes::set_priority(int priority_)
0107 {
0108 priority = priority_;
0109 }
0110
0111 int
0112 attributes::get_priority() const
0113 {
0114 return priority;
0115 }
0116
0117 void
0118 attributes::set_stack_size(size_t size)
0119 {
0120 stack_size = size;
0121 }
0122
0123 size_t
0124 attributes::get_stack_size() const
0125 {
0126 return stack_size;
0127 }
0128
0129 void
0130 attributes::set_scheduler(const std::string& scheduler_)
0131 {
0132 scheduler = scheduler_;
0133 }
0134
0135 void
0136 attributes::set_scheduler(const char* scheduler_)
0137 {
0138 scheduler = scheduler_;
0139 }
0140
0141 const std::string&
0142 attributes::get_scheduler()
0143 {
0144 return scheduler;
0145 }
0146
0147 attributes::sched_attr
0148 attributes::get_scheduler_attr() const
0149 {
0150 return attr;
0151 }
0152
0153 void
0154 attributes::set_scheduler_policy(sched_policy policy_)
0155 {
0156 attr = sched_explicit;
0157 policy = policy_;
0158 }
0159
0160 attributes::sched_policy
0161 attributes::get_scheduler_policy() const
0162 {
0163 return policy;
0164 }
0165
0166 void
0167 attributes::commit()
0168 {
0169 pthread_t pid = ::pthread_self();
0170
0171 system_error_check(::pthread_setname_np(pid, name.c_str()),
0172 "getting name");
0173
0174 int spolicy;
0175 struct sched_param sched_param;
0176
0177 system_error_check(::pthread_getschedparam(::pthread_self(),
0178 &spolicy,
0179 &sched_param),
0180 "getting scheduler parameters");
0181
0182 switch (policy) {
0183 case sched_other:
0184 spolicy = SCHED_OTHER;
0185 break;
0186 case sched_fifo:
0187 spolicy = SCHED_FIFO;
0188 break;
0189 case sched_roundrobin:
0190 spolicy = SCHED_RR;
0191 break;
0192 case sched_sporadic:
0193 spolicy = SCHED_SPORADIC;
0194 break;
0195 default:
0196 system_error_check(EINVAL, "get scheduler policy");
0197 break;
0198 }
0199
0200 sched_param.sched_priority = priority;
0201
0202 system_error_check(::pthread_setschedparam(::pthread_self(),
0203 spolicy,
0204 &sched_param),
0205 "getting scheduler parameters");
0206
0207 if (!scheduler.empty()) {
0208 char sname[4] = { ' ', ' ', ' ', ' ' };
0209 for (size_t c = 0; c < sizeof(sname); ++c) {
0210 if (c >= scheduler.length()) {
0211 break;
0212 }
0213 sname[c] = scheduler[c];
0214 }
0215 rtems_name scheduler_name = rtems_build_name(sname[0],
0216 sname[1],
0217 sname[2],
0218 sname[3]);
0219 rtems_id scheduler_id;
0220 runtime_error_check(::rtems_scheduler_ident(scheduler_name,
0221 &scheduler_id),
0222 "get scheduler id");
0223
0224
0225
0226
0227 }
0228 }
0229
0230 void
0231 attributes::update()
0232 {
0233 char buf[32];
0234 system_error_check(::pthread_getname_np(::pthread_self(),
0235 buf,
0236 sizeof (buf)),
0237 "getting name");
0238 name = buf;
0239
0240 int spolicy;
0241 struct sched_param sched_param;
0242 system_error_check(::pthread_getschedparam(::pthread_self(),
0243 &spolicy,
0244 &sched_param),
0245 "getting scheduler parameters");
0246
0247 switch (spolicy) {
0248 case SCHED_OTHER:
0249 policy = sched_other;
0250 break;
0251 case SCHED_FIFO:
0252 policy = sched_fifo;
0253 break;
0254 case SCHED_RR:
0255 policy = sched_roundrobin;
0256 break;
0257 case SCHED_SPORADIC:
0258 policy = sched_sporadic;
0259 break;
0260 default:
0261 system_error_check(EINVAL, "get scheduler policy");
0262 break;
0263 }
0264 priority = sched_param.sched_priority;
0265
0266 pthread_attr_t pattr;
0267 system_error_check(::pthread_getattr_np(::pthread_self(), &pattr),
0268 "getting thread attributes");
0269 system_error_check(::pthread_attr_getstacksize(&pattr, &stack_size),
0270 "getting stack size");
0271 int inheritsched = 0;
0272 system_error_check(::pthread_attr_getinheritsched(&pattr, &inheritsched),
0273 "getting inherited sheduler attribute");
0274 switch (inheritsched) {
0275 case PTHREAD_INHERIT_SCHED:
0276 attr = sched_inherit;
0277 break;
0278 case PTHREAD_EXPLICIT_SCHED:
0279 attr = sched_explicit;
0280 break;
0281 default:
0282 system_error_check(EINVAL, "get scheduler attribute");
0283 break;
0284 }
0285
0286 rtems_id scheduler_id;
0287 runtime_error_check(::rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id));
0288 #if HAVE_GET_SCHEDULER_NAME
0289 char name[5];
0290 if (!get_scheduler_name(scheduler_id, &name[0])) {
0291 system_error_check(ENOENT, "get scheduler name");
0292 }
0293 scheduler = name;
0294 #endif
0295 }
0296
0297 attributes&
0298 attributes::operator=(const attributes& other)
0299 {
0300 name = other.name;
0301 priority = other.priority;
0302 stack_size = other.stack_size;
0303 attr = other.attr;
0304 policy = other.policy;
0305 return *this;
0306 }
0307
0308 bool
0309 attributes::operator==(const attributes& other) const
0310 {
0311 return
0312 name == other.name &&
0313 priority == other.priority &&
0314 stack_size == other.stack_size &&
0315 attr == other.attr &&
0316 policy == other.policy;
0317 }
0318
0319 void*
0320 thread_generic_entry(void* arg)
0321 {
0322 thread::state_ptr s{ static_cast<thread::state_base*>(arg) };
0323 try {
0324 s->run();
0325 } catch (...) {
0326 std::terminate();
0327 }
0328 return nullptr;
0329 }
0330
0331 thread&
0332 thread::operator=(thread&& thread_)
0333 {
0334 if (joinable()) {
0335 std::terminate();
0336 }
0337 swap(thread_);
0338 return *this;
0339 }
0340
0341 void
0342 thread::swap(thread& thread_) noexcept
0343 {
0344 std::swap(id_, thread_.id_);
0345 }
0346
0347 bool
0348 thread::joinable() const noexcept
0349 {
0350 return !(id_ == id());
0351 }
0352
0353 void
0354 thread::join()
0355 {
0356 if (!joinable()) {
0357 system_error_check(EINVAL, "join");
0358 }
0359 system_error_check(::pthread_join(id_.id_, nullptr), "join");
0360 id_ = id();
0361 }
0362
0363 void
0364 thread::detach()
0365 {
0366 if (!joinable()) {
0367 system_error_check(EINVAL, "detach");
0368 }
0369 system_error_check(::pthread_detach(id_.id_), "detach");
0370 id_ = id();
0371 }
0372
0373 thread::state_base::~state_base() = default;
0374
0375 void
0376 thread::start_thread(thread::state_ptr s)
0377 {
0378 const attributes attr = s->get_attributes();
0379
0380 pthread_attr_t pattr;
0381
0382 system_error_check(::pthread_attr_init(&pattr),
0383 "attribute init");
0384
0385 struct sched_param param;
0386 param.sched_priority = attr.get_priority();
0387 system_error_check(::pthread_attr_setschedparam(&pattr, ¶m),
0388 "set sched param");
0389
0390 int spolicy;
0391 switch (attr.get_scheduler_policy()) {
0392 case attributes::sched_other:
0393 spolicy = SCHED_OTHER;
0394 break;
0395 case attributes::sched_roundrobin:
0396 spolicy = SCHED_RR;
0397 break;
0398 case attributes::sched_sporadic:
0399 spolicy = SCHED_SPORADIC;
0400 break;
0401 default:
0402 spolicy = SCHED_FIFO;
0403 break;
0404 }
0405 system_error_check(::pthread_attr_setschedpolicy(&pattr, spolicy),
0406 "set scheduler policy");
0407
0408 if (attr.get_scheduler_attr() == attributes::sched_inherit) {
0409 ::pthread_attr_setinheritsched(&pattr, PTHREAD_INHERIT_SCHED);
0410 }
0411 else {
0412 ::pthread_attr_setinheritsched(&pattr, PTHREAD_EXPLICIT_SCHED);
0413 }
0414
0415 system_error_check(::pthread_attr_setstacksize(&pattr,
0416 attr.get_stack_size()),
0417 "set stack size");
0418
0419
0420
0421
0422
0423 system_error_check(::pthread_create(&id_.id_,
0424 &pattr,
0425 thread_generic_entry,
0426 s.get()),
0427 "create thread");
0428
0429 system_error_check(::pthread_setname_np(id_.id_,
0430 attr.get_name().c_str()),
0431 "setting thread name");
0432
0433 ::pthread_attr_destroy(&pattr);
0434
0435 s.release();
0436 };
0437 };
0438 };