[PATCH] c-user: Add self-contained objects chapter

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Feb 1 10:17:57 UTC 2017


Update #2843.
---
 c-user/index.rst                  |   1 +
 c-user/self_contained_objects.rst | 337 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 338 insertions(+)
 create mode 100644 c-user/self_contained_objects.rst

diff --git a/c-user/index.rst b/c-user/index.rst
index 7937042..4b7fe22 100644
--- a/c-user/index.rst
+++ b/c-user/index.rst
@@ -62,6 +62,7 @@ to the Community Project hosted at http://www.rtems.org/.
 	board_support_packages
 	user_extensions
 	configuring_a_system
+	self_contained_objects
 	multiprocessing
 	symmetric_multiprocessing_services
 	pci_library
diff --git a/c-user/self_contained_objects.rst b/c-user/self_contained_objects.rst
new file mode 100644
index 0000000..76c2a64
--- /dev/null
+++ b/c-user/self_contained_objects.rst
@@ -0,0 +1,337 @@
+.. comment SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. COMMENT: Copyright (c) 2014, 2017.
+.. COMMENT: embedded brains GmbH.
+.. COMMENT: All rights reserved.
+
+Self-Contained Objects
+**********************
+
+Introduction
+============
+
+One of the original design goals of RTEMS was the support for heterogeneous
+computing based on message passing.  This was realized by synchronization
+objects with an architecture-independent identifier provided by the system
+during object creation (a 32-bit unsigned integer used as a bitfield) and a
+user-defined four character name.  This approach in the so called Classic API
+has some weaknesses:
+
+* Dynamic memory (the workspace) is used to allocate object pools.  This
+  requires a complex configuration with heavy use of the C pre-processor.
+  Dynamic memory is forbidden by some coding standards, e.g. MISRA C:2012
+  :cite:`MISRA:2012:C`.
+
+* Objects are created via function calls which return an object identifier.
+  The object operations use this identifier and map it internally to an object
+  representation.
+
+* The object identifier is only known at run-time.  This hinders compiler
+  optimizations and static analysis.
+
+* The objects reside in a table, e.g. they are suspect to false sharing of
+  cache lines :cite:`Drepper:2007:Memory`.
+
+* The object operations use a rich set of options and attributes.  For each
+  object operation these parameters must be evaluated and validated at run-time
+  to figure out what to do exactly for this operation.
+
+For applications that use fine grained locking the mapping of the identifier to
+the object representation and the parameter evaluation are a significant
+overhead that may degrade the performance dramatically.  An example is the `new
+network stack (libbsd) <https://git.rtems.org/rtems-libbsd>`_ which uses
+hundreds of locks in a basic setup and the OpenMP support.
+
+To overcome these issues new self-contained objects are available in RTEMS 4.12
+via the Newlib supplied :file:`<threads.h>`, :file:`<pthread.h>` and
+:file:`<sys/lock.h>` header files.  The following synchronization objects are
+provided
+
+* POSIX spinlocks,
+
+* mutexes,
+
+* recursive mutexes,
+
+* condition variables,
+
+* counting semaphores,
+
+* binary semaphores, and
+
+* Futex synchronization :cite:`Franke:2002:Futex`.
+
+This allows much better performance in SMP configurations as well as in
+uni-processor configurations.  The application configuration is significantly
+simplified, since it is no longer necessary to account for lock objects used by
+Newlib and GCC.  The Newlib defined self-contained objects can be a statically
+initialized and reside in the ``.bss`` section.  Destruction is a no-operation.
+
+Self-Contained Objects API
+==========================
+
+To give the RTEMS users access to self-contained objects an API is necessary.
+One option is to use the POSIX threads API (pthreads) and change its
+implementation to use self-contained objects.  However, there are some other
+things to consider.  Users of the Classic API may want to run their
+applications with different RTEMS versions.  Since the POSIX threads API is
+optional it may be not available at all, for example in a stripped down space
+qualified version.  The POSIX threads API has a lot of options that need
+run-time evaluation, so that optimal performance is not achievable.  There are
+a variety of error conditions.  This is a problem in combination with some
+coding standards, e.g.  MISRA C:2012.  APIs used by Linux (e.g.
+`<linux/mutex.h>
+<http://lxr.free-electrons.com/source/include/linux/mutex.h>`_) or the FreeBSD
+kernel (e.g.
+`MUTEX(9) <https://www.freebsd.org/cgi/man.cgi?query=mutex&sektion=9>`_) are
+better suited as a template for high-performance synchronization objects.
+
+The API defined in the following sections should be implementable via the
+Classic API, the self-contained objects present in RTEMS 4.12 and the POSIX
+API.  Timed operations are not available since the timeout semantics of the
+Classic API and the POSIX threads API are quite different.
+
+Mutual Exclusion
+================
+
+The :c:type:`rtems_mutex` provides mutual-exclusion synchronization using the
+:ref:`PriorityInheritance` in uni-processor configurations or the :ref:`OMIP`
+in SMP configurations.  Recursive locking is not supported
+:cite:`Williams:2012:CA`.
+
+.. c:type:: rtems_mutex
+
+The ``rtems_mutex`` is the type of a mutual-exclusion synchronization object.
+The storage space for this object must be provided by the user.  There are no
+defined comparison or assignment operators for this type.  Only the object
+itself may be used for performing synchronization.  The result of referring to
+copies of the object in calls to :c:func:`rtems_mutex_lock`,
+:c:func:`rtems_mutex_unlock`, and :c:func:`rtems_mutex_destroy` is undefined.
+Objects of this type must be initialized via :c:func:`RTEMS_MUTEX_INITIALIZER`
+or :c:func:`rtems_mutex_init` and must be destroyed via
+:c:func:`rtems_mutex_destroy`.
+
+.. c:function:: RTEMS_MUTEX_INITIALIZER(name)
+
+An initializer for static initialization.  It is equivalent to a call to
+:c:func:`rtems_mutex_init`.  Global mutexes without a name may reside in the
+``.bss`` section.
+
+.. c:function:: void rtems_mutex_init(rtems_mutex *mutex, const char *name)
+
+Initializes the ``mutex`` with the specified ``name``.  The ``name`` must be
+persistent throughout the life-time of the mutex.  The mutex is unlocked after
+initialization.
+
+.. c:function:: void rtems_mutex_lock(rtems_mutex *mutex)
+
+Locks the ``mutex``.  In case the mutex is currently locked, then the thread is
+blocked until it becomes the mutex owner.  Threads wait in priority order.
+
+This function must be called from thread context with interrupts enabled.
+
+.. c:function:: void rtems_mutex_unlock(rtems_mutex *mutex)
+
+Unlocks the ``mutex``.  In case the currently executing thread is not the owner
+of the ``mutex``, then the result is unpredictable.
+
+This function must be called from thread context with interrupts enabled.
+
+.. c:function:: void rtems_mutex_destroy(rtems_mutex *mutex)
+
+Destroys the ``mutex``.  In case the ``mutex`` is locked or still in use, then
+the result is unpredictable.
+
+Condition Variables
+===================
+
+The :c:type:`rtems_condition` provides a condition variable synchronization
+object.
+
+.. c:type:: rtems_condition
+
+The ``rtems_condition`` is the type of a condition variable object.  The
+storage space for this object must be provided by the user.  There are no
+defined comparison or assignment operators for this type.  Only the object
+itself may be used for performing synchronization.  The result of referring to
+copies of the object in calls to :c:func:`rtems_condition_wait`,
+:c:func:`rtems_condition_signal`, :c:func:`rtems_condition_broadcast`, and
+:c:func:`rtems_condition_destroy` is undefined.  Objects of this type must be
+initialized via :c:func:`RTEMS_CONDITION_INITIALIZER` or
+:c:func:`rtems_condition_init` and must be destroyed via
+:c:func:`rtems_condition_destroy`.
+
+.. c:function:: RTEMS_CONDITION_INITIALIZER(name)
+
+An initializer for static initialization.  It is equivalent to a call to
+:c:func:`rtems_condition_init`.  Global condition variables without a name may
+reside in the ``.bss`` section.
+
+.. c:function:: void rtems_condition_init(rtems_condition *condition, const char *name)
+
+Initializes the ``condition`` with the specified ``name``.  The ``name`` must
+be persistent throughout the life-time of the condition variable.
+
+.. c:function:: void rtems_condition_wait(rtems_condition *condition, rtems_mutex *mutex)
+
+Atomically waits for the condition and unlocks the mutex.  Once the condition
+is signalled to the thread it wakes up and locks the mutex.  Threads wait in
+priority order.
+
+This function must be called from thread context with interrupts enabled.
+
+.. c:function:: void rtems_condition_signal(rtems_condition *condition)
+
+Signals the condition to the highest priority waiting thread.  If no threads
+wait currently for the condition, then nothing happens.
+
+.. c:function:: void rtems_condition_broadcast(rtems_condition *condition)
+
+Signals the condition to all waiting threads.  If no threads wait currently for
+the condition, then nothing happens.
+
+.. c:function:: void rtems_condition_destroy(rtems_condition *condition)
+
+Destroys the ``condition``.  In case the ``condition`` still in use, then the
+result is unpredictable.
+
+Counting Semaphores
+===================
+
+The :c:type:`rtems_counting_semaphore` provides a counting semaphore
+synchronization object.
+
+.. c:type:: rtems_counting_semaphore
+
+The ``rtems_counting_semaphore`` is the type of a counting semaphore object.
+The storage space for this object must be provided by the user.  There are no
+defined comparison or assignment operators for this type.  Only the object
+itself may be used for performing synchronization.  The result of referring to
+copies of the object in calls to :c:func:`rtems_counting_semaphore_wait`,
+:c:func:`rtems_counting_semaphore_post`, and
+:c:func:`rtems_counting_semaphore_destroy` is undefined.  Objects of this type
+must be initialized via :c:func:`RTEMS_COUNTING_SEMAPHORE_INITIALIZER` or
+:c:func:`rtems_counting_semaphore_init` and must be destroyed via
+:c:func:`rtems_counting_semaphore_destroy`.
+
+.. c:function:: RTEMS_COUNTING_SEMAPHORE_INITIALIZER(name, value)
+
+An initializer for static initialization.  It is equivalent to a call to
+:c:func:`rtems_counting_semaphore_init`.  Global counting semaphores without a
+name may reside in the ``.bss`` section.
+
+.. c:function:: void rtems_counting_semaphore_init(rtems_counting_semaphore *semaphore, const char *name, unsigned int count)
+
+Initializes the ``semaphore`` with the specified ``name`` and ``count``.  The
+``name`` must be persistent throughout the life-time of the counting semaphore.
+The initial value is set to ``count``.
+
+.. c:function:: void rtems_counting_semaphore_wait(rtems_counting_semaphore *semaphore)
+
+Waits for the counting semaphore.  In case the current semaphore count is
+positive, then the count is decremented and the function returns immediately,
+otherwise the thread is blocked waiting for a semaphore post.  Threads wait in
+priority order.
+
+This function must be called from thread context with interrupts enabled.
+
+.. c:function:: void rtems_counting_semaphore_post(rtems_counting_semaphore *semaphore)
+
+Posts the counting semaphore.  In case at least one thread is waiting on the
+counting semaphore, then the highest priority thread is woken up, otherwise the
+current count is incremented.
+
+This function may be called from interrupt context.  In case it is called from
+thread context, then interrupts must be enabled.
+
+.. c:function:: void rtems_counting_semaphore_destroy(rtems_counting_semaphore *semaphore)
+
+Destroys the ``semaphore``.  In case the ``semaphore`` still in use, then the
+result is unpredictable.
+
+Binary Semaphores
+=================
+
+The :c:type:`rtems_binary_semaphore` provides a binary semaphore
+synchronization object.
+
+.. c:type:: rtems_binary_semaphore
+
+The ``rtems_binary_semaphore`` is the type of a binary semaphore object.  The
+storage space for this object must be provided by the user.  There are no
+defined comparison or assignment operators for this type.  Only the object
+itself may be used for performing synchronization.  The result of referring to
+copies of the object in calls to :c:func:`rtems_binary_semaphore_wait`,
+:c:func:`rtems_binary_semaphore_post`, and
+:c:func:`rtems_binary_semaphore_destroy` is undefined.  Objects of this type
+must be initialized via :c:func:`RTEMS_BINARY_SEMAPHORE_INITIALIZER` or
+:c:func:`rtems_binary_semaphore_init` and must be destroyed via
+:c:func:`rtems_binary_semaphore_destroy`.
+
+.. c:function:: RTEMS_BINARY_SEMAPHORE_INITIALIZER(name)
+
+An initializer for static initialization.  It is equivalent to a call to
+:c:func:`rtems_binary_semaphore_init`.  Global binary semaphores without a name
+may reside in the ``.bss`` section.
+
+.. c:function:: void rtems_binary_semaphore_init(rtems_binary_semaphore *semaphore, const char *name)
+
+Initializes the ``semaphore`` with the specified ``name``.  The ``name`` must
+be persistent throughout the life-time of the binary semaphore.  The initial
+value is set to zero.
+
+.. c:function:: void rtems_binary_semaphore_wait(rtems_binary_semaphore *semaphore)
+
+Waits for the binary semaphore.  In case the current semaphore count is
+positive, then the count is decremented and the function returns immediately,
+otherwise the thread is blocked waiting for a semaphore post.  Threads wait in
+priority order.
+
+This function must be called from thread context with interrupts enabled.
+
+.. c:function:: void rtems_binary_semaphore_post(rtems_binary_semaphore *semaphore)
+
+Posts the binary semaphore.  In case at least one thread is waiting on the
+binary semaphore, then the highest priority thread is woken up, otherwise the
+current count is set to one.
+
+This function may be called from interrupt context.  In case it is called from
+thread context, then interrupts must be enabled.
+
+.. c:function:: void rtems_binary_semaphore_destroy(rtems_binary_semaphore *semaphore)
+
+Destroys the ``semaphore``.  In case the ``semaphore`` still in use, then the
+result is unpredictable.
+
+Threads
+=======
+
+.. warning::
+
+   The self-contained threads support is work in progress.  In contrast to the
+   synchronization objects the self-contained thread support is not just an API
+   glue layer to already existing implementations.
+
+The :c:type:`rtems_thread` provides a thread of execution.
+
+.. c:type:: rtems_thread
+
+The ``rtems_thread`` is the type of a thread object.
+
+.. c:function:: RTEMS_THREAD_INITIALIZER(name, stack_size, priority, flags, entry, arg)
+
+.. c:function:: void rtems_thread_start(rtems_thread *thread, const char *name, size_t stack_size, uint32_t priority, uint32_t flags, void (*entry)(void *), void *arg)
+
+.. c:function:: void rtems_thread_restart(rtems_thread *thread, void *arg)
+
+.. c:function:: void rtems_thread_event_send(rtems_thread *thread, uint32_t events)
+
+.. c:function:: void rtems_thread_event_poll(rtems_thread *thread, uint32_t events_of_interest, uint32_t *actual_events)
+
+.. c:function:: void rtems_thread_event_wait_all(rtems_thread *thread, uint32_t events_of_interest, uint32_t *actual_events)
+
+.. c:function:: void rtems_thread_event_wait_any(rtems_thread *thread, uint32_t events_of_interest, uint32_t *actual_events)
+
+.. c:function:: void rtems_thread_destroy(rtems_thread *thread)
+
+.. c:function:: void rtems_thread_self_destroy(void)
-- 
1.8.4.5



More information about the devel mailing list