From: Chris Johns <chr...@rtems.org> --- user/index.rst | 2 + user/languages/c.rst | 14 ++ user/languages/cpp.rst | 312 +++++++++++++++++++++++++++++++++++++++ user/languages/index.rst | 21 +++ 4 files changed, 349 insertions(+) create mode 100644 user/languages/c.rst create mode 100644 user/languages/cpp.rst create mode 100644 user/languages/index.rst
diff --git a/user/index.rst b/user/index.rst index a91aa55..32667f4 100644 --- a/user/index.rst +++ b/user/index.rst @@ -42,6 +42,8 @@ RTEMS User Manual (|version|). bld/index bsps/index + languages/index + exe/index testing/index tracing/index diff --git a/user/languages/c.rst b/user/languages/c.rst new file mode 100644 index 0000000..c3965eb --- /dev/null +++ b/user/languages/c.rst @@ -0,0 +1,14 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2020 Chris Johns <chr...@rtems.org> + +.. index:: C +.. index:: C Programming Language + +C += +.. index:: C + +RTEMS supports the C programming language. + +TBD. diff --git a/user/languages/cpp.rst b/user/languages/cpp.rst new file mode 100644 index 0000000..8a8cb86 --- /dev/null +++ b/user/languages/cpp.rst @@ -0,0 +1,312 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2020 Chris Johns <chr...@rtems.org> + +.. index:: C++ +.. index:: C++ Programming Language + +C++ +=== +.. index:: C++ + +RTEMS supports the C++ programming language and its standard library. The +supported language versions are C++11, C++14, and C++17. + +The C++ standard library provides a rich set of interfaces to support +multi-threaded programming. The Thread support library provides +``std::lock_guard`` as a means to manage ``std::mutex`` or similar objects +within a code block while execution remains within that block. The +``std::promise`` and ``std::future`` supports provides a controlled means for +threads to end, clean-up and return a status value of some type. The Atomic +operations library provdes a range of methods to atomically acess data as well +as establish inter-thread synchronization and order non-atomic memory +accesses. + +The Thread support library maps to the RTEMS POSIX ``pthread`` interface and +the various sychronisation primatives such as mutual exclusion, condition +variables, and futures map to the high performance self-contained RTEMS +interface. These objects have a fast execution profile and their storage is +self-contained which means it does not have to be accounted for in the +configuration and work-space settings. C++ applications do not need to be +concerned about the number of locks being used and can implement fine grain +locking protocols. + +RTEMS Threads +------------- + +RTEMS provides an alternative Thread interface that lets you specify the +attributes of a thread when it is constructed. This is an extension to the +standard and is not based on any current or pending standards efforts. The +goal is to make the interface as close as possible to the existing standard to +minimise the impact on code being ported to RTEMS. + +The following compiler option must be used as the implementation uses the +``std::invoke`` call which is only available with C++17: + +.. code-block:: c++ + + --std=c++17 + +The standard Thread support library specifies the thread constructor as: + +.. code-block:: c++ + + template< class Function, class... Args > + explicit thread( Function&& f, Args&&... args ); + +A thread constructed using this interface will have a default set of initial +values. An important atribute of a thread is the stack size and this cannot be +specified or altered with this interface. On Unix systems virtual memory can +be used to manage a thread's stack size and stack handling is more complex +when security is considered so manually controlling the stack size of a thread +is not needed or wanted. + +Attributes +^^^^^^^^^^ + +The ``rtems::thread::attributes`` class provides an interface to control the +various attributes a thread has. The header file is: + +.. code-block:: c++ + + #include <rtems/thread.hpp> + +The default constructor initialises the attributes to the executing thread's +settings and the stack size is set to the configured minimum. You can then +alter the attributes to match the requirements of the new thread. It is easy +to set a name, stack size and priority: + +.. code-block:: c++ + + rtems::thread::attribute attr; + attr.set_name("blue"); + attr.set_stack_size(16 * 1024); + attr.set_priority(attr.get_priority() + 1); + +The ``update()`` method will read the attributes of the currently executing +thread and update the attribute instance making the call. The stack size is +not read and updated, there is no public interface in RTEMS to obtain the +executing thread's stack size. + +An attribute object can be used to start a number of threads. The thread does +not referenced the attribute object once running. + +An attribute object can be used to alter an attribute of a thread after it has +started by calling the ``commit()`` method. The ``commit()`` method does not +change the name or stack size of the executing thread. + +The attribute controls the scheduler policy, this is based on the POSIX +standard. The policies are: + +``sched_other`` + A CPU budget algorthim with timeslicing where the timeslice is reset. + +``sched_fifo`` + A CPU budget algorthim with no timeslicing. + +``sched_roundrobin`` + A CPU budget algorthim with timeslicing where the timeslice is exhausted. + +``sched_sporadic`` + A CPU budget algorthim with a priorty, low priority and a replenish period. + +Thread +^^^^^^ + +The ``rtems::thread::thread`` class provides a thread interface to start a new +thread executing using the provided attributes. The header file is: + +.. code-block:: c++ + + #include <rtems/thread.hpp> + +The ``thread`` provides the same constructor as the C++ standard's Thread +support library: + +.. code-block:: c++ + + template<typename F, typename... Args> + explicit thread (F&& func, Args&&... args); + +A thread can be run using the default parameters: + +.. code-block:: c++ + + #include <chrono> + #include <iostream> + + #include <rtems/thread.hpp> + + static void wait_for(size_t seconds) + { + while (seconds--) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "Seconds: " << seconds << std::endl; + } + } + + void example_1() + { + std::cout << "Start example 1" << std::endl; + + rtems::thread::thread t(wait_for, 5); + t.join(); + + std::cout << "End example 1" << std::endl; + } + +The ``thread`` provides a way to construct a thread with attributes: + +.. code-block:: c++ + + template <typename A, typename F, typename ...Args, + class = enable_if_attributes<A>> + explicit thread (A&& attr, F&& func, Args&&... args); + +To create threads with different names and priorities use the ``attribute`` +class and pass it to the ``thread`` class when constructing: + +.. code-block:: c++ + + #include <chrono> + #include <iostream> + + #include <rtems/thread.hpp> + + static void wait_for(std::string me, size_t seconds, size_t announce) + { + size_t count = 0; + while (count < seconds) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + if ((count % announce) == 0) + std::cout << me << ": " << count << std::endl; + count++; + } + } + + void example_2() + { + std::cout << "Start example 2" << std::endl; + + rtems::thread::attributes attr; + attr.set_stack_size(16 * 1024); + + attr.set_priority(100); + attr.set_name("T1"); + rtems::thread::thread t1(attr, wait_for, "T1", 10, 1); + + attr.set_priority(101); + attr.set_name("T2"); + rtems::thread::thread t2(attr, wait_for, "T2", 10, 2); + + attr.set_priority(attr.get_priority()); + attr.set_name("T3"); + rtems::thread::thread t3(attr, wait_for, "T3", 15, 3); + + t1.join(); + t2.join(); + t3.join(); + + std::cout << "End example 2" << std::endl; + } + +A more powerful example shows the encapsulation of threads in a class or +structure to provide a concurrent interface. The example uses a thread in a +class to count seconds. The example shows the use of atomics and a mutex to +access to some elements in the class sequentially: + +.. code-block:: c++ + + #include <atomic> + #include <chrono> + #include <iostream> + #include <mutex> + + #include <rtems/thread.hpp> + + class ticker + { + public: + ticker(); + + void start(const size_t life_time); + bool finished(); + + size_t seconds(); + + private: + void timer(const size_t life_time); + + rtems::thread::thread tocker; + std::mutex lock; + std::atomic<bool> done; + bool running; + std::atomic<size_t> the_seconds; + }; + + ticker::ticker() + : done(false), + running(false), + the_seconds(0) + { + } + + void ticker::start(const size_t life_time) + { + std::lock_guard<std::mutex> guard(lock); + if (!running) { + rtems::thread::attributes attr; + attr.set_name("CLCK"); + attr.set_stack_size(8 * 1024); + attr.set_priority(10); + running = true; + tocker = rtems::thread::thread(attr, &ticker::timer, this, life_time); + } + } + + bool ticker::finished() + { + return done.load(); + } + + size_t ticker::seconds() + { + return the_seconds.load(); + } + + void ticker::timer(const size_t life_time) + { + while (the_seconds.load() < life_time) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + the_seconds++; + } + done = true; + std::lock_guard<std::mutex> guard(lock); + running = false; + } + + void example_3() + { + std::cout << "Start example 3" << std::endl; + + ticker my_ticker; + + my_ticker.start(5); + + while (!my_ticker.finished()) { + std::this_thread::sleep_for(std::chrono::seconds(2)); + std::cout << "Ticker is " << my_ticker.seconds() << std::endl; + } + + std::cout << "End example 3" << std::endl; + } + +The thread object's constructor provides the arguments to the new thread. The +first argument is the ``this`` pointer and that is required because the class +method is not static. The remaining arguments are optional and they only need +to match the signature of the method being used as the thread. In the example +the value passed to the ``start`` method is passed to the thread's body by it +arguments. Note, the arguments are copied so do not reference or use +references to local variables held in the context of the constructing +thread. If passing pointers wrap them in a ``std::unique_ptr`` or +``std::shared_ptr`` object. diff --git a/user/languages/index.rst b/user/languages/index.rst new file mode 100644 index 0000000..f27e324 --- /dev/null +++ b/user/languages/index.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +.. Copyright (C) 2020 Chris Johns <chr...@rtems.org> + +.. _Languages: + +Languages +********* +.. index:: Languages +.. index:: Programming Languages + +This section discusses the languages you can use to develop RTEMS +applications with. The RTEMS Application Programming Interfaces (API) +are specified a C language bindings but this does not limit the +languages RTEMS supports. + +.. toctree:: + + c + cpp + ada -- 2.24.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel