From 6269686dfbb2dd8da1556bafbc0241b29b647051 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Mon, 31 Mar 2025 13:25:07 +1100 Subject: [PATCH] rtemscxx: Support building on Unix This lets you develop unittests on Unix. --- cpukit/include/rtems/thread.hpp | 33 ++++++- cpukit/librtemscxx/thread.cpp | 148 ++++++++++++++++++++------------ 2 files changed, 121 insertions(+), 60 deletions(-) diff --git a/cpukit/include/rtems/thread.hpp b/cpukit/include/rtems/thread.hpp index faa7f2af51..559a3e0a32 100644 --- a/cpukit/include/rtems/thread.hpp +++ b/cpukit/include/rtems/thread.hpp @@ -362,17 +362,34 @@ namespace rtems Parms p; template - static std::__tuple_element_t&& declval(); + static std::tuple_element_t&& declval(); + + template struct _Index_tuple { }; + + template + struct _Build_index_tuple + { +#if __has_builtin(__make_integer_seq) + template + using _IdxTuple = _Index_tuple<_Indices...>; + + // Clang defines __make_integer_seq for this purpose. + using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; +#else + // For GCC and other compilers, use __integer_pack instead. + using __type = _Index_tuple<__integer_pack(_Num)...>; +#endif + }; template - auto invoke(std::_Index_tuple) + auto invoke(_Index_tuple) noexcept(noexcept(std::invoke(declval()...))) -> decltype(std::invoke(declval()...)) { return std::invoke(std::get(std::move(p))...); } using indices = - typename std::_Build_index_tuple::value>::__type; + typename _Build_index_tuple::value>::__type; void run() { invoke(indices()); @@ -453,7 +470,13 @@ namespace rtems } inline std::thread::id thread::get_id() const noexcept { +#ifdef __clang__ + /* clang does not allow construction of std::thread::id with + an id so fail this call */ + return std::thread::id(); +#else return std::thread::id(id_.id_); +#endif } inline bool @@ -469,7 +492,11 @@ namespace rtems template inline std::basic_ostream& operator<<(std::basic_ostream& out, thread::id id_) { +#ifdef __clang__ + return out << id_.id_; +#else return out << std::thread::id(id_.id_); +#endif } }; }; diff --git a/cpukit/librtemscxx/thread.cpp b/cpukit/librtemscxx/thread.cpp index 19df3bbf59..6ef492ac8b 100644 --- a/cpukit/librtemscxx/thread.cpp +++ b/cpukit/librtemscxx/thread.cpp @@ -36,7 +36,12 @@ #include +#ifdef __rtems__ #include +#define MINIMUM_STACK_SIZE RTEMS_MINIMUM_STACK_SIZE +#else /* __rtems__ */ +#define MINIMUM_STACK_SIZE (8 * 1024UL) +#endif /* __rtems__ */ #if HAVE_GET_SCHEDULER_NAME extern "C" bool get_scheduler_name(rtems_id sid, char* name); @@ -53,6 +58,17 @@ bool get_scheduler_name(rtems_id sid, char* name) } #endif +#ifdef __FreeBSD__ +#include +static inline int pthread_getattr_np(pthread_t p, pthread_attr_t *a) { + return ::pthread_attr_get_np(p, a); +} +#endif /* __FreeBSD__ */ + +#ifdef SCHED_SPORADIC +#define HAVE_SCHED_SPORADIC 1 +#endif /* SCHED_SPORADIC */ + namespace rtems { namespace thread @@ -67,7 +83,7 @@ namespace rtems attributes::attributes() : priority(-1), - stack_size(RTEMS_MINIMUM_STACK_SIZE), + stack_size(MINIMUM_STACK_SIZE), attr(sched_inherit), policy(sched_fifo) { @@ -168,16 +184,16 @@ namespace rtems { pthread_t pid = ::pthread_self(); - system_error_check(::pthread_setname_np(pid, name.c_str()), - "getting name"); + system_error_check( + ::pthread_setname_np(pid, name.c_str()), + "getting name"); - int spolicy; + int spolicy; struct sched_param sched_param; - system_error_check(::pthread_getschedparam(::pthread_self(), - &spolicy, - &sched_param), - "getting scheduler parameters"); + system_error_check( + ::pthread_getschedparam(pid, &spolicy, &sched_param), + "getting scheduler parameters"); switch (policy) { case sched_other: @@ -190,8 +206,10 @@ namespace rtems spolicy = SCHED_RR; break; case sched_sporadic: +#ifdef HAVE_SCHED_SPORADIC spolicy = SCHED_SPORADIC; break; +#endif /* HAVE_SCHED_SPORADIC */ default: system_error_check(EINVAL, "get scheduler policy"); break; @@ -199,10 +217,9 @@ namespace rtems sched_param.sched_priority = priority; - system_error_check(::pthread_setschedparam(::pthread_self(), - spolicy, - &sched_param), - "getting scheduler parameters"); + system_error_check( + ::pthread_setschedparam(pid, spolicy, &sched_param), + "getting scheduler parameters"); if (!scheduler.empty()) { char sname[4] = { ' ', ' ', ' ', ' ' }; @@ -212,37 +229,37 @@ namespace rtems } sname[c] = scheduler[c]; } - rtems_name scheduler_name = rtems_build_name(sname[0], - sname[1], - sname[2], - sname[3]); +#ifdef __rtems__ + rtems_name scheduler_name = rtems_build_name( + sname[0], sname[1], sname[2], sname[3]); rtems_id scheduler_id; - runtime_error_check(::rtems_scheduler_ident(scheduler_name, - &scheduler_id), - "get scheduler id"); + runtime_error_check( + ::rtems_scheduler_ident(scheduler_name, &scheduler_id), + "get scheduler id"); // runtime_error_check (::rtems_task_set_scheduler (RTEMS_SELF, // scheduler_id, // 1), // "set scheduler id"); +#endif /* __rtems__ */ } } void attributes::update() { - char buf[32]; - system_error_check(::pthread_getname_np(::pthread_self(), - buf, - sizeof (buf)), - "getting name"); + pthread_t pid = ::pthread_self(); + + char buf[64]; + system_error_check( + ::pthread_getname_np(pid, buf, sizeof (buf)), + "getting name"); name = buf; - int spolicy; + int spolicy; struct sched_param sched_param; - system_error_check(::pthread_getschedparam(::pthread_self(), - &spolicy, - &sched_param), - "getting scheduler parameters"); + system_error_check( + ::pthread_getschedparam(pid, &spolicy, &sched_param), + "getting scheduler parameters"); switch (spolicy) { case SCHED_OTHER: @@ -254,9 +271,11 @@ namespace rtems case SCHED_RR: policy = sched_roundrobin; break; +#ifdef HAVE_SCHED_SPORADIC case SCHED_SPORADIC: policy = sched_sporadic; break; +#endif /* HAVE_SCHED_SPORADIC */ default: system_error_check(EINVAL, "get scheduler policy"); break; @@ -264,13 +283,22 @@ namespace rtems priority = sched_param.sched_priority; pthread_attr_t pattr; - system_error_check(::pthread_getattr_np(::pthread_self(), &pattr), - "getting thread attributes"); - system_error_check(::pthread_attr_getstacksize(&pattr, &stack_size), - "getting stack size"); + system_error_check( + ::pthread_attr_init(&pattr), "attribute init"); + + system_error_check( + ::pthread_getattr_np(pid, &pattr), + "getting thread attributes"); + system_error_check( + ::pthread_attr_getstacksize(&pattr, &stack_size), + "getting stack size"); int inheritsched = 0; - system_error_check(::pthread_attr_getinheritsched(&pattr, &inheritsched), - "getting inherited sheduler attribute"); + system_error_check( + ::pthread_attr_getinheritsched(&pattr, &inheritsched), + "getting inherited scheduler attribute"); + + ::pthread_attr_destroy(&pattr); + switch (inheritsched) { case PTHREAD_INHERIT_SCHED: attr = sched_inherit; @@ -283,8 +311,11 @@ namespace rtems break; } +#ifdef __rtems__ rtems_id scheduler_id; - runtime_error_check(::rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id)); + runtime_error_check( + ::rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id)); +#endif /* __rtems__ */ #if HAVE_GET_SCHEDULER_NAME char name[5]; if (!get_scheduler_name(scheduler_id, &name[0])) { @@ -378,14 +409,8 @@ namespace rtems const attributes attr = s->get_attributes(); pthread_attr_t pattr; - - system_error_check(::pthread_attr_init(&pattr), - "attribute init"); - - struct sched_param param; - param.sched_priority = attr.get_priority(); - system_error_check(::pthread_attr_setschedparam(&pattr, ¶m), - "set sched param"); + system_error_check( + ::pthread_attr_init(&pattr), "attribute init"); int spolicy; switch (attr.get_scheduler_policy()) { @@ -396,14 +421,17 @@ namespace rtems spolicy = SCHED_RR; break; case attributes::sched_sporadic: +#ifdef HAVE_SCHED_SPORADIC spolicy = SCHED_SPORADIC; break; +#endif /* HAVE_SCHED_SPORADIC */ default: spolicy = SCHED_FIFO; break; } - system_error_check(::pthread_attr_setschedpolicy(&pattr, spolicy), - "set scheduler policy"); + system_error_check( + ::pthread_attr_setschedpolicy(&pattr, spolicy), + "set scheduler policy"); if (attr.get_scheduler_attr() == attributes::sched_inherit) { ::pthread_attr_setinheritsched(&pattr, PTHREAD_INHERIT_SCHED); @@ -412,23 +440,29 @@ namespace rtems ::pthread_attr_setinheritsched(&pattr, PTHREAD_EXPLICIT_SCHED); } - system_error_check(::pthread_attr_setstacksize(&pattr, - attr.get_stack_size()), - "set stack size"); +#ifndef __linux__ + struct sched_param param; + param.sched_priority = attr.get_priority(); + system_error_check( + ::pthread_attr_setschedparam(&pattr, ¶m), + "set sched param"); + + system_error_check( + ::pthread_attr_setstacksize(&pattr, attr.get_stack_size()), + "set stack size"); +#endif /* __linux__ */ /* * Hold the new thread in the state's run handler until the rest * of the thread is set up after the create call. */ - system_error_check(::pthread_create(&id_.id_, - &pattr, - thread_generic_entry, - s.get()), - "create thread"); + system_error_check( + ::pthread_create(&id_.id_, &pattr, thread_generic_entry, s.get()), + "create thread"); - system_error_check(::pthread_setname_np(id_.id_, - attr.get_name().c_str()), - "setting thread name"); + system_error_check( + ::pthread_setname_np(id_.id_, attr.get_name().c_str()), + "setting thread name"); ::pthread_attr_destroy(&pattr);