From 15ada1522f220ac8851e41d88114ee286460eca4 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Thu, 12 Oct 2023 20:02:16 -0400 Subject: [PATCH] doc: posix: structural reorganization of posix docs Revise the structure of the POSIX API docs. This separates related items out to dedicated pages. Further improvements could yet be made - e.g. using the 'collapse' feature to expand and collapse large sections of text or tables. Signed-off-by: Christopher Friedt (cherry picked from commit 3b4523588724d52c2e037d65fbe98ae4f06097d2) --- doc/_scripts/redirects.py | 2 +- doc/introduction/index.rst | 2 + doc/services/portability/index.rst | 2 +- doc/services/portability/posix/aep/index.rst | 191 ++++++++ .../portability/posix/conformance/index.rst | 145 +++++++ .../posix/implementation/index.rst | 77 ++++ doc/services/portability/posix/index.rst | 14 + .../portability/posix/kconfig/index.rst | 52 +++ .../option_groups/index.rst} | 408 ++++++++++-------- .../portability/posix/overview/index.rst | 135 ++++++ .../{ => posix/overview}/posix.svg | 2 +- 11 files changed, 851 insertions(+), 179 deletions(-) create mode 100644 doc/services/portability/posix/aep/index.rst create mode 100644 doc/services/portability/posix/conformance/index.rst create mode 100644 doc/services/portability/posix/implementation/index.rst create mode 100644 doc/services/portability/posix/index.rst create mode 100644 doc/services/portability/posix/kconfig/index.rst rename doc/services/portability/{posix.rst => posix/option_groups/index.rst} (57%) create mode 100644 doc/services/portability/posix/overview/index.rst rename doc/services/portability/{ => posix/overview}/posix.svg (68%) diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index 8c9120e9899a61..8d3d2da1d6791c 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -71,7 +71,7 @@ ('guides/pm/power_domain', 'services/pm/power_domain'), ('guides/pm/system', 'services/pm/system'), ('guides/portability/index', 'services/portability/index'), - ('guides/portability/posix', 'services/portability/posix'), + ('guides/portability/posix', 'services/portability/posix/index'), ('guides/porting/arch', 'hardware/porting/arch'), ('guides/porting/board_porting', 'hardware/porting/board_porting'), ('guides/porting/index', 'hardware/porting/index'), diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst index 5444694dd21cae..198dedd254a205 100644 --- a/doc/introduction/index.rst +++ b/doc/introduction/index.rst @@ -80,6 +80,8 @@ Zephyr offers a large and ever growing number of features including: * Red/black tree ready queue * Traditional multi-queue ready queue +.. _zephyr_intro_configurability: + **Highly configurable / Modular for flexibility** Allows an application to incorporate *only* the capabilities it needs as it needs them, and to specify their quantity and size. diff --git a/doc/services/portability/index.rst b/doc/services/portability/index.rst index 18b1a83c95f7f1..357aa778514a25 100644 --- a/doc/services/portability/index.rst +++ b/doc/services/portability/index.rst @@ -14,6 +14,6 @@ supported by the Zephyr RTOS. .. toctree:: :maxdepth: 1 - posix.rst + posix/index.rst cmsis_rtos_v1.rst cmsis_rtos_v2.rst diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst new file mode 100644 index 00000000000000..857635c103116e --- /dev/null +++ b/doc/services/portability/posix/aep/index.rst @@ -0,0 +1,191 @@ +.. _posix_aep: + +POSIX Application Environment Profiles (AEP) +############################################ + +Although inactive, `IEEE 1003.13-2003`_ defined a number of AEP that inspired the modern +subprofiling options of `IEEE 1003.1-2017`_. The single-purpose realtime system profiles +are listed below, for reference, in terms that agree with the current POSIX-1 standard. PSE54 +is not considered at this time. + +.. _posix_aep_pse51: + +Minimal Realtime System Profile (PSE51) +======================================= + +.. Conforming implementations shall define _POSIX_AEP_REALTIME_MINIMAL to the value 200312L + +.. csv-table:: PSE51 System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_AEP_REALTIME_MINIMAL, -1, + +.. csv-table:: PSE51 Option Groups + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + POSIX_C_LANG_JUMP,, + POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_DEVICE_IO,, :ref:`†` + POSIX_FILE_LOCKING,, + POSIX_SIGNALS,, :ref:`†` + POSIX_SINGLE_PROCESS,, :ref:`†` + POSIX_THREADS_BASE, yes, :ref:`†` + XSI_THREADS_EXT, yes, :ref:`†` + +.. csv-table:: PSE51 Option Requirements + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_CLOCK_SELECTION, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_FSYNC, -1, + _POSIX_MEMLOCK, -1, + _POSIX_MEMLOCK_RANGE, -1, + _POSIX_MONOTONIC_CLOCK, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_REALTIME_SIGNALS, -1, + _POSIX_SEMAPHORES, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_SHARED_MEMORY_OBJECTS, -1, + _POSIX_SYNCHRONIZED_IO, -1, + _POSIX_THREAD_ATTR_STACKADDR, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_ATTR_STACKSIZE, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_CPUTIME, -1, + _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` + _POSIX_THREAD_PRIO_PROTECT, -1, + _POSIX_THREAD_PRIORITY_SCHEDULING, -1, + _POSIX_THREAD_SPORADIC_SERVER, -1, + _POSIX_TIMEOUTS, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_TIMERS, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + +.. note:: + For PSE51 support, 44 of 75 symbols are currently implemented. + +.. _posix_aep_pse52: + +Realtime Controller System Profile (PSE52) +========================================== + +.. Conforming implementations shall define _POSIX_AEP_REALTIME_CONTROLLER to the value 200312L + +.. csv-table:: PSE52 System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_AEP_REALTIME_CONTROLLER, -1, + +.. csv-table:: PSE52 Option Groups + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + POSIX_C_LANG_JUMP,, + POSIX_C_LANG_MATH, yes, + POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_DEVICE_IO,, :ref:`†` + POSIX_FD_MGMT,, + POSIX_FILE_LOCKING,, + POSIX_FILE_SYSTEM,, + POSIX_SIGNALS,, :ref:`†` + POSIX_SINGLE_PROCESS,, :ref:`†` + POSIX_THREADS_BASE, yes, :ref:`†` + XSI_THREADS_EXT, yes, :ref:`†` + +.. csv-table:: PSE52 Option Requirements + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_CLOCK_SELECTION, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_FSYNC, -1, + _POSIX_MAPPED_FILES, -1, + _POSIX_MEMLOCK, -1, + _POSIX_MEMLOCK_RANGE, -1, + _POSIX_MESSAGE_PASSING, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + _POSIX_MONOTONIC_CLOCK, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_REALTIME_SIGNALS, -1, + _POSIX_SEMAPHORES, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_SHARED_MEMORY_OBJECTS, -1, + _POSIX_SYNCHRONIZED_IO, -1, + _POSIX_THREAD_ATTR_STACKADDR, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_ATTR_STACKSIZE, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_CPUTIME, -1, + _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` + _POSIX_THREAD_PRIO_PROTECT, -1, + _POSIX_THREAD_PRIORITY_SCHEDULING, -1, + _POSIX_THREAD_SPORADIC_SERVER, -1, + _POSIX_TIMEOUTS, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_TIMERS, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_TRACE, -1, + _POSIX_TRACE_EVENT_FILTER, -1, + _POSIX_TRACE_LOG, -1, + +.. _posix_aep_pse53: + +Dedicated Realtime System Profile (PSE53) +========================================= + +.. Conforming implementations shall define _POSIX_AEP_REALTIME_MINIMAL to the value 200312L + +.. csv-table:: PSE53 System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_AEP_REALTIME_CONTROLLER, -1, + +.. csv-table:: PSE53 Option Groups + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + POSIX_C_LANG_JUMP,, + POSIX_C_LANG_MATH, yes, + POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_DEVICE_IO,, :ref:`†` + POSIX_FD_MGMT,, + POSIX_FILE_LOCKING,, + POSIX_FILE_SYSTEM,, + POSIX_MULTI_PROCESS,, :ref:`†` + POSIX_NETWORKING, yes, :ref:`†` + POSIX_PIPE,, :ref:`†` + POSIX_SIGNALS,, :ref:`†` + POSIX_SIGNAL_JUMP,, :ref:`†` + POSIX_SINGLE_PROCESS,, :ref:`†` + POSIX_THREADS_BASE, yes, :ref:`†` + XSI_THREADS_EXT, yes, :ref:`†` + +.. csv-table:: PSE53 Option Requirements + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_ASYNCHRONOUS_IO, -1, + _POSIX_CLOCK_SELECTION, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_CPUTIME, -1, + _POSIX_FSYNC, -1, + _POSIX_MAPPED_FILES, -1, + _POSIX_MEMLOCK, -1, + _POSIX_MEMLOCK_RANGE, -1, + _POSIX_MEMORY_PROTECTION, -1, + _POSIX_MESSAGE_PASSING, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + _POSIX_MONOTONIC_CLOCK, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_PRIORITIZED_IO, -1, + _POSIX_PRIORITY_SCHEDULING, -1, + _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS` + _POSIX_REALTIME_SIGNALS, -1, + _POSIX_SEMAPHORES, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_SHARED_MEMORY_OBJECTS, -1, + _POSIX_SPAWN, -1, + _POSIX_SPORADIC_SERVER, -1, + _POSIX_SYNCHRONIZED_IO, -1, + _POSIX_THREAD_ATTR_STACKADDR, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_ATTR_STACKSIZE, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_CPUTIME, -1, + _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` + _POSIX_THREAD_PRIO_PROTECT, -1, + _POSIX_THREAD_PRIORITY_SCHEDULING, -1, + _POSIX_THREAD_PROCESS_SHARED, -1, + _POSIX_THREAD_SPORADIC_SERVER, -1, + _POSIX_TIMEOUTS, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_TIMERS, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_TRACE, -1, + _POSIX_TRACE_EVENT_FILTER, -1, + _POSIX_TRACE_LOG, -1, + +.. _IEEE 1003.1-2017: https://standards.ieee.org/ieee/1003.1/7101/ +.. _IEEE 1003.13-2003: https://standards.ieee.org/ieee/1003.13/3322/ diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst new file mode 100644 index 00000000000000..7d28efcf9acf15 --- /dev/null +++ b/doc/services/portability/posix/conformance/index.rst @@ -0,0 +1,145 @@ +.. _posix_conformance: + +POSIX Conformance +################# + +As per `IEEE 1003.1-2017`, this section details Zephyr's POSIX conformance. + +.. _posix_undefined_behaviour: + +.. note:: + As per POSIX 1003.13, single process mode is supported directly by both PSE51 and PSE52 + profiles. While Zephyr includes support for many features found in PSE53, PSE53 itself requires + supporting multiple processes. Since supporting multiple processes is beyond the scope of + Zephyr's current design, some features requiring multi-process capabilities may exhibit + undefined behaviour, which we denote with the † (obelus) symbol. + +.. _posix_system_interfaces: + +POSIX System Interfaces +======================= + +.. The following have values greater than -1 in Zephyr, conformant with the POSIX specification. + +.. csv-table:: POSIX System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_CHOWN_RESTRICTED, 0, + _POSIX_NO_TRUNC, 0, + _POSIX_VDISABLE, 0, + +.. The following should be valued greater than zero in Zephyr, in order to be strictly conformant + with the POSIX specification. + +.. csv-table:: POSIX System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_JOB_CONTROL, -1, :ref:`†` + _POSIX_REGEXP, -1, :ref:`†` + _POSIX_SAVED_IDS, -1, :ref:`†` + _POSIX_SHELL, -1, :ref:`†` + +.. TODO: POSIX_ASYNCHRONOUS_IO, and other interfaces below, are mandatory. That means that a + strictly conforming application need not be modified in order to compile against Zephyr. + However, we may add implementations that simply fail with ENOSYS as long as the functional + modification is clearly documented. The implementation is not required for PSE51 or PSE52 + and beyond that POSIX async I/O functions are rarely used in practice. + +.. csv-table:: POSIX System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_VERSION, 200809L, + _POSIX_ASYNCHRONOUS_IO, -1, :ref:`†` + :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_BARRIER` + :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_MAPPED_FILES, -1, :ref:`†` + _POSIX_MEMORY_PROTECTION, -1, :ref:`†` + :ref:`_POSIX_READER_WRITER_LOCKS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` + _POSIX_REALTIME_SIGNALS, -1, :ref:`†` + :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` + _POSIX_THREAD_SAFE_FUNCTIONS, 200809L, + :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX2_C_BIND, 200809L, + +.. csv-table:: POSIX System Interfaces (Optional) + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_ADVISORY_INFO, -1, + _POSIX_CPUTIME, -1, + _POSIX_FSYNC, -1, + _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` + _POSIX_MEMLOCK, -1, + _POSIX_MEMLOCK_RANGE, -1, + :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + _POSIX_MONOTONIC_CLOCK, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + _POSIX_PRIORITIZED_IO, -1, + :ref:`_POSIX_PRIORITY_SCHEDULING`, -1, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS` + _POSIX_SHARED_MEMORY_OBJECTS, -1, + _POSIX_SPAWN, -1, + _POSIX_SPORADIC_SERVER, -1, + _POSIX_SYNCHRONIZED_IO, -1, + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_CPUTIME, -1, + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` + _POSIX_THREAD_PRIO_PROTECT, -1, + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_PROCESS_SHARED, -1, + _POSIX_THREAD_SPORADIC_SERVER, -1, + _POSIX_TRACE, -1, + _POSIX_TRACE_EVENT_FILTER, -1, + _POSIX_TRACE_INHERIT, -1, + _POSIX_TRACE_LOG, -1, + _POSIX_TYPED_MEMORY_OBJECTS, -1, + _XOPEN_CRYPT, -1, + _XOPEN_REALTIME, -1, + _XOPEN_REALTIME_THREADS, -1, + :ref:`_XOPEN_STREAMS`, -1, :kconfig:option:`CONFIG_NET_SOCKETS` + _XOPEN_UNIX, -1, + +POSIX Shell and Utilities +========================= + +Zephyr does not support a POSIX shell or utilities at this time. + +.. csv-table:: POSIX Shell and Utilities + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX2_C_DEV, -1, :ref:`†` + _POSIX2_CHAR_TERM, -1, :ref:`†` + _POSIX2_FORT_DEV, -1, :ref:`†` + _POSIX2_FORT_RUN, -1, :ref:`†` + _POSIX2_LOCALEDEF, -1, :ref:`†` + _POSIX2_PBS, -1, :ref:`†` + _POSIX2_PBS_ACCOUNTING, -1, :ref:`†` + _POSIX2_PBS_LOCATE, -1, :ref:`†` + _POSIX2_PBS_MESSAGE, -1, :ref:`†` + _POSIX2_PBS_TRACK, -1, :ref:`†` + _POSIX2_SW_DEV, -1, :ref:`†` + _POSIX2_UPE, -1, :ref:`†` + _POSIX2_UNIX, -1, :ref:`†` + _POSIX2_UUCP, -1, :ref:`†` + +XSI Conformance +############### + +XSI System Interfaces +===================== + +.. csv-table:: XSI System Interfaces + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_FSYNC, -1, :ref:`†` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + _POSIX_THREAD_PROCESS_SHARED, -1, diff --git a/doc/services/portability/posix/implementation/index.rst b/doc/services/portability/posix/implementation/index.rst new file mode 100644 index 00000000000000..011317fef34a1c --- /dev/null +++ b/doc/services/portability/posix/implementation/index.rst @@ -0,0 +1,77 @@ +.. _posix_details: + +Implementation Details +###################### + +In many ways, Zephyr provides support like any POSIX OS; API bindings are provided in the C +programming language, POSIX headers are available in the standard include path, when configured. + +Unlike other multi-purpose POSIX operating systems + +- Zephyr is not "a POSIX OS". The Zephyr kernel was not designed around the POSIX standard, and + POSIX support is an opt-in feature +- Zephyr apps are not linked separately, nor do they execute as subprocesses +- Zephyr, libraries, and application code are compiled and linked together, running similarly to + a single-process application, in a single (possibly virtual) address space +- Zephyr does not provide a POSIX shell, compiler, utilities, and is not self-hosting. + +.. note:: + Unlike the Linux kernel or FreeBSD, Zephyr does not maintain a static table of system call + numbers for each supported architecture, but instead generates system calls dynamically at + build time. See `System Calls `_ for more information. + +Design +====== + +As a library, Zephyr's POSIX API implementation makes an effort to be a thin abstraction layer +between the application, middleware, and the Zephyr kernel. + +Some general design considerations: + +- The POSIX interface and implementations should be part of Zephyr's POSIX library, and not + elsewhere, unless required both by the POSIX API implementation and some other feature. An + example where the implementation should remain part of the POSIX implementation is + ``getopt()``. Examples where the implementation should be part of separate libraries are + multithreading and networking. + +- When the POSIX API and another Zephyr subsystem both rely on a feature, the implementation of + that feature should be as a separate Zephyr library that can be used by both the POSIX API and + the other library or subsystem. This reduces the likelihood of dependency cycles in code. When + practical, that rule should expand to include macros. In the example below, ``libposix`` + depends on ``libzfoo`` for the implementation of some functionality "foo" in Zephyr. If + ``libzfoo`` also depends on ``libposix``, then there is a dependency cycle. The cycle can be + removed via mutual dependency, ``libcommon``. + +.. graphviz:: + :caption: Dependency cycle between POSIX and another Zephyr library + + digraph { + node [shape=rect, style=rounded]; + rankdir=LR; + + libposix [fillcolor="#d5e8d4"]; + libzfoo [fillcolor="#dae8fc"]; + + libposix -> libzfoo; + libzfoo -> libposix; + } + +.. graphviz:: + :caption: Mutual dependencies between POSIX and other Zephyr libraries + + digraph { + node [shape=rect, style=rounded]; + rankdir=LR; + + libposix [fillcolor="#d5e8d4"]; + libzfoo [fillcolor="#dae8fc"]; + libcommon [fillcolor="#f8cecc"]; + + libposix -> libzfoo; + libposix -> libcommon; + libzfoo -> libcommon; + } + +- POSIX API calls should be provided as regular callable C functions; if a Zephyr + `System Call `_ is needed as part of the implementation, the declaration and the + implementation of that system call should be hidden behind the POSIX API. diff --git a/doc/services/portability/posix/index.rst b/doc/services/portability/posix/index.rst new file mode 100644 index 00000000000000..5fc5117df4419f --- /dev/null +++ b/doc/services/portability/posix/index.rst @@ -0,0 +1,14 @@ +.. _posix_support: + +POSIX +##### + +.. toctree:: + :maxdepth: 2 + + overview/index.rst + conformance/index.rst + aep/index.rst + implementation/index.rst + option_groups/index.rst + kconfig/index.rst diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst new file mode 100644 index 00000000000000..c1599dd55063c0 --- /dev/null +++ b/doc/services/portability/posix/kconfig/index.rst @@ -0,0 +1,52 @@ +.. _posix_kconfig_options: + +Configuration Options +********************* + +This is a non-exhaustive list of specific :ref:`kconfig` options relating to Zephyr's +implementation of the POSIX API. + +* :kconfig:option:`CONFIG_APP_LINK_WITH_POSIX_SUBSYS` +* :kconfig:option:`CONFIG_EVENTFD` +* :kconfig:option:`CONFIG_EVENTFD_MAX` +* :kconfig:option:`CONFIG_FDTABLE` +* :kconfig:option:`CONFIG_FNMATCH` +* :kconfig:option:`CONFIG_GETOPT` +* :kconfig:option:`CONFIG_GETOPT_LONG` +* :kconfig:option:`CONFIG_MAX_PTHREAD_BARRIER_COUNT` +* :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` +* :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` +* :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` +* :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` +* :kconfig:option:`CONFIG_MAX_TIMER_COUNT` +* :kconfig:option:`CONFIG_MQUEUE_NAMELEN_MAX` +* :kconfig:option:`CONFIG_MSG_COUNT_MAX` +* :kconfig:option:`CONFIG_MSG_SIZE_MAX` +* :kconfig:option:`CONFIG_NET_SOCKETPAIR` +* :kconfig:option:`CONFIG_NET_SOCKETS` +* :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` +* :kconfig:option:`CONFIG_NET_SOCKETS_POSIX_NAMES` +* :kconfig:option:`CONFIG_POSIX_API` +* :kconfig:option:`CONFIG_POSIX_CLOCK` +* :kconfig:option:`CONFIG_POSIX_FS` +* :kconfig:option:`CONFIG_POSIX_LIMITS_RTSIG_MAX` +* :kconfig:option:`CONFIG_POSIX_MAX_FDS` +* :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` +* :kconfig:option:`CONFIG_POSIX_MQUEUE` +* :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` +* :kconfig:option:`CONFIG_POSIX_SIGNAL` +* :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` +* :kconfig:option:`CONFIG_POSIX_UNAME` +* :kconfig:option:`CONFIG_POSIX_UNAME_NODENAME_LEN` +* :kconfig:option:`CONFIG_POSIX_UNAME_VERSION_LEN` +* :kconfig:option:`CONFIG_PTHREAD` +* :kconfig:option:`CONFIG_PTHREAD_BARRIER` +* :kconfig:option:`CONFIG_PTHREAD_COND` +* :kconfig:option:`CONFIG_PTHREAD_CREATE_BARRIER` +* :kconfig:option:`CONFIG_PTHREAD_IPC` +* :kconfig:option:`CONFIG_PTHREAD_KEY` +* :kconfig:option:`CONFIG_PTHREAD_MUTEX` +* :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` +* :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` +* :kconfig:option:`CONFIG_SEM_VALUE_MAX` +* :kconfig:option:`CONFIG_TIMER` diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix/option_groups/index.rst similarity index 57% rename from doc/services/portability/posix.rst rename to doc/services/portability/posix/option_groups/index.rst index 392147594c83ad..0381b1848200c4 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -1,131 +1,18 @@ -.. _posix_support: +.. _posix_option_groups: -POSIX Support -############# +Subprofiling Option Groups +########################## -The Portable Operating System Interface (POSIX) is a family of standards -specified by the IEEE Computer Society for maintaining compatibility between -operating systems. Zephyr implements a subset of the embedded profiles PSE51 -and PSE52, and BSD Sockets API. - -With the POSIX support available in Zephyr, an existing POSIX compliant -application can be ported to run on the Zephyr kernel, and therefore leverage -Zephyr features and functionality. Additionally, a library designed for use with -POSIX threading compatible operating systems can be ported to Zephyr kernel -based applications with minimal or no changes. - -.. figure:: posix.svg - :align: center - :alt: POSIX Support in Zephyr - - POSIX support in Zephyr - -The POSIX API subset is an increasingly popular OSAL (operating system -abstraction layer) for IoT and embedded applications, as can be seen in -Zephyr, AWS:FreeRTOS, TI-RTOS, and NuttX. - -Benefits of POSIX support in Zephyr include: - -- Offering a familiar API to non-embedded programmers, especially from Linux -- Enabling reuse (portability) of existing libraries based on POSIX APIs -- Providing an efficient API subset appropriate for small (MCU) embedded systems - - -System Overview -=============== - -Units of Functionality -++++++++++++++++++++++ - -The system profile is defined in terms of component profiles that specify Units -of Functionality that can be combined to realize the application platform. A Unit -of Functionality is a defined set of services which can be implemented. If -implemented, the standard prescribes that all services in the Unit must -be implemented. - -A Minimal Realtime System Profile implementation must support the -following Units of Functionality as defined in IEEE Std. 1003.1 (also referred to -as POSIX.1-2017). - - -.. csv-table:: Units of Functionality - :header: Requirements, Supported, Remarks - :widths: 50,10,60 - - - POSIX_C_LANG_JUMP, - POSIX_C_LANG_SUPPORT,yes - POSIX_DEVICE_IO, - POSIX_FILE_LOCKING, - POSIX_SIGNALS, - POSIX_SINGLE_PROCESS, - POSIX_SPIN_LOCKS,yes - POSIX_THREADS_BASE,yes - XSI_THREAD_MUTEX_EXT,yes - XSI_THREADS_EXT,yes - - -Option Requirements -++++++++++++++++++++ - -An implementation supporting the Minimal Realtime System -Profile must support the POSIX.1 Option Requirements which are defined in the -standard. Options Requirements are used for further sub-profiling within the -units of functionality: they further define the functional behavior of the -system service (normally adding extra functionality). Depending on the profile -to which the POSIX implementation complies,parameters and/or the precise -functionality of certain services may differ. - -The following list shows the option requirements that are implemented in -Zephyr. - - -.. csv-table:: Option Requirements - :header: Requirements, Supported - :widths: 50,10 - - _POSIX_BARRIERS,yes - _POSIX_CLOCK_SELECTION,yes - _POSIX_FSYNC, - _POSIX_MEMLOCK, - _POSIX_MEMLOCK_RANGE, - _POSIX_MONOTONIC_CLOCK,yes - _POSIX_NO_TRUNC, - _POSIX_REALTIME_SIGNALS, - _POSIX_SEMAPHORES,yes - _POSIX_SHARED_MEMORY_OBJECTS, - _POSIX_SPIN_LOCKS,yes - _POSIX_SYNCHRONIZED_IO, - _POSIX_THREAD_ATTR_STACKADDR,yes - _POSIX_THREAD_ATTR_STACKSIZE,yes - _POSIX_THREAD_CPUTIME, - _POSIX_THREAD_PRIO_INHERIT, - _POSIX_THREAD_PRIO_PROTECT, - _POSIX_THREAD_PRIORITY_SCHEDULING,yes - _POSIX_THREAD_SPORADIC_SERVER, - _POSIX_TIMEOUTS, - _POSIX_TIMERS,yes - _POSIX2_C_DEV, - _POSIX2_SW_DEV, - - - -Units of Functionality -====================== - -This section describes the Units of Functionality (fixed sets of interfaces) -which are implemented (partially or completely) in Zephyr. Please refer to the -standard for a full description of each listed interface. +.. _posix_option_group_threads_base: POSIX_THREADS_BASE -+++++++++++++++++++ +================== The basic assumption in this profile is that the system consists of a single (implicit) process with multiple threads. Therefore, the standard requires all basic thread services, except those related to multiple processes. - .. csv-table:: POSIX_THREADS_BASE :header: API, Supported :widths: 50,10 @@ -179,12 +66,12 @@ multiple processes. pthread_sigmask(), pthread_testcancel(), - +.. _posix_option_group_xsi_thread_ext: XSI_THREAD_EXT -++++++++++++++ +============== -The XSI_THREADS_EXT Unit of Functionality is required because it provides +The XSI_THREADS_EXT option group is required because it provides functions to control a thread's stack. This is considered useful for any real-time application. @@ -201,33 +88,14 @@ This table lists service support status in Zephyr: pthread_getconcurrency(), pthread_setconcurrency() - -XSI_THREAD_MUTEX_EXT -++++++++++++++++++++ - -The XSI_THREAD_MUTEX_EXT Unit of Functionality is required because it has -options for controlling the behavior of mutexes under erroneous application use. - - -This table lists service support status in Zephyr: - -.. csv-table:: XSI_THREAD_MUTEX_EXT - :header: API, Supported - :widths: 50,10 - - pthread_mutexattr_gettype(),yes - pthread_mutexattr_settype(),yes - +.. _posix_option_group_c_lang_support: POSIX_C_LANG_SUPPORT -++++++++++++++++++++ +==================== -The POSIX_C_LANG_SUPPORT Unit of Functionality contains the general ISO C +The POSIX_C_LANG_SUPPORT option group contains the general ISO C Library. -This is implemented as part of the minimal C library available in Zephyr. - - .. csv-table:: POSIX_C_LANG_SUPPORT :header: API, Supported :widths: 50,10 @@ -338,11 +206,12 @@ This is implemented as part of the minimal C library available in Zephyr. vsprintf(),yes vsscanf(), +.. _posix_option_group_single_process: POSIX_SINGLE_PROCESS -+++++++++++++++++++++ +==================== -The POSIX_SINGLE_PROCESS Unit of Functionality contains services for single +The POSIX_SINGLE_PROCESS option group contains services for single process applications. .. csv-table:: POSIX_SINGLE_PROCESS @@ -358,9 +227,10 @@ process applications. uname(),yes unsetenv() +.. _posix_option_group_signals: POSIX_SIGNALS -+++++++++++++ +============= Signal services are a basic mechanism within POSIX-based systems and are required for error and event handling. @@ -369,7 +239,6 @@ required for error and event handling. :header: API, Supported :widths: 50,10 - abort(),yes alarm(), kill(), @@ -388,32 +257,20 @@ required for error and event handling. sigwait(), strsignal(),yes -.. csv-table:: POSIX_SPIN_LOCKS - :header: API, Supported - :widths: 50,10 - - pthread_spin_destroy(),yes - pthread_spin_init(),yes - pthread_spin_lock(),yes - pthread_spin_trylock(),yes - pthread_spin_unlock(),yes - +.. _posix_option_group_device_io: POSIX_DEVICE_IO -+++++++++++++++ +=============== .. csv-table:: POSIX_DEVICE_IO :header: API, Supported :widths: 50,10 - flockfile(), - ftrylockfile(), - funlockfile(), - getc_unlocked(), - getchar_unlocked(),yes - putc_unlocked(), - putchar_unlocked() - clearerr(), + FD_CLR(),yes + FD_ISSET(),yes + FD_SET(),yes + FD_ZERO(),yes + clearerr(),yes close(),yes fclose(), fdopen(), @@ -436,17 +293,22 @@ POSIX_DEVICE_IO gets(), open(),yes perror(),yes + poll(),yes printf(),yes + pread(), + pselect(), putc(),yes putchar(),yes puts(),yes + pwrite(), read(),yes scanf(), + select(),yes setbuf(), setvbuf(), - stderr,yes - stdin,yes - stdout,yes + stderr, + stdin, + stdout, ungetc(), vfprintf(),yes vfscanf(), @@ -454,8 +316,72 @@ POSIX_DEVICE_IO vscanf(), write(),yes +.. _posix_option_group_barriers: + +POSIX_BARRIERS +============== + +.. csv-table:: POSIX_BARRIERS + :header: API, Supported + :widths: 50,10 + + pthread_barrier_destroy(),yes + pthread_barrier_init(),yes + pthread_barrier_wait(),yes + pthread_barrierattr_destroy(),yes + pthread_barrierattr_init(),yes + +.. _posix_option_group_clock_selection: + +POSIX_CLOCK_SELECTION +===================== + +.. csv-table:: POSIX_CLOCK_SELECTION + :header: API, Supported + :widths: 50,10 + + pthread_condattr_getclock(),yes + pthread_condattr_setclock(),yes + clock_nanosleep(),yes + +.. _posix_option_group_semaphores: + +POSIX_SEMAPHORES +================ + +.. csv-table:: POSIX_SEMAPHORES + :header: API, Supported + :widths: 50,10 + + sem_close(), + sem_destroy(),yes + sem_getvalue(),yes + sem_init(),yes + sem_open(), + sem_post(),yes + sem_trywait(),yes + sem_unlink(), + sem_wait(),yes + +.. _posix_option_group_spin_locks: + +POSIX_SPIN_LOCKS +================ + +.. csv-table:: POSIX_SPIN_LOCKS + :header: API, Supported + :widths: 50,10 + + pthread_spin_destroy(),yes + pthread_spin_init(),yes + pthread_spin_lock(),yes + pthread_spin_trylock(),yes + pthread_spin_unlock(),yes + +.. _posix_option_group_timers: + POSIX_TIMERS -++++++++++++ +============ .. csv-table:: POSIX_TIMERS :header: API, Supported @@ -471,13 +397,143 @@ POSIX_TIMERS timer_getoverrun(),yes timer_settime(),yes -POSIX_CLOCK_SELECTION -+++++++++++++++++++++ -.. csv-table:: POSIX_CLOCK_SELECTION +.. _posix_options: + +Additional POSIX Options +======================== + +.. _posix_option_message_passing: + +_POSIX_MESSAGE_PASSING +++++++++++++++++++++++ + +.. csv-table:: _POSIX_MESSAGE_PASSING :header: API, Supported :widths: 50,10 - pthread_condattr_getclock(),yes - pthread_condattr_setclock(),yes - clock_nanosleep(),yes + mq_close(),yes + mq_getattr(),yes + mq_notify(), + mq_open(),yes + mq_receive(),yes + mq_send(),yes + mq_setattr(),yes + mq_unlink(),yes + +_POSIX_PRIORITY_SCHEDULING +++++++++++++++++++++++++++ + +.. _posix_option_priority_scheduling: + +.. csv-table:: _POSIX_PRIORITY_SCHEDULING + :header: API, Supported + :widths: 50,10 + + sched_get_priority_max(),yes + sched_get_priority_min(),yes + sched_getparam(), + sched_getscheduler(), + sched_rr_get_interval(), + sched_setparam(), + sched_setscheduler(), + sched_yield(),yes + +.. _posix_option_reader_writer_locks: + +_POSIX_READER_WRITER_LOCKS +++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_READER_WRITER_LOCKS + :header: API, Supported + :widths: 50,10 + + pthread_rwlock_destroy(),yes + pthread_rwlock_init(),yes + pthread_rwlock_rdlock(),yes + pthread_rwlock_tryrdlock(),yes + pthread_rwlock_trywrlock(),yes + pthread_rwlock_unlock(),yes + pthread_rwlock_wrlock(),yes + pthread_rwlockattr_destroy(),yes + pthread_rwlockattr_getpshared(), + pthread_rwlockattr_init(),yes + pthread_rwlockattr_setpshared(), + +.. _posix_option_thread_attr_stackaddr: + +_POSIX_THREAD_ATTR_STACKADDR +++++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_ATTR_STACKADDR + :header: API, Supported + :widths: 50,10 + + pthread_attr_getstackaddr(),yes + pthread_attr_setstackaddr(),yes + +.. _posix_option_thread_attr_stacksize: + +_POSIX_THREAD_ATTR_STACKSIZE +++++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_ATTR_STACKSIZE + :header: API, Supported + :widths: 50,10 + + pthread_attr_getstacksize(),yes + pthread_attr_setstacksize(),yes + +.. _posix_option_thread_priority_scheduling: + +_POSIX_THREAD_PRIORITY_SCHEDULING ++++++++++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_PRIORITY_SCHEDULING + :header: API, Supported + :widths: 50,10 + + pthread_attr_getinheritsched(), + pthread_attr_getschedpolicy(),yes + pthread_attr_getscope(), + pthread_attr_setinheritsched(), + pthread_attr_setschedpolicy(),yes + pthread_attr_setscope(), + pthread_getschedparam(),yes + pthread_setschedparam(),yes + pthread_setschedprio(),yes + +.. _posix_option_timeouts: + +_POSIX_TIMEOUTS ++++++++++++++++ + +.. csv-table:: _POSIX_TIMEOUTS + :header: API, Supported + :widths: 50,10 + + mq_timedreceive(), + mq_timedsend(), + pthread_mutex_timedlock(),yes + pthread_rwlock_timedrdlock(),yes + pthread_rwlock_timedwrlock(),yes + sem_timedwait(),yes + posix_trace_timedgetnext_event(), + +.. _posix_option_xopen_streams: + +_XOPEN_STREAMS +++++++++++++++ + +.. csv-table:: _XOPEN_STREAMS + :header: API, Supported + :widths: 50,10 + + fattach(), + fdetach(), + getmsg(), + getpmsg(), + ioctl(),yes + isastream(), + putmsg(), + putpmsg(), diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst new file mode 100644 index 00000000000000..56810e49ac1419 --- /dev/null +++ b/doc/services/portability/posix/overview/index.rst @@ -0,0 +1,135 @@ +.. _posix_overview: + +Overview +######## + +The Portable Operating System Interface (POSIX) is a family of standards specified by the +`IEEE Computer Society`_ for maintaining compatibility between operating systems. Zephyr +implements a subset of the standard POSIX API specified by `IEEE 1003.1-2017`_ (also known as +POSIX-1.2017). + +.. figure:: posix.svg + :align: center + :alt: POSIX Support in Zephyr + + POSIX support in Zephyr + +.. note:: + This page does not document Zephyr's :ref:`POSIX architecture`, which is used to + run Zephyr as a native application under the host operating system for prototyping, + test, and diagnostic purposes. + +With the POSIX support available in Zephyr, an existing POSIX conformant +application can be ported to run on the Zephyr kernel, and therefore leverage +Zephyr features and functionality. Additionally, a library designed to be +POSIX conformant can be ported to Zephyr kernel based applications with no changes. + +The POSIX API is an increasingly popular OSAL (operating system abstraction layer) for IoT and +embedded applications, as can be seen in Zephyr, AWS:FreeRTOS, TI-RTOS, and NuttX. + +Benefits of POSIX support in Zephyr include: + +- Offering a familiar API to non-embedded programmers, especially from Linux +- Enabling reuse (portability) of existing libraries based on POSIX APIs +- Providing an efficient API subset appropriate for small (MCU) embedded systems + +.. _posix_subprofiles: + +POSIX Subprofiles +================= + +While Zephyr supports running multiple `threads `_ (possibly in an `SMP `_ +configuration), as well as `Virtual Memory and MMUs `_, Zephyr code and data +normally share a common address space. The Zephyr kernel executable code and the application +executable code are typically compiled into the same binary artifact. From that perspective, Zephyr +apps can be seen as running in the context of a single process. + +While multi-purpose operating systems (OS) offer full POSIX conformance, Real-Time Operating +Systems (RTOS) such as Zephyr typically serve a fixed-purpose, have limited hardware resources, +and experience limited user interaction. In such systems, full POSIX conformance can be +impractical and unnecessary. + +For that reason, POSIX defined the following :ref:`Application Environment Profiles (AEP)` +as part of `IEEE 1003.13-2003`_ (also known as POSIX.13-2003). + +* Minimal Realtime System Profile (:ref:`PSE51 `) +* Realtime Controller System Profile (:ref:`PSE52 `) +* Dedicated Realtime System Profile (:ref:`PSE53 `) +* Multi-Purpose Realtime System (PSE54) + +POSIX.13-2003 AEP were formalized in 2003 via "Units of Functionality" but the specification is now +inactive (for reference only). Nevertheless, the intent is still captured as part of POSIX-1.2017 +via :ref:`Options` and :ref:`Option Groups`, in Appendix E. + +.. _posix_apps: + +POSIX Applications in Zephyr +============================ + +A POSIX app in Zephyr is :ref:`built like any other app` and therefore requires the +usual :file:`prj.conf`, :file:`CMakeLists.txt`, and source code. For example, the app below +leverages the ``nanosleep()`` and ``perror()`` POSIX functions. + +.. code-block:: cfg + :caption: `prj.conf` for a simple POSIX app in Zephyr + + CONFIG_POSIX_API=y + +.. code-block:: c + :caption: A simple app that uses Zephyr's POSIX API + + #include + #include + #include + + void megasleep(size_t megaseconds) + { + struct timespec ts = { + .tv_sec = megaseconds * 1000000, + .tv_nsec = 0, + }; + + printf("See you in a while!\n"); + if (nanosleep(&ts, NULL) == -1) { + perror("nanosleep"); + } + } + + int main() + { + megasleep(42); + return 0; + } + +.. + TODO: insert a link to a list of all samples tagged with 'posix' + +.. _posix_config: + +Configuration +============= + +Like most features in Zephyr, POSIX features are +:ref:`highly configurable` but disabled by default. Users must +explicitly choose to enable POSIX options via :ref:`Kconfig` selection. Indeed, there are +:ref:`many Kconfig options in Zephyr` for the POSIX API to allow for +feature selection at various levels of granularity. + +Alternatively, users may enable one of the Kconfig options below as a shortcut to enable multiple +:ref:`Option Groups`. + +* :kconfig:option:`CONFIG_POSIX_API` +* :kconfig:option:`CONFIG_PTHREAD_IPC` + +.. note:: + Since the POSIX environment in Zephyr is fully configurable via :ref:`Kconfig`, + configurations that require modifying features should not be made if strict compliance is + required (POSIX-1.2017, section 2.1.3.1). + +.. + TODO: create Kconfig shortcuts for PSE51, PSE52, and PSE53 + +.. _IEEE: https://www.ieee.org/ +.. _IEEE Computer Society: https://www.computer.org/ +.. _IEEE 1003.1-2017: https://standards.ieee.org/ieee/1003.1/7101/ +.. _IEEE 1003.13-2003: https://standards.ieee.org/ieee/1003.13/3322/ diff --git a/doc/services/portability/posix.svg b/doc/services/portability/posix/overview/posix.svg similarity index 68% rename from doc/services/portability/posix.svg rename to doc/services/portability/posix/overview/posix.svg index c21ecba2ae507a..a62be70994ec2f 100644 --- a/doc/services/portability/posix.svg +++ b/doc/services/portability/posix/overview/posix.svg @@ -1,2 +1,2 @@ -
Hardware
Hardware
BSP
BSP
Zephyr Kernel
Zephyr Kernel
POSIX PSE51
POSIX PSE51
File System
File System
POSIX PSE52
<div>POSIX PSE52</div>
Networking
Networking
BSD Sockets
<div>BSD Sockets<br></div>
 Middleware
 Middleware
Application
Application
\ No newline at end of file +
Hardware
Hardware
BSP
BSP
Zephyr Kernel
Zephyr Kernel
POSIX PSE51
POSIX PSE51
File System
File System
POSIX PSE52
POSIX PSE52
Networking
Networking
POSIX PSE53
POSIX PSE53
 Middleware
 Middleware
Application
Application
\ No newline at end of file