On Fri, Oct 9, 2020 at 9:38 AM Joel Sherrill <j...@rtems.org> wrote: > > > > On Fri, Oct 9, 2020 at 10:26 AM Gedare Bloom <ged...@rtems.org> wrote: >> >> On Thu, Oct 8, 2020 at 11:42 PM <chr...@rtems.org> wrote: >> > >> > 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> >> > + > > > Should there be a general introduction on the compilers we support > and that we inherently rely on them. This puts the context into what > do GCC and CLANG support and which compiler(s) are available > on your target architecture. > > Also Ada should have a TBD section. > > If you can build Fortran with the RSB, it also needs a TBD section. > Surprising though it may be, it does work. :) > >> >> > +.. index:: C >> > +.. index:: C Programming Language >> > + >> > +C >> > += >> > +.. index:: C >> > + >> > +RTEMS supports the C programming language. >> > + >> > +TBD. > > > Obviously TBD but supported via the inherent compiler support > with the C Standard Library provided by newlib. Could reference > the POSIX Compliance Guide section on the C Standard Library. > > Support should be primarily for C99 and C11 including C11 threads. > Don't C11 thread also map to pthreads? > > There is a C11 threads example in rtems-examples. > > Disclaimer: C11 threads are a terrible API. > > >> > 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. >> >> I'm curious, will C++98/C++03 compliant code work? I admit to being >> completely out of touch with the C++ standard evolution. > > > Yes. The FACE Conformance Test Suite has been run against our C++03 > support with no issues. GCC and its C++ Library are the magic here. > >> >> >> > + >> > +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 >> provides >> access >> >> > +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 >> primitives > > > synchronization > or synchronisation to be self-consistent. thanks for spotting that.. the UK/AU s throws off my typo parsing :)
>> >> >> > +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 >> attribute >> >> > +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 >> comma splice, add a conjunction. I don't know if this should be >> "because there is no"? >> >> > +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. >> reference >> >> > + >> > +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 >> "policy based" (delete ", this is") >> >> > +standard. The policies are: >> > + >> > +``sched_other`` >> > + A CPU budget algorthim with timeslicing where the timeslice is reset. >> s/algorthim/algorithm >> >> > + >> > +``sched_fifo`` >> > + A CPU budget algorthim with no timeslicing. >> s/algorthim/algorithm >> >> > + >> > +``sched_roundrobin`` >> > + A CPU budget algorthim with timeslicing where the timeslice is >> > exhausted. >> s/algorthim/algorithm >> >> > + >> > +``sched_sporadic`` >> > + A CPU budget algorthim with a priorty, low priority and a replenish >> > period. >> s/algorthim/algorithm >> s/priorty/priority >> >> > + >> > +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: >> delete 'to' -> read as "mutex to access some" >> >> > + >> > +.. 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 >> s/it/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..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) >> delete " with" >> >> > +are specified a C language bindings but this does not limit the >> s/a/as >> >> > +languages RTEMS supports. >> > + >> > +.. toctree:: >> > + >> > + c >> > + cpp >> > + ada >> >> There are many other languages that are (suspected to be) working. >> java, go, lua, ... Maybe this section needs to be either expanded with >> all the languages we have seen used, or the language needs to be made >> more vague to imply that we support the bindings for c/c++/ada and >> that other languages can be supported? >> >> > -- >> > 2.24.1 >> > >> > _______________________________________________ >> > devel mailing list >> > devel@rtems.org >> > http://lists.rtems.org/mailman/listinfo/devel >> _______________________________________________ >> devel mailing list >> devel@rtems.org >> http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel