[PATCH v2] user: Add a Languages section

chrisj at rtems.org chrisj at rtems.org
Sun Oct 18 22:00:45 UTC 2020


From: Chris Johns <chrisj at rtems.org>

---
 user/index.rst           |   2 +
 user/languages/c.rst     |  18 +++
 user/languages/cpp.rst   | 312 +++++++++++++++++++++++++++++++++++++++
 user/languages/index.rst |  24 +++
 4 files changed, 356 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..cca0a4b
--- /dev/null
+++ b/user/languages/c.rst
@@ -0,0 +1,18 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. Copyright (C) 2020 Chris Johns <chrisj at rtems.org>
+
+.. index:: C
+.. index:: C Programming Language
+
+C
+=
+.. index:: C
+
+RTEMS supports the C programming language via the inherent C compiler
+support with the C Standard Library provided by newlib. The support
+language version is C99 and C11 including C11 threads. The RTEMS POSIX
+1003.1 Compliance Guide details the supported interfaces and standards
+the C Standard Library supports.
+
+TBD.
diff --git a/user/languages/cpp.rst b/user/languages/cpp.rst
new file mode 100644
index 0000000..f9e4cb9
--- /dev/null
+++ b/user/languages/cpp.rst
@@ -0,0 +1,312 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. Copyright (C) 2020 Chris Johns <chrisj at 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 provides a range of methods to atomically access 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 synchronization primitives 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
+minimize 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 attribute 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 initialise 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 reference 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 based on the POSIX standard. The
+policies are:
+
+``sched_other``
+  A CPU budget algorithm with time-slicing where the time-slice is reset.
+
+``sched_fifo``
+ A CPU budget algorithm with no time-slicing.
+
+``sched_roundrobin``
+  A CPU budget algorithm with time-slicing where the time-slice is exhausted.
+
+``sched_sporadic``
+  A CPU budget algorithm with a priority, 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 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 its
+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..3b262b5
--- /dev/null
+++ b/user/languages/index.rst
@@ -0,0 +1,24 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. Copyright (C) 2020 Chris Johns <chrisj at rtems.org>
+
+.. _Languages:
+
+Languages
+*********
+.. index:: Languages
+.. index:: Programming Languages
+
+This section discusses some of the languages you can use to develop
+RTEMS applications. The RTEMS Application Programming Interfaces (API)
+are specified as C language bindings but this does not limit the
+languages RTEMS supports.
+
+The languages listed in the section are supported and tested. Many
+others languages have been ported to RTEMS over the years and maybe
+available as 3rd party additions.
+
+.. toctree::
+
+   c
+   cpp
-- 
2.24.1



More information about the devel mailing list