mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
cpukit/librcxx: Add a C++ thread interface with attributes
This commit is contained in:
68
cpukit/include/rtems/error.hpp
Normal file
68
cpukit/include/rtems/error.hpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup RTEMSC++
|
||||||
|
*
|
||||||
|
* @brief RTEMS Error exception.
|
||||||
|
*
|
||||||
|
* Provide an error exception for RTEMS errors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(RTEMS_ERROR_HPP)
|
||||||
|
#define RTEMS_ERROR_HPP
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <rtems/error.h>
|
||||||
|
|
||||||
|
namespace rtems
|
||||||
|
{
|
||||||
|
class runtime_error :
|
||||||
|
public std::runtime_error
|
||||||
|
{
|
||||||
|
const rtems_status_code sc;
|
||||||
|
public:
|
||||||
|
runtime_error (const rtems_status_code sc);
|
||||||
|
runtime_error (const rtems_status_code sc, const std::string& what);
|
||||||
|
runtime_error (const rtems_status_code sc, const char* what);
|
||||||
|
~runtime_error ();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw a rtems::runtime_error exception if the RTEMS status code is
|
||||||
|
* not RTEMS_SUCCESSFUL.
|
||||||
|
*/
|
||||||
|
void runtime_error_check (const rtems_status_code sc);
|
||||||
|
void runtime_error_check (const rtems_status_code sc, const std::string& what);
|
||||||
|
void runtime_error_check (const rtems_status_code sc, const char* what);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
477
cpukit/include/rtems/thread.hpp
Normal file
477
cpukit/include/rtems/thread.hpp
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup RTEMSC++
|
||||||
|
*
|
||||||
|
* @brief C++ standard thread support with thread attribute control.
|
||||||
|
*
|
||||||
|
* Provide a way to create a thread in C++ with attributes that let
|
||||||
|
* you control the real-time embedded parameters need to run
|
||||||
|
* threads on RTEMS.
|
||||||
|
*
|
||||||
|
* The code requires the `-std=c++17` option to access `std::invoke()`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(RTEMS_THREAD_HPP)
|
||||||
|
#define RTEMS_THREAD_HPP
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace rtems
|
||||||
|
{
|
||||||
|
namespace thread
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Manage the attributes of a thread.
|
||||||
|
*/
|
||||||
|
class attributes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The scheduler attribute.
|
||||||
|
*/
|
||||||
|
enum sched_attr {
|
||||||
|
sched_inherit, /**< Inherit the scheduler attributes
|
||||||
|
* from the creating thread. */
|
||||||
|
sched_explicit /**< Explicitly set the scheduler to these
|
||||||
|
* attributes. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scheduler policies.
|
||||||
|
*/
|
||||||
|
enum sched_policy {
|
||||||
|
sched_other, /**< Other scheduler policy */
|
||||||
|
sched_fifo, /**< FIFO scheduler policy */
|
||||||
|
sched_roundrobin, /**< Round robin scheduler policy */
|
||||||
|
sched_sporadic /**< Sporadic scheduler policy */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a thread attributes object with the current settings of the
|
||||||
|
* executing thread. The stack size is set to the configured minimum
|
||||||
|
* stack size.
|
||||||
|
*/
|
||||||
|
attributes ();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy construct the thread attributes.
|
||||||
|
*
|
||||||
|
* @param attr The attributes to copy.
|
||||||
|
*/
|
||||||
|
attributes (const attributes& attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the name of the thread. The thread is a classic API thread and
|
||||||
|
* the name is only 4 characters.
|
||||||
|
*
|
||||||
|
* @param name The name as a string.
|
||||||
|
*/
|
||||||
|
void set_name (const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the name of the thread. The thread is a classic API thread and
|
||||||
|
* the name is only 4 characters.
|
||||||
|
*
|
||||||
|
* @param name The name as a string.
|
||||||
|
*/
|
||||||
|
void set_name (const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the thread.
|
||||||
|
*
|
||||||
|
* @retval const std::string& The name of the thread.
|
||||||
|
*/
|
||||||
|
const std::string& get_name () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the priority of the thread.
|
||||||
|
*
|
||||||
|
* @param priority The POSIX API priority of the thread.
|
||||||
|
*/
|
||||||
|
void set_priority (int priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the POSIX API priority of the thread.
|
||||||
|
*
|
||||||
|
* @retval int The POSIX API thread priority.
|
||||||
|
*/
|
||||||
|
int get_priority () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the stack size. If the size is less than the configured minimum
|
||||||
|
* the minimum value is used.
|
||||||
|
*
|
||||||
|
* @param size The stack size in bytes.
|
||||||
|
*/
|
||||||
|
void set_stack_size (size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the stack size.
|
||||||
|
*
|
||||||
|
* @retval size_t The stack size in bytes.
|
||||||
|
*/
|
||||||
|
size_t get_stack_size () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scheduler name. If not set no scheduler is set.
|
||||||
|
*
|
||||||
|
* @parrm scheduler The name of the scheduler.
|
||||||
|
*/
|
||||||
|
void set_scheduler (const std::string& scheduler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scheduler name. If not set no scheduler is set.
|
||||||
|
*/
|
||||||
|
void set_scheduler (const char* scheduler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get scheduler name.
|
||||||
|
*/
|
||||||
|
const std::string& get_scheduler ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attributes' scheduler attribute for the thread.
|
||||||
|
*
|
||||||
|
* @return sched_attr The attributes' scheduler attribute
|
||||||
|
*/
|
||||||
|
sched_attr get_scheduler_attr () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scheduler policy for the thread. This call sets the
|
||||||
|
* scheduler attribute to @ref sched_explicit.
|
||||||
|
*
|
||||||
|
* @param policy The scheduler policy.
|
||||||
|
*/
|
||||||
|
void set_scheduler_policy (sched_policy policy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the scheduler policy for the thread.
|
||||||
|
*/
|
||||||
|
sched_policy get_scheduler_policy () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit any changes to the executing thread.
|
||||||
|
*
|
||||||
|
* @note only the priority and attribute of a thread can be changed. The
|
||||||
|
* name and stack size are ignored.
|
||||||
|
*/
|
||||||
|
void commit ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the attribute values from the executing thread. The attributes
|
||||||
|
* are updated from the current thread when constructed and the values
|
||||||
|
* returned are those held since then. If another thread changes the
|
||||||
|
* attributes of the current thread those changes will not be seen until
|
||||||
|
* this method is called. Except for the name and stack size any local
|
||||||
|
* changes made will lost then the update call is made.
|
||||||
|
*/
|
||||||
|
void update ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy operator.
|
||||||
|
*/
|
||||||
|
attributes& operator= (const attributes& attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The comparison operator does not check the name or stack size
|
||||||
|
* of a thread.
|
||||||
|
*/
|
||||||
|
bool operator== (const attributes& attr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name; /**< Name of the thread */
|
||||||
|
int priority; /**< POSIX API priority */
|
||||||
|
size_t stack_size; /**< Stack size in bytes */
|
||||||
|
std::string scheduler; /**< Name of the scheduler */
|
||||||
|
sched_attr attr; /**< Scheduler's attribute */
|
||||||
|
sched_policy policy; /**< Scheduler's policy */
|
||||||
|
/* affinity, cpu set size is? */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a thread with thread attributes.
|
||||||
|
*
|
||||||
|
* Create a thread optionally with thread attributes. The usage of this
|
||||||
|
* class follows the C++ standard for std::thread. The standard support
|
||||||
|
* for creating a thread does not let you control the attributes of a
|
||||||
|
* thread and control is important in embedded real-time
|
||||||
|
* applications. This class lets you control a thread attributes and use
|
||||||
|
* the extensive an excellent thread support the C++ standard provides.
|
||||||
|
*
|
||||||
|
* There is no indication attribute support for threads will be added to
|
||||||
|
* the C++ standard and what it will look like. The support provided here
|
||||||
|
* is designed to make as little impact on a code base as possible. While
|
||||||
|
* the attributes supported are specific to RTEMS they are common to all
|
||||||
|
* embedded operating systems.
|
||||||
|
*
|
||||||
|
* The support provided here is specific to GCC due to the use of some
|
||||||
|
* non-standard interfaces to get the indices of the template argument
|
||||||
|
* pack in new thread's context. A standards only solution would be
|
||||||
|
* preferred.
|
||||||
|
*/
|
||||||
|
class thread
|
||||||
|
{
|
||||||
|
friend void* thread_generic_entry (void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base state class to interface to derived template of the thread
|
||||||
|
* state from the generic entry point for the thread.
|
||||||
|
*/
|
||||||
|
struct state_base
|
||||||
|
{
|
||||||
|
virtual ~state_base ();
|
||||||
|
virtual const attributes get_attributes () = 0;
|
||||||
|
virtual void run () = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state is passed to the new thread context as a unique
|
||||||
|
* pointer. This handles the hand over and clean up.
|
||||||
|
*/
|
||||||
|
using state_ptr = std::unique_ptr<state_base>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template check to see if the first argument of a thread is a set of
|
||||||
|
* attributes.
|
||||||
|
*/
|
||||||
|
template <typename A, class DecayA = typename std::decay<A>::type>
|
||||||
|
using enable_if_attributes = typename std::enable_if
|
||||||
|
<std::is_same<DecayA, attributes>::value>::type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need our own id type so the thread class can access the pthread
|
||||||
|
* handle to initialise it.
|
||||||
|
*/
|
||||||
|
class id {
|
||||||
|
public:
|
||||||
|
id () noexcept : id_ (0) { }
|
||||||
|
explicit id (pthread_t id_) : id_ (id_) { }
|
||||||
|
private:
|
||||||
|
pthread_t id_;
|
||||||
|
|
||||||
|
friend class thread;
|
||||||
|
friend bool operator== (thread::id l, thread::id r) noexcept;
|
||||||
|
|
||||||
|
template<class CharT, class Traits>
|
||||||
|
friend std::basic_ostream<CharT, Traits>&
|
||||||
|
operator<< (std::basic_ostream<CharT, Traits>& out, thread::id id_);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default thread constructions.
|
||||||
|
*/
|
||||||
|
thread () noexcept = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The std::thread equivalent constructor. The attributes will be the
|
||||||
|
* same as the executing thread with a default thread name and the
|
||||||
|
* configured minimum stack size.
|
||||||
|
*/
|
||||||
|
template<typename F, typename... Args>
|
||||||
|
explicit thread (F&& func, Args&&... args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a thread with the provided attributes. The entry point and
|
||||||
|
* optional arguments are the same as std::thread.
|
||||||
|
*/
|
||||||
|
template <typename A, typename F, typename ...Args,
|
||||||
|
class = enable_if_attributes<A>>
|
||||||
|
explicit thread (A&& attr, F&& func, Args&&... args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the thread id to this instance.
|
||||||
|
*/
|
||||||
|
thread& operator= (thread&& thread_);
|
||||||
|
|
||||||
|
void swap(thread& thread_) noexcept;
|
||||||
|
|
||||||
|
bool joinable() const noexcept;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constrain use. These are not available.
|
||||||
|
*/
|
||||||
|
thread (thread&) = delete;
|
||||||
|
thread (const thread&) = delete;
|
||||||
|
thread (const thread&&) = delete;
|
||||||
|
thread& operator= (const thread&) = delete;
|
||||||
|
|
||||||
|
std::thread::id get_id() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
id id_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke the thread's entry point with the parameter pack in the new
|
||||||
|
* thread's context. This object holds the parameters copied onto the
|
||||||
|
* new thread's stack making them available to entry point routine.
|
||||||
|
*/
|
||||||
|
template<typename Parms>
|
||||||
|
struct invoker {
|
||||||
|
Parms p;
|
||||||
|
|
||||||
|
template<size_t Index>
|
||||||
|
static std::__tuple_element_t<Index, Parms>&& declval ();
|
||||||
|
|
||||||
|
template<size_t... Ind>
|
||||||
|
auto invoke (std::_Index_tuple<Ind...>)
|
||||||
|
noexcept (noexcept (std::invoke (declval<Ind>()...)))
|
||||||
|
-> decltype (std::invoke (declval<Ind> ()...)) {
|
||||||
|
return std::invoke (std::get<Ind> (std::move (p))...);
|
||||||
|
}
|
||||||
|
|
||||||
|
using indices =
|
||||||
|
typename std::_Build_index_tuple<std::tuple_size<Parms>::value>::__type;
|
||||||
|
|
||||||
|
void run () {
|
||||||
|
invoke (indices ());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state holds the invoker with the parameters. The generic entry
|
||||||
|
* point calls the virtual methods to get the attributes and to run the
|
||||||
|
* new thread in the new thread's context.
|
||||||
|
*/
|
||||||
|
template<typename Invoker>
|
||||||
|
struct state : state_base {
|
||||||
|
const attributes attr;
|
||||||
|
Invoker i;
|
||||||
|
|
||||||
|
state (const attributes& attr, Invoker&& i)
|
||||||
|
: attr (attr),
|
||||||
|
i (std::forward<Invoker> (i)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributes get_attributes () override {
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run () override {
|
||||||
|
i.run ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the state. This dynamic memory is managed by the unique pointer
|
||||||
|
* and is passed to the generic thread entry point.
|
||||||
|
*/
|
||||||
|
template<typename Invoker>
|
||||||
|
static state_ptr
|
||||||
|
make_state (const attributes& attr, Invoker&& i) {
|
||||||
|
using state_impl = state<Invoker>;
|
||||||
|
return state_ptr{ new state_impl (attr, std::forward<Invoker> (i)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decay the parameters so they can be correctly packed into the
|
||||||
|
* parameter tuple.
|
||||||
|
*/
|
||||||
|
template<typename... T>
|
||||||
|
using decayed_tuple = std::tuple<typename std::decay<T>::type...>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the invoker with the parameters.
|
||||||
|
*/
|
||||||
|
template<typename F, typename... Args>
|
||||||
|
static invoker<decayed_tuple<F, Args...>>
|
||||||
|
make_invoker (F&& func, Args&&... args)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
decayed_tuple<F, Args...> {
|
||||||
|
std::forward<F> (func), std::forward<Args> (args)...
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and start the thread.
|
||||||
|
*/
|
||||||
|
void start_thread (state_ptr s);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline typename std::decay<T>::type
|
||||||
|
decay_copy (T&& t) {
|
||||||
|
return std::forward<T> (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F, typename... Args>
|
||||||
|
thread::thread (F&& func, Args&&... args)
|
||||||
|
: id_ (0) {
|
||||||
|
attributes attr;
|
||||||
|
start_thread (
|
||||||
|
make_state (attr,
|
||||||
|
make_invoker (decay_copy (std::forward<F> (func)),
|
||||||
|
decay_copy (std::forward<Args> (args))...))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename A, typename F, typename... Args,
|
||||||
|
class = thread::enable_if_attributes<A>>
|
||||||
|
thread::thread (A&& attr, F&& func, Args&&... args)
|
||||||
|
: id_ (0) {
|
||||||
|
start_thread (
|
||||||
|
make_state (attr,
|
||||||
|
make_invoker (decay_copy (std::forward<F> (func)),
|
||||||
|
decay_copy (std::forward<Args> (args))...))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::thread::id thread::get_id() const noexcept {
|
||||||
|
return std::thread::id (id_.id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator== (thread::id l, thread::id r) noexcept {
|
||||||
|
return l.id_ == r.id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator!= (thread::id l, thread::id r) noexcept {
|
||||||
|
return !(l == r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class C, class T>
|
||||||
|
inline std::basic_ostream<C, T>&
|
||||||
|
operator<< (std::basic_ostream<C, T>& out, thread::id id_) {
|
||||||
|
return out << std::thread::id (id_.id_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
76
cpukit/librtemscxx/error.cpp
Normal file
76
cpukit/librtemscxx/error.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtems/error.hpp>
|
||||||
|
|
||||||
|
namespace rtems
|
||||||
|
{
|
||||||
|
runtime_error::runtime_error (const rtems_status_code sc)
|
||||||
|
: std::runtime_error (::rtems_status_text (sc)),
|
||||||
|
sc (sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_error::runtime_error (const rtems_status_code sc,
|
||||||
|
const std::string& what)
|
||||||
|
: std::runtime_error (what + ": " + ::rtems_status_text (sc)),
|
||||||
|
sc (sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_error::runtime_error (const rtems_status_code sc,
|
||||||
|
const char* what)
|
||||||
|
: std::runtime_error (std::string (what) + ": " + ::rtems_status_text (sc)),
|
||||||
|
sc (sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_error::~runtime_error()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime_error_check (const rtems_status_code sc)
|
||||||
|
{
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
throw runtime_error (sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime_error_check (const rtems_status_code sc, const std::string& what)
|
||||||
|
{
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
throw runtime_error (sc, what);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime_error_check (const rtems_status_code sc, const char* what)
|
||||||
|
{
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
throw runtime_error (sc, what);
|
||||||
|
}
|
||||||
|
};
|
||||||
416
cpukit/librtemscxx/thread.cpp
Normal file
416
cpukit/librtemscxx/thread.cpp
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_GNU_SOURCE)
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include <rtems/error.hpp>
|
||||||
|
#include <rtems/thread.hpp>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
#if HAVE_GET_SCHEDULER_NAME
|
||||||
|
extern "C" bool get_scheduler_name (rtems_id sid, char* name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_GET_SCHEDULER_NAME
|
||||||
|
bool get_scheduler_name (rtems_id sid, char* name)
|
||||||
|
{
|
||||||
|
name[0] = 'N';
|
||||||
|
name[1] = 'O';
|
||||||
|
name[2] = 'P';
|
||||||
|
name[3] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace rtems
|
||||||
|
{
|
||||||
|
namespace thread
|
||||||
|
{
|
||||||
|
void
|
||||||
|
system_error_check (int ec, const char* what)
|
||||||
|
{
|
||||||
|
if (ec != 0)
|
||||||
|
throw std::system_error (ec, std::system_category(), what);
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes::attributes ()
|
||||||
|
: priority (-1),
|
||||||
|
stack_size (RTEMS_MINIMUM_STACK_SIZE),
|
||||||
|
attr (sched_inherit),
|
||||||
|
policy (sched_fifo)
|
||||||
|
{
|
||||||
|
update ();
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes::attributes (const attributes& attr)
|
||||||
|
: name (attr.name),
|
||||||
|
priority (attr.priority),
|
||||||
|
stack_size (attr.stack_size),
|
||||||
|
scheduler (attr.scheduler),
|
||||||
|
attr (attr.attr),
|
||||||
|
policy (attr.policy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_name (const std::string& name_)
|
||||||
|
{
|
||||||
|
name = name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_name (const char* name_)
|
||||||
|
{
|
||||||
|
name = name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string&
|
||||||
|
attributes::get_name () const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_priority (int priority_)
|
||||||
|
{
|
||||||
|
priority = priority_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
attributes::get_priority () const
|
||||||
|
{
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_stack_size(size_t size)
|
||||||
|
{
|
||||||
|
stack_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
attributes::get_stack_size () const
|
||||||
|
{
|
||||||
|
return stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_scheduler (const std::string& scheduler_)
|
||||||
|
{
|
||||||
|
scheduler = scheduler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_scheduler (const char* scheduler_)
|
||||||
|
{
|
||||||
|
scheduler = scheduler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string&
|
||||||
|
attributes::get_scheduler ()
|
||||||
|
{
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes::sched_attr
|
||||||
|
attributes::get_scheduler_attr () const
|
||||||
|
{
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::set_scheduler_policy (sched_policy policy_)
|
||||||
|
{
|
||||||
|
attr = sched_explicit;
|
||||||
|
policy = policy_;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes::sched_policy
|
||||||
|
attributes::get_scheduler_policy () const
|
||||||
|
{
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::commit ()
|
||||||
|
{
|
||||||
|
pthread_t pid = ::pthread_self ();
|
||||||
|
|
||||||
|
system_error_check (::pthread_setname_np (pid, name.c_str ()),
|
||||||
|
"getting name");
|
||||||
|
|
||||||
|
int spolicy;
|
||||||
|
struct sched_param sched_param;
|
||||||
|
|
||||||
|
system_error_check (::pthread_getschedparam (::pthread_self (),
|
||||||
|
&spolicy,
|
||||||
|
&sched_param),
|
||||||
|
"getting scheduler parameters");
|
||||||
|
|
||||||
|
switch (policy) {
|
||||||
|
case sched_other:
|
||||||
|
spolicy = SCHED_OTHER;
|
||||||
|
break;
|
||||||
|
case sched_fifo:
|
||||||
|
spolicy = SCHED_FIFO;
|
||||||
|
break;
|
||||||
|
case sched_roundrobin:
|
||||||
|
spolicy = SCHED_RR;
|
||||||
|
break;
|
||||||
|
case sched_sporadic:
|
||||||
|
spolicy = SCHED_SPORADIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
system_error_check (EINVAL, "get scheduler policy");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sched_param.sched_priority = priority;
|
||||||
|
|
||||||
|
system_error_check (::pthread_setschedparam (::pthread_self (),
|
||||||
|
spolicy,
|
||||||
|
&sched_param),
|
||||||
|
"getting scheduler parameters");
|
||||||
|
|
||||||
|
if (!scheduler.empty ()) {
|
||||||
|
char sname[4] = { ' ', ' ', ' ', ' ' };
|
||||||
|
for (size_t c = 0; c < sizeof (sname); ++c) {
|
||||||
|
if (c >= scheduler.length ())
|
||||||
|
break;
|
||||||
|
sname[c] = scheduler[c];
|
||||||
|
}
|
||||||
|
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_task_set_scheduler (RTEMS_SELF,
|
||||||
|
// scheduler_id,
|
||||||
|
// 1),
|
||||||
|
// "set scheduler id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attributes::update ()
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
system_error_check (::pthread_getname_np (::pthread_self (),
|
||||||
|
buf,
|
||||||
|
sizeof (buf)),
|
||||||
|
"getting name");
|
||||||
|
name = buf;
|
||||||
|
|
||||||
|
int spolicy;
|
||||||
|
struct sched_param sched_param;
|
||||||
|
system_error_check (::pthread_getschedparam (::pthread_self (),
|
||||||
|
&spolicy,
|
||||||
|
&sched_param),
|
||||||
|
"getting scheduler parameters");
|
||||||
|
|
||||||
|
switch (spolicy) {
|
||||||
|
case SCHED_OTHER:
|
||||||
|
policy = sched_other;
|
||||||
|
break;
|
||||||
|
case SCHED_FIFO:
|
||||||
|
policy = sched_fifo;
|
||||||
|
break;
|
||||||
|
case SCHED_RR:
|
||||||
|
policy = sched_roundrobin;
|
||||||
|
break;
|
||||||
|
case SCHED_SPORADIC:
|
||||||
|
policy = sched_sporadic;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
system_error_check (EINVAL, "get scheduler policy");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
int inheritsched = 0;
|
||||||
|
system_error_check (::pthread_attr_getinheritsched (&pattr, &inheritsched),
|
||||||
|
"getting inherited sheduler attribute");
|
||||||
|
switch (inheritsched) {
|
||||||
|
case PTHREAD_INHERIT_SCHED:
|
||||||
|
attr = sched_inherit;
|
||||||
|
break;
|
||||||
|
case PTHREAD_EXPLICIT_SCHED:
|
||||||
|
attr = sched_explicit;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
system_error_check (EINVAL, "get scheduler attribute");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_id scheduler_id;
|
||||||
|
runtime_error_check (::rtems_task_get_scheduler (RTEMS_SELF, &scheduler_id));
|
||||||
|
#if HAVE_GET_SCHEDULER_NAME
|
||||||
|
char name[5];
|
||||||
|
if (!get_scheduler_name (scheduler_id, &name[0]))
|
||||||
|
system_error_check (ENOENT, "get scheduler name");
|
||||||
|
scheduler = name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes&
|
||||||
|
attributes::operator= (const attributes& other)
|
||||||
|
{
|
||||||
|
name = other.name;
|
||||||
|
priority = other.priority;
|
||||||
|
stack_size = other.stack_size;
|
||||||
|
attr = other.attr;
|
||||||
|
policy = other.policy;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
attributes::operator== (const attributes& other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
name == other.name &&
|
||||||
|
priority == other.priority &&
|
||||||
|
stack_size == other.stack_size &&
|
||||||
|
attr == other.attr &&
|
||||||
|
policy == other.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
thread_generic_entry (void* arg)
|
||||||
|
{
|
||||||
|
thread::state_ptr s{ static_cast<thread::state_base*> (arg) };
|
||||||
|
try {
|
||||||
|
s->run ();
|
||||||
|
} catch (...) {
|
||||||
|
std::terminate ();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread&
|
||||||
|
thread::operator= (thread&& thread_)
|
||||||
|
{
|
||||||
|
if (joinable ())
|
||||||
|
std::terminate ();
|
||||||
|
swap(thread_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
thread::swap(thread& thread_) noexcept
|
||||||
|
{
|
||||||
|
std::swap(id_, thread_.id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
thread::joinable() const noexcept
|
||||||
|
{
|
||||||
|
return !(id_ == id());
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::state_base::~state_base () = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
thread::start_thread (thread::state_ptr s)
|
||||||
|
{
|
||||||
|
const attributes attr = s->get_attributes ();
|
||||||
|
|
||||||
|
pthread_attr_t pattr;
|
||||||
|
|
||||||
|
system_error_check (::pthread_attr_init (&pattr),
|
||||||
|
"attribute init");
|
||||||
|
|
||||||
|
system_error_check (::pthread_attr_setdetachstate (&pattr,
|
||||||
|
PTHREAD_CREATE_DETACHED),
|
||||||
|
"set detached state");
|
||||||
|
|
||||||
|
struct sched_param param;
|
||||||
|
param.sched_priority = attr.get_priority ();
|
||||||
|
system_error_check (::pthread_attr_setschedparam (&pattr, ¶m),
|
||||||
|
"set ");
|
||||||
|
|
||||||
|
int spolicy;
|
||||||
|
switch (attr.get_scheduler_policy ()) {
|
||||||
|
case attributes::sched_other:
|
||||||
|
spolicy = SCHED_OTHER;
|
||||||
|
break;
|
||||||
|
case attributes::sched_roundrobin:
|
||||||
|
spolicy = SCHED_RR;
|
||||||
|
break;
|
||||||
|
case attributes::sched_sporadic:
|
||||||
|
spolicy = SCHED_SPORADIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
spolicy = SCHED_FIFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
::pthread_attr_setinheritsched (&pattr, PTHREAD_EXPLICIT_SCHED);
|
||||||
|
|
||||||
|
system_error_check (::pthread_attr_setstacksize(&pattr,
|
||||||
|
attr.get_stack_size ()),
|
||||||
|
"set stack size");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_setname_np (id_.id_,
|
||||||
|
attr.get_name ().c_str ()),
|
||||||
|
"setting thread name");
|
||||||
|
|
||||||
|
::pthread_attr_destroy (&pattr);
|
||||||
|
|
||||||
|
s.release ();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -27,6 +27,8 @@ links:
|
|||||||
uid: libpppd
|
uid: libpppd
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
uid: librtemscpu
|
uid: librtemscpu
|
||||||
|
- role: build-dependency
|
||||||
|
uid: librtemscxx
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
uid: librtemsdfltcfg
|
uid: librtemsdfltcfg
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
|
|||||||
21
spec/build/cpukit/librtemscxx.yml
Normal file
21
spec/build/cpukit/librtemscxx.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
|
||||||
|
build-type: library
|
||||||
|
cflags: []
|
||||||
|
copyrights:
|
||||||
|
- Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
cppflags: []
|
||||||
|
cxxflags: [-std=c++17]
|
||||||
|
enabled-by: true
|
||||||
|
includes: []
|
||||||
|
install:
|
||||||
|
- destination: ${BSP_INCLUDEDIR}
|
||||||
|
source:
|
||||||
|
- cpukit/include/rtems/c++/error
|
||||||
|
- cpukit/include/rtems/c++/thread
|
||||||
|
install-path: ${BSP_LIBDIR}
|
||||||
|
links: []
|
||||||
|
source:
|
||||||
|
- cpukit/librtemscxx/error.cpp
|
||||||
|
- cpukit/librtemscxx/thread.cpp
|
||||||
|
target: rtemscxx
|
||||||
|
type: build
|
||||||
@@ -214,6 +214,8 @@ links:
|
|||||||
uid: pwdgrp02
|
uid: pwdgrp02
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
uid: rbheap01
|
uid: rbheap01
|
||||||
|
- role: build-dependency
|
||||||
|
uid: rcxx01
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
uid: read
|
uid: read
|
||||||
- role: build-dependency
|
- role: build-dependency
|
||||||
|
|||||||
22
spec/build/testsuites/libtests/rcxx01.yml
Normal file
22
spec/build/testsuites/libtests/rcxx01.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
|
||||||
|
build-type: test-program
|
||||||
|
cflags: []
|
||||||
|
copyrights:
|
||||||
|
- Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
cppflags: []
|
||||||
|
cxxflags: [-std=c++17]
|
||||||
|
enabled-by: true
|
||||||
|
features: c cxx cxxprogram
|
||||||
|
includes: []
|
||||||
|
ldflags: []
|
||||||
|
links: []
|
||||||
|
source:
|
||||||
|
- testsuites/libtests/rcxx01/init.c
|
||||||
|
- testsuites/libtests/rcxx01/thread.cpp
|
||||||
|
stlib: []
|
||||||
|
target: testsuites/libtests/rcxx01.exe
|
||||||
|
type: build
|
||||||
|
use-after: []
|
||||||
|
use-before:
|
||||||
|
- rtemsdefaultconfig
|
||||||
|
- rtemscxx
|
||||||
89
testsuites/libtests/rcxx01/init.c
Normal file
89
testsuites/libtests/rcxx01/init.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "tmacros.h"
|
||||||
|
|
||||||
|
const char rtems_test_name[] = "RCXX 1";
|
||||||
|
|
||||||
|
/* forward declarations to avoid warnings */
|
||||||
|
rtems_task Init(rtems_task_argument argument);
|
||||||
|
|
||||||
|
void rcxx_run_test(void);
|
||||||
|
|
||||||
|
rtems_task Init(
|
||||||
|
rtems_task_argument ignored
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TEST_BEGIN();
|
||||||
|
|
||||||
|
rcxx_run_test();
|
||||||
|
|
||||||
|
TEST_END();
|
||||||
|
rtems_test_exit( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* configuration information */
|
||||||
|
|
||||||
|
#include <rtems/serial_mouse.h>
|
||||||
|
|
||||||
|
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||||
|
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
|
||||||
|
|
||||||
|
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5
|
||||||
|
|
||||||
|
#define CONFIGURE_MEMORY_OVERHEAD (2024)
|
||||||
|
|
||||||
|
#define CONFIGURE_MAXIMUM_TASKS 1
|
||||||
|
#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
|
||||||
|
|
||||||
|
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
|
||||||
|
|
||||||
|
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||||
|
|
||||||
|
#define CONFIGURE_INIT_TASK_STACK_SIZE (10U * 1024U)
|
||||||
|
|
||||||
|
#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
|
||||||
|
|
||||||
|
#define CONFIGURE_INIT
|
||||||
|
|
||||||
|
#include <rtems/confdefs.h>
|
||||||
|
|
||||||
|
/* end of file */
|
||||||
16
testsuites/libtests/rcxx01/rcxx01.doc
Normal file
16
testsuites/libtests/rcxx01/rcxx01.doc
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2019 Chris Johns <chrisj@rtems.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
This file describes the directives and concepts tested by this test set.
|
||||||
|
|
||||||
|
test set name: rcxx01
|
||||||
|
|
||||||
|
directives:
|
||||||
|
|
||||||
|
rtems::thread::thread
|
||||||
|
rtems::thread::attributes
|
||||||
|
|
||||||
|
concepts:
|
||||||
|
|
||||||
|
+ Create a thread using the default method, ie like std::thread.
|
||||||
|
* Create a thread with changed attributes.
|
||||||
13
testsuites/libtests/rcxx01/rcxx01.scn
Normal file
13
testsuites/libtests/rcxx01/rcxx01.scn
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
*** BEGIN OF TEST RCXX 1 ***
|
||||||
|
*** TEST VERSION: 5.0.0.7ba04a62227286dcd3da20ea7319d9c64b8f5fd1
|
||||||
|
*** TEST STATE: EXPECTED-PASS
|
||||||
|
*** TEST BUILD:
|
||||||
|
*** TEST TOOLS: 7.5.0 20191114 (RTEMS 5, RSB ceb811fa19ddcfdd449a8da8f1107e6e592727b6, Newlib d14714c69)
|
||||||
|
Thread: start: default
|
||||||
|
1 D
|
||||||
|
Thread: start: attr
|
||||||
|
2 R
|
||||||
|
Thread: end: default
|
||||||
|
Thread: end: attr
|
||||||
|
|
||||||
|
*** END OF TEST RCXX 1 ***
|
||||||
110
testsuites/libtests/rcxx01/thread.cpp
Normal file
110
testsuites/libtests/rcxx01/thread.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Chris Johns (http://contemporary.software)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <rtems/thread.hpp>
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
extern "C" void rcxx_run_test(void);
|
||||||
|
|
||||||
|
struct test_thread
|
||||||
|
{
|
||||||
|
test_thread();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
bool running();
|
||||||
|
void body(const char* title, int i, char c);
|
||||||
|
|
||||||
|
rtems::thread::thread thread_default;
|
||||||
|
rtems::thread::thread thread_attr;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
|
bool finished;
|
||||||
|
};
|
||||||
|
|
||||||
|
test_thread::test_thread()
|
||||||
|
: finished(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_thread::start()
|
||||||
|
{
|
||||||
|
thread_default = rtems::thread::thread(&test_thread::body, this,
|
||||||
|
"default", 1, 'D');
|
||||||
|
|
||||||
|
rtems::thread::attributes attr;
|
||||||
|
|
||||||
|
attr.set_name("RTHREAD");
|
||||||
|
attr.set_priority(5);
|
||||||
|
attr.set_stack_size(32 * 1024);
|
||||||
|
|
||||||
|
thread_attr = rtems::thread::thread(attr, &test_thread::body, this,
|
||||||
|
"attr", 2, 'R');
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_thread::body(const char* title, int i, char c)
|
||||||
|
{
|
||||||
|
std::cout << "Thread: start: " << title << std::endl
|
||||||
|
<< ' ' << i << ' ' << c << std::endl;
|
||||||
|
|
||||||
|
size_t count = 5;
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
std::this_thread::sleep_for(1s);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Thread: end: " << title << std::endl;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_thread::running()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return finished == false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rcxx_run_test(void)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
test_thread tt;
|
||||||
|
tt.start();
|
||||||
|
while (tt.running())
|
||||||
|
std::this_thread::sleep_for(1s);
|
||||||
|
} catch (...) {
|
||||||
|
std::cout << "Thread: ouch" << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user