From a891c045a761896ccb47704522876077695adba9 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 21 Oct 2015 10:10:17 -0400 Subject: [PATCH] doc: Add section on floating point services to Kernel Primer Change-Id: Ic96385595740796e6bb28425cacd05a1285a89bb Signed-off-by: Allan Stephens --- doc/kernel/common/common.rst | 1 + doc/kernel/common/common_float.rst | 182 +++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 doc/kernel/common/common_float.rst diff --git a/doc/kernel/common/common.rst b/doc/kernel/common/common.rst index a6c4a704188..ff821196f2f 100644 --- a/doc/kernel/common/common.rst +++ b/doc/kernel/common/common.rst @@ -12,3 +12,4 @@ microkernel applications and nanokernel applications. common_contexts.rst common_kernel_clocks.rst common_atomic.rst + common_float.rst diff --git a/doc/kernel/common/common_float.rst b/doc/kernel/common/common_float.rst new file mode 100644 index 00000000000..f902e814ab0 --- /dev/null +++ b/doc/kernel/common/common_float.rst @@ -0,0 +1,182 @@ +.. _float_services: + +Floating Point Services +####################### + +.. note:: + Floating point services are currently available only for platforms + based on the Intel x86 architecture. + +Concepts +******** + +The kernel allows an application's tasks and fibers to use floating point +registers on platform configurations that support these registers. +Threads that use the x87 FPU/MMX registers are known as "FPU users", +while threads that use SSE registers are known as "SSE users". + +.. note:: + The kernel does not support the use of floating point registers by ISRs. + +The kernel can be configured to provide only the floating point services +required by an application. Three modes of operation are supported, +which are described below. In addition, the kernel's support for the SSE +registers can be included or omitted, as desired. + +No FP registers mode +==================== + +This mode is used when the application has no tasks or fibers that use +floating point registers. It is the kernel's default floating point services +mode. + +If a task or fiber uses any floating point register, +the kernel generates a fatal error condition and aborts the thread. + +Unshared FP registers mode +========================== + +This mode is used when the application has only a single task or fiber +that uses floating point registers. + +The kernel initializes the floating point registers so they can be used +by any task or fiber. The floating point registers are left unchanged +whenever a context switch occurs. + +.. note:: + Incorrect operation may result if two or more tasks or fibers use + floating point registers, as the kernel does not attempt to detect + (or prevent) multiple threads from using these registers. + +Shared FP registers mode +======================== + +This mode is used when the application has two or more tasks or fibers +that use floating point registers. + +The kernel initializes the floating point registers so they can be used +by any task or fiber, then saves and restores these registers during +context switches to ensure the computations performed by each FPU user +or SSE user are not impacted by the computations performed by the other users. +A "lazy save" algorithm is used during context switching which updates the +floating point registers only when it is absolutely necessary---for example, +the registers are *not* saved when switching from an FPU user to a thread +that does not use the floating point registers, and then switching back +to the original FPU user. + +Every task that uses the floating point registers must provide stack space +where the kernel can save the registers during context switches. An FPU user +must provide 108 bytes of added stack space, above and beyond its normal +requirements; an SSE user must provide 464 bytes of added stack space. + +.. note:: + A task that does *not* use the floating point registers does not need + to provide any added stack space. A fiber does *not* need to provide any + added stack space, regardless of whether or not it uses the floating + point registers. + +The kernel automatically detects that a given task or fiber is using +the floating point registers the first time the thread accesses them. +The thread is tagged as an SSE user if the kernel has been configured +to support the SSE registers, or as an FPU user if the SSE registers are +not supported. If this would result in a thread that is an FPU user being +tagged as an SSE user, or if the application wants to avoid the exception +handling overhead involved in auto-tagging threads, it is possible to +pre-tag a thread using one of the techniques listed below. + +* A task or fiber can tag itself as an FPU user or SSE user by calling + :c:func:`task_float_enable()` or :c:func:`fiber_float_enable()` + once it has started executing. + +* A fiber can be tagged as an FPU user or SSE user by its creator + when the fiber is started. + +* A microkernel task can be tagged as an FPU user or SSE user by adding it + to the :c:macro:`FPU` task group or the :c:macro:`SSE` task group + when the task is defined. + +.. note:: + Adding the task to the :c:macro:`FPU` or :c:macro:`SSE` task groups + by calling :c:func:`task_group_join()` does *not* tag the task + as an FPU user or SSE user. + +If a task or fiber uses the floating point registers infrequently +it can call :c:func:`task_float_disable()` or :c:func:`fiber_float_disable()` +to remove its tagging as an FPU user or SSE user. This eliminates the need +for the kernel to take steps to preserve the contents of the floating point +registers during context switches when there is no need to do so. +When the thread again needs to use the floating point registers it can re-tag +itself as an FPU user or SSE user using one of the techniques listed above. + + +Purpose +******* + +Use the kernel floating point services when an application needs to +perform floating point operations. + + +Usage +***** + +Configuring Floating Point Services +=================================== + +To configure unshared FP registers mode, enable the :option:`FLOAT` +configuration option and leave the :option:`FP_SHARING` configuration option +disabled. + +To configure shared FP registers mode, enable both the :option:`FLOAT` +configuration option and the :option:`FP_SHARING` configuration option. +Also, ensure that any task that uses the floating point registers has +sufficient added stack space for saving floating point register values +during context switches, as described above. + +Use the :option:`SSE` configuration option to enable support for +SSEx instructions. + + +Example: Performing Floating Point Arithmetic +============================================= +This code shows how a routine can use floating point arithmetic to avoid +overflow issues when computing the average of a series of integer values. +Note that no special coding is required if the kernel is properly configured. + +.. code-block:: c + + int average(int *values, int num_values) + { + double sum; + int i; + + sum = 0.0; + + for (i = 0; i < num_values; i++) { + sum += *values; + values++; + } + + return (int)((sum / num_values) + 0.5); + } + +APIs +**** + +The following floating point services APIs are provided by +:file:`microkernel.h` and by :file:`nanokernel.h`: + +:c:func:`fiber_float_enable()` + Tells the kernel that the specified task or fiber is now an FPU user + or SSE user. + +:c:func:`task_float_enable()` + Tells the kernel that the specified task or fiber is now an FPU user + or SSE user. + +:c:func:`fiber_float_disable()` + Tells the kernel that the specified task or fiber is no longer an FPU user + or SSE user. + +:c:func:`task_float_disable()` + Tells the kernel that the specified task or fiber is no longer an FPU user + or SSE user.