<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Oct 9, 2020 at 10:26 AM Gedare Bloom <<a href="mailto:gedare@rtems.org">gedare@rtems.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, Oct 8, 2020 at 11:42 PM <<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>> wrote:<br>
><br>
> From: Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>><br>
><br>
> ---<br>
>  user/index.rst           |   2 +<br>
>  user/languages/c.rst     |  14 ++<br>
>  user/languages/cpp.rst   | 312 +++++++++++++++++++++++++++++++++++++++<br>
>  user/languages/index.rst |  21 +++<br>
>  4 files changed, 349 insertions(+)<br>
>  create mode 100644 user/languages/c.rst<br>
>  create mode 100644 user/languages/cpp.rst<br>
>  create mode 100644 user/languages/index.rst<br>
><br>
> diff --git a/user/index.rst b/user/index.rst<br>
> index a91aa55..32667f4 100644<br>
> --- a/user/index.rst<br>
> +++ b/user/index.rst<br>
> @@ -42,6 +42,8 @@ RTEMS User Manual (|version|).<br>
>      bld/index<br>
>      bsps/index<br>
><br>
> +    languages/index<br>
> +<br>
>      exe/index<br>
>      testing/index<br>
>      tracing/index<br>
> diff --git a/user/languages/c.rst b/user/languages/c.rst<br>
> new file mode 100644<br>
> index 0000000..c3965eb<br>
> --- /dev/null<br>
> +++ b/user/languages/c.rst<br>
> @@ -0,0 +1,14 @@<br>
> +.. SPDX-License-Identifier: CC-BY-SA-4.0<br>
> +<br>
> +.. Copyright (C) 2020 Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>><br>
> +<br></blockquote><div><br></div><div>Should there be a general introduction on the compilers we support</div><div>and that we inherently rely on them. This puts the context into what</div><div>do GCC and CLANG support and which compiler(s) are available</div><div>on your target architecture.</div><div><br></div><div>Also Ada should have a TBD section.</div><div><br></div><div>If you can build Fortran with the RSB, it also needs a TBD section.</div><div>Surprising though it may be, it does work. :)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +.. index:: C<br>
> +.. index:: C Programming Language<br>
> +<br>
> +C<br>
> +=<br>
> +.. index:: C<br>
> +<br>
> +RTEMS supports the C programming language.<br>
> +<br>
> +TBD.<br></blockquote><div><br></div><div>Obviously TBD but supported via the inherent compiler support</div><div>with the C Standard Library provided by newlib. Could reference</div><div>the POSIX Compliance Guide section on the C Standard Library.</div><div><br></div><div>Support should be primarily for C99 and C11 including C11 threads.</div><div>Don't C11 thread also map to pthreads? </div><div><br></div><div>There is a C11 threads example in rtems-examples.</div><div><br></div><div>Disclaimer: C11 threads are a terrible API. </div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> diff --git a/user/languages/cpp.rst b/user/languages/cpp.rst<br>
> new file mode 100644<br>
> index 0000000..8a8cb86<br>
> --- /dev/null<br>
> +++ b/user/languages/cpp.rst<br>
> @@ -0,0 +1,312 @@<br>
> +.. SPDX-License-Identifier: CC-BY-SA-4.0<br>
> +<br>
> +.. Copyright (C) 2020 Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>><br>
> +<br>
> +.. index:: C++<br>
> +.. index:: C++ Programming Language<br>
> +<br>
> +C++<br>
> +===<br>
> +.. index:: C++<br>
> +<br>
> +RTEMS supports the C++ programming language and its standard library. The<br>
> +supported language versions are C++11, C++14, and C++17.<br>
<br>
I'm curious, will C++98/C++03 compliant code work? I admit to being<br>
completely out of touch with the C++ standard evolution.<br></blockquote><div><br></div><div>Yes.  The FACE Conformance Test Suite has been run against our C++03</div><div>support with no issues. GCC and its C++ Library are the magic here.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +<br>
> +The C++ standard library provides a rich set of interfaces to support<br>
> +multi-threaded programming. The Thread support library provides<br>
> +``std::lock_guard`` as a means to manage ``std::mutex`` or similar objects<br>
> +within a code block while execution remains within that block. The<br>
> +``std::promise`` and ``std::future`` supports provides a controlled means for<br>
> +threads to end, clean-up and return a status value of some type. The Atomic<br>
> +operations library provdes a range of methods to atomically acess data as well<br>
provides<br>
access<br>
<br>
> +as establish inter-thread synchronization and order non-atomic memory<br>
> +accesses.<br>
> +<br>
> +The Thread support library maps to the RTEMS POSIX ``pthread`` interface and<br>
> +the various sychronisation primatives such as mutual exclusion, condition<br>
primitives<br></blockquote><div><br></div><div>synchronization</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +variables, and futures map to the high performance self-contained RTEMS<br>
> +interface. These objects have a fast execution profile and their storage is<br>
> +self-contained which means it does not have to be accounted for in the<br>
> +configuration and work-space settings. C++ applications do not need to be<br>
> +concerned about the number of locks being used and can implement fine grain<br>
> +locking protocols.<br>
> +<br>
> +RTEMS Threads<br>
> +-------------<br>
> +<br>
> +RTEMS provides an alternative Thread interface that lets you specify the<br>
> +attributes of a thread when it is constructed. This is an extension to the<br>
> +standard and is not based on any current or pending standards efforts. The<br>
> +goal is to make the interface as close as possible to the existing standard to<br>
> +minimise the impact on code being ported to RTEMS.<br>
> +<br>
> +The following compiler option must be used as the implementation uses the<br>
> +``std::invoke`` call which is only available with C++17:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   --std=c++17<br>
> +<br>
> +The standard Thread support library specifies the thread constructor as:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   template< class Function, class... Args ><br>
> +   explicit thread( Function&& f, Args&&... args );<br>
> +<br>
> +A thread constructed using this interface will have a default set of initial<br>
> +values. An important atribute of a thread is the stack size and this cannot be<br>
attribute<br>
<br>
> +specified or altered with this interface. On Unix systems virtual memory can<br>
> +be used to manage a thread's stack size and stack handling is more complex<br>
> +when security is considered so manually controlling the stack size of a thread<br>
> +is not needed or wanted.<br>
> +<br>
> +Attributes<br>
> +^^^^^^^^^^<br>
> +<br>
> +The ``rtems::thread::attributes`` class provides an interface to control the<br>
> +various attributes a thread has. The header file is:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   #include <rtems/thread.hpp><br>
> +<br>
> +The default constructor initialises the attributes to the executing thread's<br>
> +settings and the stack size is set to the configured minimum. You can then<br>
> +alter the attributes to match the requirements of the new thread. It is easy<br>
> +to set a name, stack size and priority:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   rtems::thread::attribute attr;<br>
> +   attr.set_name("blue");<br>
> +   attr.set_stack_size(16 * 1024);<br>
> +   attr.set_priority(attr.get_priority() + 1);<br>
> +<br>
> +The ``update()`` method will read the attributes of the currently executing<br>
> +thread and update the attribute instance making the call. The stack size is<br>
> +not read and updated, there is no public interface in RTEMS to obtain the<br>
comma splice, add a conjunction. I don't know if this should be<br>
"because there is no"?<br>
<br>
> +executing thread's stack size.<br>
> +<br>
> +An attribute object can be used to start a number of threads. The thread does<br>
> +not referenced the attribute object once running.<br>
reference<br>
<br>
> +<br>
> +An attribute object can be used to alter an attribute of a thread after it has<br>
> +started by calling the ``commit()`` method. The ``commit()`` method does not<br>
> +change the name or stack size of the executing thread.<br>
> +<br>
> +The attribute controls the scheduler policy, this is based on the POSIX<br>
"policy based" (delete ", this is")<br>
<br>
> +standard. The policies are:<br>
> +<br>
> +``sched_other``<br>
> +  A CPU budget algorthim with timeslicing where the timeslice is reset.<br>
s/algorthim/algorithm<br>
<br>
> +<br>
> +``sched_fifo``<br>
> + A CPU budget algorthim with no timeslicing.<br>
s/algorthim/algorithm<br>
<br>
> +<br>
> +``sched_roundrobin``<br>
> +  A CPU budget algorthim with timeslicing where the timeslice is exhausted.<br>
s/algorthim/algorithm<br>
<br>
> +<br>
> +``sched_sporadic``<br>
> +  A CPU budget algorthim with a priorty, low priority and a replenish period.<br>
s/algorthim/algorithm<br>
s/priorty/priority<br>
<br>
> +<br>
> +Thread<br>
> +^^^^^^<br>
> +<br>
> +The ``rtems::thread::thread`` class provides a thread interface to start a new<br>
> +thread executing using the provided attributes. The header file is:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   #include <rtems/thread.hpp><br>
> +<br>
> +The ``thread`` provides the same constructor as the C++ standard's Thread<br>
> +support library:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   template<typename F, typename... Args><br>
> +   explicit thread (F&& func, Args&&... args);<br>
> +<br>
> +A thread can be run using the default parameters:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   #include <chrono><br>
> +   #include <iostream><br>
> +<br>
> +   #include <rtems/thread.hpp><br>
> +<br>
> +   static void wait_for(size_t seconds)<br>
> +   {<br>
> +     while (seconds--) {<br>
> +       std::this_thread::sleep_for(std::chrono::seconds(1));<br>
> +       std::cout << "Seconds: " << seconds << std::endl;<br>
> +     }<br>
> +   }<br>
> +<br>
> +   void example_1()<br>
> +   {<br>
> +     std::cout << "Start example 1" << std::endl;<br>
> +<br>
> +     rtems::thread::thread t(wait_for, 5);<br>
> +     t.join();<br>
> +<br>
> +     std::cout << "End example 1" << std::endl;<br>
> +   }<br>
> +<br>
> +The ``thread`` provides a way to construct a thread with attributes:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   template <typename A, typename F, typename ...Args,<br>
> +             class = enable_if_attributes<A>><br>
> +   explicit thread (A&& attr, F&& func, Args&&... args);<br>
> +<br>
> +To create threads with different names and priorities use the ``attribute``<br>
> +class and pass it to the ``thread`` class when constructing:<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   #include <chrono><br>
> +   #include <iostream><br>
> +<br>
> +   #include <rtems/thread.hpp><br>
> +<br>
> +   static void wait_for(std::string me, size_t seconds, size_t announce)<br>
> +   {<br>
> +     size_t count = 0;<br>
> +     while (count < seconds) {<br>
> +       std::this_thread::sleep_for(std::chrono::seconds(1));<br>
> +       if ((count % announce) == 0)<br>
> +         std::cout << me << ": " << count << std::endl;<br>
> +       count++;<br>
> +     }<br>
> +   }<br>
> +<br>
> +   void example_2()<br>
> +   {<br>
> +     std::cout << "Start example 2" << std::endl;<br>
> +<br>
> +     rtems::thread::attributes attr;<br>
> +     attr.set_stack_size(16 * 1024);<br>
> +<br>
> +     attr.set_priority(100);<br>
> +     attr.set_name("T1");<br>
> +     rtems::thread::thread t1(attr, wait_for, "T1", 10, 1);<br>
> +<br>
> +     attr.set_priority(101);<br>
> +     attr.set_name("T2");<br>
> +     rtems::thread::thread t2(attr, wait_for, "T2", 10, 2);<br>
> +<br>
> +     attr.set_priority(attr.get_priority());<br>
> +     attr.set_name("T3");<br>
> +     rtems::thread::thread t3(attr, wait_for, "T3", 15, 3);<br>
> +<br>
> +     t1.join();<br>
> +     t2.join();<br>
> +     t3.join();<br>
> +<br>
> +     std::cout << "End example 2" << std::endl;<br>
> +   }<br>
> +<br>
> +A more powerful example shows the encapsulation of threads in a class or<br>
> +structure to provide a concurrent interface. The example uses a thread in a<br>
> +class to count seconds. The example shows the use of atomics and a mutex to<br>
> +access to some elements in the class sequentially:<br>
delete 'to' -> read as "mutex to access some"<br>
<br>
> +<br>
> +.. code-block:: c++<br>
> +<br>
> +   #include <atomic><br>
> +   #include <chrono><br>
> +   #include <iostream><br>
> +   #include <mutex><br>
> +<br>
> +   #include <rtems/thread.hpp><br>
> +<br>
> +   class ticker<br>
> +   {<br>
> +     public:<br>
> +       ticker();<br>
> +<br>
> +       void start(const size_t life_time);<br>
> +       bool finished();<br>
> +<br>
> +       size_t seconds();<br>
> +<br>
> +     private:<br>
> +       void timer(const size_t life_time);<br>
> +<br>
> +       rtems::thread::thread tocker;<br>
> +       std::mutex            lock;<br>
> +       std::atomic<bool>     done;<br>
> +       bool                  running;<br>
> +       std::atomic<size_t>   the_seconds;<br>
> +   };<br>
> +<br>
> +   ticker::ticker()<br>
> +     : done(false),<br>
> +       running(false),<br>
> +       the_seconds(0)<br>
> +   {<br>
> +   }<br>
> +<br>
> +   void ticker::start(const size_t life_time)<br>
> +   {<br>
> +     std::lock_guard<std::mutex> guard(lock);<br>
> +     if (!running) {<br>
> +       rtems::thread::attributes attr;<br>
> +       attr.set_name("CLCK");<br>
> +       attr.set_stack_size(8 * 1024);<br>
> +       attr.set_priority(10);<br>
> +       running = true;<br>
> +       tocker = rtems::thread::thread(attr, &ticker::timer, this, life_time);<br>
> +     }<br>
> +   }<br>
> +<br>
> +   bool ticker::finished()<br>
> +   {<br>
> +     return done.load();<br>
> +   }<br>
> +<br>
> +   size_t ticker::seconds()<br>
> +   {<br>
> +     return the_seconds.load();<br>
> +   }<br>
> +<br>
> +   void ticker::timer(const size_t life_time)<br>
> +   {<br>
> +     while (the_seconds.load() < life_time) {<br>
> +       std::this_thread::sleep_for(std::chrono::seconds(1));<br>
> +       the_seconds++;<br>
> +     }<br>
> +     done = true;<br>
> +     std::lock_guard<std::mutex> guard(lock);<br>
> +     running = false;<br>
> +   }<br>
> +<br>
> +   void example_3()<br>
> +   {<br>
> +     std::cout << "Start example 3" << std::endl;<br>
> +<br>
> +     ticker my_ticker;<br>
> +<br>
> +     my_ticker.start(5);<br>
> +<br>
> +     while (!my_ticker.finished()) {<br>
> +       std::this_thread::sleep_for(std::chrono::seconds(2));<br>
> +       std::cout << "Ticker is " << my_ticker.seconds() << std::endl;<br>
> +     }<br>
> +<br>
> +     std::cout << "End example 3" << std::endl;<br>
> +   }<br>
> +<br>
> +The thread object's constructor provides the arguments to the new thread. The<br>
> +first argument is the ``this`` pointer and that is required because the class<br>
> +method is not static. The remaining arguments are optional and they only need<br>
> +to match the signature of the method being used as the thread. In the example<br>
> +the value passed to the ``start`` method is passed to the thread's body by it<br>
s/it/its<br>
<br>
> +arguments. Note, the arguments are copied so do not reference or use<br>
> +references to local variables held in the context of the constructing<br>
> +thread. If passing pointers wrap them in a ``std::unique_ptr`` or<br>
> +``std::shared_ptr`` object.<br>
> diff --git a/user/languages/index.rst b/user/languages/index.rst<br>
> new file mode 100644<br>
> index 0000000..f27e324<br>
> --- /dev/null<br>
> +++ b/user/languages/index.rst<br>
> @@ -0,0 +1,21 @@<br>
> +.. SPDX-License-Identifier: CC-BY-SA-4.0<br>
> +<br>
> +.. Copyright (C) 2020 Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>><br>
> +<br>
> +.. _Languages:<br>
> +<br>
> +Languages<br>
> +*********<br>
> +.. index:: Languages<br>
> +.. index:: Programming Languages<br>
> +<br>
> +This section discusses the languages you can use to develop RTEMS<br>
> +applications with. The RTEMS Application Programming Interfaces (API)<br>
delete " with"<br>
<br>
> +are specified a C language bindings but this does not limit the<br>
s/a/as<br>
<br>
> +languages RTEMS supports.<br>
> +<br>
> +.. toctree::<br>
> +<br>
> +   c<br>
> +   cpp<br>
> +   ada<br>
<br>
There are many other languages that are (suspected to be) working.<br>
java, go, lua, ... Maybe this section needs to be either expanded with<br>
all the languages we have seen used, or the language needs to be made<br>
more vague to imply that we support the bindings for c/c++/ada and<br>
that other languages can be supported?<br>
<br>
> --<br>
> 2.24.1<br>
><br>
> _______________________________________________<br>
> devel mailing list<br>
> <a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
> <a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div></div>