From 5b4e077b6fccd7a7729c15cd63d5a68bb3af6985 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 27 Apr 2021 12:47:43 -0400 Subject: [PATCH 1/9] Fix #963, improve documentation of UtAssert API calls The UtAssert API documentation was very terse and some references are obsolete/incorrect. This converts to doxygen form and corrects the stale/incorrect references. In particular - UtMemSet does not exist, but the standard C memset call should be used to fill a memory region with a constant value. --- ut_assert/inc/utassert.h | 173 +++++++++++++++++++++++++++++++-------- ut_assert/inc/uttools.h | 102 +++++++++++++++++++---- 2 files changed, 228 insertions(+), 47 deletions(-) diff --git a/ut_assert/inc/utassert.h b/ut_assert/inc/utassert.h index e583ef859..6f303fa83 100644 --- a/ut_assert/inc/utassert.h +++ b/ut_assert/inc/utassert.h @@ -83,61 +83,98 @@ typedef struct * Macro Definitions */ -/* A simplified UtAssert that uses the expression itself as the description */ +/** + * \brief A simplified UtAssert that uses the expression itself as the description + */ #define UtAssert_Simple(Expression) UtAssert(Expression, #Expression, __FILE__, __LINE__) -/* Evaluates a expression as either true or false. true means the test passed, false means the test failed. */ +/** + * \brief Evaluates a expression as either true or false. + * + * true means the test passed, false means the test failed. + */ #define UtAssert_True(Expression, ...) UtAssertEx(Expression, UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Evaluates a expression as either true or false. true means the test passed, false means the test failed. */ +/** + * \copydoc UtAssert_True + */ #define UtAssert_Bool(Expression, ...) UtAssertEx(Expression, UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Asserts a test failure */ +/** + * \brief Asserts a test failure + */ #define UtAssert_Failed(...) UtAssertEx(false, UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Assert a test Not Applicable */ +/** + * \brief Assert a test Not Applicable + */ #define UtAssert_NA(...) UtAssertEx(false, UTASSERT_CASETYPE_NA, __FILE__, __LINE__, __VA_ARGS__) -/* Compares two integers and determines if they are equal within a specified absolute tolerance. */ +/** + * \brief Compares two integers and determines if they are equal within a specified absolute tolerance. + */ #define UtAssert_IntegerCmpAbs(x, y, Tolerance, ...) \ UtAssertEx((abs((x) - (y)) <= (Tolerance)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares two floating point numbers and determines if they are equal within a specified absolute tolerance. */ +/** + * \brief Compares two floating point numbers and determines if they are equal within a specified absolute tolerance. + */ #define UtAssert_DoubleCmpAbs(x, y, Tolerance, ...) \ UtAssertEx((fabs((x) - (y)) <= (Tolerance)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares two floating point numbers and determines if they are equal within a specified relative tolerance. */ +/** + * \brief Compares two floating point numbers and determines if they are equal within a specified relative tolerance. + */ #define UtAssert_DoubleCmpRel(x, y, Ratio, ...) \ UtAssertEx((fabs((x) - (y)) / (x) <= (Ratio)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares two strings and determines if they are equal. */ +/** + * \brief Compares two strings and determines if they are equal. + */ #define UtAssert_StrCmp(String1, String2, ...) \ UtAssertEx((strcmp(String1, String2) == 0), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares at most Length characters of two strings and determines if they are equal. */ +/** + * \brief Compares at most Length characters of two strings and determines if they are equal. + */ #define UtAssert_StrnCmp(String1, String2, Length, ...) \ UtAssertEx((strncmp(String1, String2, Length) == 0), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares two regions of memory and determines if they are equal. */ +/** + * \brief Compares two regions of memory and determines if they are equal. + */ #define UtAssert_MemCmp(Memory1, Memory2, Length, ...) \ UtAssertEx((memcmp(Memory1, Memory2, Length) == 0), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares a region of memory to a static pattern and determines if they are equal. Note: Use UtMemSet to - * fill a region of memory with a static pattern. */ +/** + * \brief Compares a region of memory to a static pattern and determines if they are equal. + * + * \note Use standard memset() to fill a region of memory with a static pattern. + */ #define UtAssert_MemCmpValue(Memory, Value, Length, ...) \ UtAssertEx((UtMemCmpValue(Memory, Value, Length)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares a region of memory to a byte count pattern and determines if they are equal. Note: Use UtMemFill to - * fill a region of memory with a byte count pattern. */ +/** + * \brief Compares a region of memory to a byte count pattern and determines if they are equal. + * + * \note Use UtMemFill() to fill a region of memory with a byte count pattern. + * \sa UtMemFill + */ #define UtAssert_MemCmpCount(Memory, Length, ...) \ UtAssertEx((UtMemCmpCount(Memory, Length)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* Compares a region of memory with the contents of a binary file and determines if they are equal. Note: Use - * UtMem2BinFile to copy a region of memory to a binary file. */ +/** + * \brief Compares a region of memory with the contents of a binary file and determines if they are equal. + * + * \note Use UtMem2BinFile() to copy a region of memory to a binary file. + * \sa UtMem2BinFile + */ #define UtAssert_Mem2BinFileCmp(Memory, Filename, ...) \ UtAssertEx((UtMem2BinFileCmp(Memory, Filename)), UtAssert_GetContext(), __FILE__, __LINE__, __VA_ARGS__) -/* A wrapper around UtAssertEx that allows the user to specify the failure type and a more descriptive message */ +/** + * \brief A wrapper around UtAssertEx that allows the user to specify the failure type and a more descriptive message + */ #define UtAssert_Type(Type, Expression, ...) \ UtAssertEx(Expression, UTASSERT_CASETYPE_##Type, __FILE__, __LINE__, __VA_ARGS__) @@ -233,43 +270,113 @@ typedef struct * Exported Functions */ -/* Returns the number of asserts that have passed. */ +/** + * \brief Returns the number of asserts that have passed. + * + * \returns Number of tests that have passed + */ uint32 UtAssert_GetPassCount(void); -/* Returns the number of asserts that have failed. */ +/** + * \brief Returns the number of asserts that have failed. + * + * \returns Number of tests that have failed + */ uint32 UtAssert_GetFailCount(void); -/* Returns the full status of UtAssert counters */ +/** + * \brief Returns the full status of UtAssert counters + * + * \returns Pointer to structure with all the current test counter values + */ const UtAssert_TestCounter_t *UtAssert_GetCounters(void); -/* Begins a test Segment */ +/** + * \brief Begins a test Segment + * + * \param SegmentName the name of the test segment, for logging/output classification + */ void UtAssert_BeginTest(const char *SegmentName); -/* Completes a test Segment */ +/** + * \brief Completes a test Segment + * + * Segment name and counters will be printed to the console + */ void UtAssert_EndTest(void); -/* Sets the context of the current test, which is the default message type for UtAssert calls */ +/** + * \brief Sets the context of the current test, which is the default message type for UtAssert calls + * + * General assert statements for which do not directly specify a case type will inherit this case type + * if an assert fails. The framework automatically sets this to #UTASSERT_CASETYPE_TSF during setup + * and #UTASSERT_CASETYPE_TTF during teardown. + * + * \sa UtAssert_GetContext + * + * \param Context the case type to use for general assert failures + */ void UtAssert_SetContext(UtAssert_CaseType_t Context); -/* Sets the context of the current test, which is the default message type for UtAssert calls */ +/** + * \brief Sets the context of the current test, which is the default message type for UtAssert calls + * + * \sa UtAssert_SetContext + * + * \returns Case type that was set previously via UtAssert_SetContext + */ UtAssert_CaseType_t UtAssert_GetContext(void); -/* Sets the context of the current test, which is the default message type for UtAssert calls */ +/** + * \brief Gets the segment name of the current test + * + * This is the name that was previously set via UtAssert_BeginTest() + * + * \note the appliction should not store this pointer, it may become + * invalid after the next call to UtAssert_EndTest() + * + * \returns pointer to current segment name + */ const char *UtAssert_GetSegmentName(void); -/* Base assert function. All asserts must call this function. */ +/** + * \brief Base assert function + * + * This basic function is provided for backward compatibility with older + * versions of Ut Assert. It generates an assert case using the current + * default context. + * + * Users should preferentially use one of the more type-specific assert macros, + * if available. + * + * \param Expression a boolean value which evaluates "true" if the test passes + * \param Description a free form string describing the test case + * \param File The source file name in which the test case appears + * \param Line The source line number in which the test case appears + */ bool UtAssert(bool Expression, const char *Description, const char *File, uint32 Line); -/* - * Assert function with CaseType (supports MIR, TSF, NA in addition to FAIL). - * Also supports printf-style message strings to allow more dynamic content in the messages +/** + * \brief Assert function with specific CaseType (supports MIR, TSF, NA in addition to FAIL). + * + * This assert routine allows more consise description of the test case, as it supports + * printf-style message strings to allow dynamic content in the messages. + * + * \param Expression a boolean value which evaluates "true" if the test passes + * \param CaseType the case type to report if expression is "false" (TSF, TTF, FAIL, DEBUG, etc) + * \param File The source file name in which the test case appears + * \param Line The source line number in which the test case appears + * \param MessageFormat a free form printf-style format string describing the test case */ bool UtAssertEx(bool Expression, UtAssert_CaseType_t CaseType, const char *File, uint32 Line, const char *MessageFormat, ...) OS_PRINTF(5, 6); -/* - * Aborts the entire test - * (for failures which going on is meaningless or impossible) +/** + * \brief Aborts the entire test + * + * This may be used for fundamental failures, after which going on becomes meaningless or impossible. + * + * \param Message a free form string describing the failure */ void UtAssert_Abort(const char *Message); diff --git a/ut_assert/inc/uttools.h b/ut_assert/inc/uttools.h index e69429388..2a76b010d 100644 --- a/ut_assert/inc/uttools.h +++ b/ut_assert/inc/uttools.h @@ -38,36 +38,110 @@ * Exported Functions */ -/* Copies a region of memory to a binary file. This file can be reloaded by calling UtBinFile2Mem or it can be - * used to verify test results by calling UtMem2BinFileCmp. */ +/** + * \brief Copies a region of memory to a binary file. + * + * This file can be reloaded by calling UtBinFile2Mem or it can be + * used to verify test results by calling UtMem2BinFileCmp. + * + * \sa UtBinFile2Mem, UtMem2BinFileCmp + * + * \param Memory pointer to memory region + * \param Filename file name to use + * \param Length size of memory region + * + * \returns true if copy was successful + */ bool UtMem2BinFile(const void *Memory, const char *Filename, uint32 Length); -/* Copies a binary file to a region of memory. */ +/** + * \brief Copies a binary file to a region of memory. + * + * \param Memory pointer to memory region + * \param Filename file name to use + * \param Length size of memory region + * + * \returns true if copy was successful + */ bool UtBinFile2Mem(void *Memory, const char *Filename, uint32 Length); -/* Copies a region of memory to a hex file */ +/** + * \brief Copies a region of memory to a hex file + * + * \param Memory pointer to memory region + * \param Filename file name to use + * \param Length size of memory region + * + * \returns true if copy was successful + */ bool UtMem2HexFile(const void *Memory, const char *Filename, uint32 Length); -/* Fills a region of memory with a byte count pattern. */ +/** + * \brief Fills a region of memory with a byte count pattern. + * + * \param Memory pointer to memory region + * \param Length size of memory region + */ void UtMemFill(void *Memory, uint32 Length); -/* Just like the standard sprintf except it returns a pointer to the result string. The result string - * cannot be larger than 256 bytes. */ +/** + * \brief Just like the standard sprintf except it returns a pointer to the result string. + * + * The result string cannot be larger than 256 bytes, and will be truncated if the output + * would exceed that length + * + * \param Spec Printf-style format string + * + * \returns pointer to result string + */ char *UtSprintf(const char *Spec, ...); -/* Calls UtPrintf to print a range of memory as hex bytes. */ +/** + * \brief print a range of memory as hex bytes. + * + * \param Memory pointer to memory region + * \param Length size of memory region + */ void UtPrintx(const void *Memory, uint32 Length); -/* Compares a region of memory to a static pattern and determines if they are equal. Note: Use UtMemSet to - * fill a region of memory with a static pattern. */ +/** + * \brief Compares a region of memory to a static pattern and determines if they are equal. + * + * \note Use standard memset() to fill a region of memory with a static value. + * + * \param Memory pointer to memory region + * \param Value static fill value to check for + * \param Length size of memory region + * + * \returns true if check was successful + */ bool UtMemCmpValue(const void *Memory, uint8 Value, uint32 Length); -/* Compares a region of memory to a byte count pattern and determines if they are equal. Note: Use UtMemFill to - * fill a region of memory with a byte count pattern. */ +/** + * \brief Compares a region of memory to a byte count pattern and determines if they are equal. + * + * \note Use UtMemFill() to fill a region of memory with a byte count pattern. + * + * \param Memory pointer to memory region + * \param Length size of memory region + * + * \returns true if check was successful + */ bool UtMemCmpCount(const void *Memory, uint32 Length); -/* Compares a region of memory with the contents of a binary file and determines if they are equal. Note: Use - * UtMem2BinFile to copy a region of memory to a binary file. */ +/** + * \brief Compares a region of memory with the contents of a binary file and determines if they are equal. + * + * \note Use UtMem2BinFile to copy a region of memory to a binary file. + * + * The size of the file determines the size of the memory region to check. The memory region must be + * at least the size of the file. + * + * \param Memory pointer to memory region + * \param Filename file name to use + * + * \returns true if check was successful + */ bool UtMem2BinFileCmp(const void *Memory, const char *Filename); /* Macros to implement simple printf-like functions for unit testing */ From 70640ec673588435ed89649ed318bea29425f572 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 30 Apr 2021 09:42:05 -0400 Subject: [PATCH 2/9] Fix #545, update OS_TaskCreate doc Clarify use of the stack_size parameter, and that it should not be 0. --- src/os/inc/osapi-task.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/os/inc/osapi-task.h b/src/os/inc/osapi-task.h index 6437f8f0f..5bf165bc4 100644 --- a/src/os/inc/osapi-task.h +++ b/src/os/inc/osapi-task.h @@ -81,12 +81,22 @@ typedef osal_task((*osal_task_entry)(void)); /**< @brief For task entry point */ * Creates a task and passes back the id of the task created. Task names must be unique; * if the name already exists this function fails. Names cannot be NULL. * + * Portable applications should always specify the actual stack size in the + * stack_size parameter, not 0. This size value is not enforced/checked by OSAL, + * but is simply passed through to the RTOS for stack creation. Some RTOS + * implementations may assume 0 means a default stack size while others + * may actually create a task with no stack. + * + * Unlike stack_size, the stack_pointer is optional and can be specified as NULL. + * In that case, a stack of the requested size will be dynamically allocated from + * the system heap. + * * @param[out] task_id will be set to the non-zero ID of the newly-created resource * @param[in] task_name the name of the new resource to create * @param[in] function_pointer the entry point of the new task * @param[in] stack_pointer pointer to the stack for the task, or NULL * to allocate a stack from the system memory heap - * @param[in] stack_size the size of the stack, or 0 to use a default stack size. + * @param[in] stack_size the size of the stack * @param[in] priority initial priority of the new task * @param[in] flags initial options for the new task * From 97de8c900fa6c0a5fc7880fb139fb426096ed7d3 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 30 Apr 2021 13:40:02 -0400 Subject: [PATCH 3/9] Fix #640, configuration guide updates Update the configuration guide for the current build system (CMake) and the currently provided set of OS/BSP layers. Many of the examples in this guide referred to items which are obsolete. However, this does *NOT* fix references to the applications and in particular the "tasking example" as this still may be brought back. --- doc/OSAL-Configuration-Guide.md | 768 +++++++++++++------------------- 1 file changed, 311 insertions(+), 457 deletions(-) diff --git a/doc/OSAL-Configuration-Guide.md b/doc/OSAL-Configuration-Guide.md index e32ff65d0..7aae314ea 100644 --- a/doc/OSAL-Configuration-Guide.md +++ b/doc/OSAL-Configuration-Guide.md @@ -4,7 +4,7 @@ The purpose of this document is to provide guidelines and conventions for the configuration and deployment of the Operating System Abstraction -Layer (OSAL) to a desired platform or platforms. +Layer (OSAL) to a desired platform or platforms. ## Background @@ -12,7 +12,7 @@ The goal OS Abstraction Layer is to promote the creation of portable and reusable real time embedded system software. Given the necessary OS abstraction layer implementations, the same embedded software should compile and run on a number of platforms ranging from spacecraft -computer systems to desktop PCs. +computer systems to desktop PCs. ## Applicable Documents @@ -27,46 +27,46 @@ computer systems to desktop PCs. |---|---| | OS | Operating System | | API | Application Programming Interface | -| CM | Configuration Management | -| CPU | Central Processing Unit | -| EEPROM | Electrically Erasable Programmable Read-Only Memory | -| HW, H/W | Hardware | -| RAM | Random-Access Memory | -| SW, S/W | Software | -| TBD | To Be Determined | +| CM | Configuration Management | +| CPU | Central Processing Unit | +| EEPROM | Electrically Erasable Programmable Read-Only Memory | +| HW, H/W | Hardware | +| RAM | Random-Access Memory | +| SW, S/W | Software | +| TBD | To Be Determined | ## Glossary of Terms The following table defines the terms used throughout this document. -These terms are identified as proper nouns and are capitalized. +These terms are identified as proper nouns and are capitalized. -| **Term** | **Definition** | +| **Term** | **Definition** | |---|---| -| Application (APP) | A generic term for a computer program in a desktop or embedded system. An Application is generally not part of the operating system. | -| Application Programmer's Interface (API) | A set of routines, protocols, and tools for building software applications | -| Board Support Package (BSP) | A collection of user-provided facilities that interface an OS and the cFE with a specific hardware platform. The BSP is responsible for hardware initialization. | -| Core Flight Executive (cFE) | A runtime environment and a set of services for hosting FSW Applications | -| Cyclic Redundancy Check | A polynomial based method for checking that a data set has remained unchanged from one time period to another. | -| Developer | Anyone who is coding a software Application. | -| Hardware Platform | The target hardware that hosts the Operating System and Application. | -| Interface Control Document | A document that describes the software interface, in detail, to another piece of software or hardware. | -| I/O Data | Any data being written to and read from an I/O port. No structure is placed on the data and no distinction as to the type of I/O device. I/O data is defined separately from memory data because it has a separate API and it's an optional interface of the cFE. | -| Log | A collection of data that an application stores that provides information to diagnose and debug FSW problems. | -| Memory Data | Any data being written to and read from memory. No structure is placed on the data and no distinction as to the type of memory is made. | +| Application (APP) | A generic term for a computer program in a desktop or embedded system. An Application is generally not part of the operating system. | +| Application Programmer's Interface (API) | A set of routines, protocols, and tools for building software applications | +| Board Support Package (BSP) | A collection of user-provided facilities that interface an OS and the cFE with a specific hardware platform. The BSP is responsible for hardware initialization. | +| Core Flight Executive (cFE) | A runtime environment and a set of services for hosting FSW Applications | +| Cyclic Redundancy Check | A polynomial based method for checking that a data set has remained unchanged from one time period to another. | +| Developer | Anyone who is coding a software Application. | +| Hardware Platform | The target hardware that hosts the Operating System and Application. | +| Interface Control Document | A document that describes the software interface, in detail, to another piece of software or hardware. | +| I/O Data | Any data being written to and read from an I/O port. No structure is placed on the data and no distinction as to the type of I/O device. I/O data is defined separately from memory data because it has a separate API and it's an optional interface of the cFE. | +| Log | A collection of data that an application stores that provides information to diagnose and debug FSW problems. | +| Memory Data | Any data being written to and read from memory. No structure is placed on the data and no distinction as to the type of memory is made. | | MMU | Memory Management Unit. A piece of hardware that manages virtual memory systems. It automatically translates addresses into physical addresses so that an application can be linked with one set of addresses but actually reside in a different part of memory. | | Network | A connection between subsystems used for communication purposes. | | Platform | See "Hardware Platform" above. | -| User | Anyone who interacts with the Software Application or system in its operational state. A user can be a developer, a tester, an operator, or a maintainer. -| Application (APP) | A generic term for a computer program in a desktop or embedded system. An Application is generally not part of the operating system. | -| Application Programmer's Interface (API) | A set of routines, protocols, and tools for building software applications | -| Board Support Package (BSP) | A collection of user-provided facilities that interface an OS and the cFE with a specific hardware platform. The BSP is responsible for hardware initialization. | -| Core Flight Executive (cFE) | A runtime environment and a set of services for hosting FSW Applications | -| Cyclic Redundancy Check | A polynomial based method for checking that a data set has remained unchanged from one time period to another. | -| Developer | Anyone who is coding a software Application. | -| Hardware Platform | The target hardware that hosts the Operating System and Application. | -| Interface Control Document | A document that describes the software interface, in detail, to another piece of software or hardware. | -| I/O Data | Any data being written to and read from an I/O port. No structure is placed on the data and no distinction as to the type of I/O device. I/O data is defined separately from memory data because it has a separate API and it's an optional interface of the cFE. | -| Log | A collection of data that an application stores that provides information to diagnose and debug FSW problems. | +| User | Anyone who interacts with the Software Application or system in its operational state. A user can be a developer, a tester, an operator, or a maintainer. +| Application (APP) | A generic term for a computer program in a desktop or embedded system. An Application is generally not part of the operating system. | +| Application Programmer's Interface (API) | A set of routines, protocols, and tools for building software applications | +| Board Support Package (BSP) | A collection of user-provided facilities that interface an OS and the cFE with a specific hardware platform. The BSP is responsible for hardware initialization. | +| Core Flight Executive (cFE) | A runtime environment and a set of services for hosting FSW Applications | +| Cyclic Redundancy Check | A polynomial based method for checking that a data set has remained unchanged from one time period to another. | +| Developer | Anyone who is coding a software Application. | +| Hardware Platform | The target hardware that hosts the Operating System and Application. | +| Interface Control Document | A document that describes the software interface, in detail, to another piece of software or hardware. | +| I/O Data | Any data being written to and read from an I/O port. No structure is placed on the data and no distinction as to the type of I/O device. I/O data is defined separately from memory data because it has a separate API and it's an optional interface of the cFE. | +| Log | A collection of data that an application stores that provides information to diagnose and debug FSW problems. | | Memory Data | Any data being written to and read from memory. No structure is placed on the data and no distinction as to the type of memory is made. | | MMU | Memory Management Unit. A piece of hardware that manages virtual memory systems. It automatically translates addresses into physical addresses so that an application can be linked with one set of addresses but actually reside in a different part of memory. | | Network | A connection between subsystems used for communication purposes. | @@ -83,7 +83,7 @@ source code from the OSAL applications, configuration parameters, and build products. The development environment is an example of how to configure and build portable software using the OSAL code, but it is by no means a requirement to use the OSAL. The included platforms for the -OSAL can be used as starting points for other boards and CPUs. +OSAL can be used as starting points for other boards and CPUs. The following sections provide instructions on how to: @@ -99,173 +99,102 @@ The following sections provide instructions on how to: - Run the OSAL Application on the target platform -In the current OSAL release, two build systems are available: the -"classic" build using ordinary makefiles, and a new build utilizing the -"cmake" tool. The "classic" build is mostly carried over from previous -OSAL releases and preserves compatibility with existing -projects/workflows. The "cmake" build offers increased features by +In the current OSAL release, the CMake tool is used to generate makefiles +to perform actual build. The "cmake" build offers increased features by introducing additional scripting and build-time configurability, allowing direct inclusion into larger projects with less need to modify -files to support a specific target or configuration. +files to support a specific target or configuration. ## Setup the Build Environment This section details the steps needed to setup the OSAL source distribution and prepare the host development environment to build the -OSAL. +OSAL. ### Setup the OSAL Source Distribution Get a copy of the OSAL source distribution directory on your build -machine. The source distribution has the following directories: +machine. The source distribution has the following directories: #### OSAL source distribution directories | **Directory** | **Description** | |---|---| -| osal | The top level OSAL source distribution directory. OSAL version 2.10 is being used as an example. | +| osal | The top level OSAL source distribution directory. OSAL version 2.10 is being used as an example. | | osal/src | The src directory contains the OSAL source, and make rules. | -| osal/src/examples | The sample directory contains the sample applications for the osal. | -| osal/src/tests | The tests directory contains a small number of OSAL tests that can run on the targets. | +| osal/src/examples | The sample directory contains the sample applications for the osal. | +| osal/src/tests | The tests directory contains a small number of OSAL tests that can run on the targets. | | osal/src/unit-tests |The unit-tests directory contains a suite of OSAL unit tests. | -| osal/src/bsp | The bsp directory contains the platform specific code for the OSAL as well as code to make the OSAL run on a particular platform. Everything in this directory is used to adapt the OSAL and Applications to a particular hardware platform. This directory also contains the startup code for the example programs. The included platforms are generic enough that they may be easy to port to other platforms and processor architectures. For example: The bsp/mcf5235-rtems board support package was ported to an ARM processor running RTEMS with minimal effort. | -| osal/src/make | The make directory contains common makefiles for building the OSAL and its applications (classic build only) | +| osal/src/bsp | The bsp directory contains the platform specific code for the OSAL as well as code to make the OSAL run on a particular platform. Everything in this directory is used to adapt the OSAL and Applications to a particular hardware platform. This directory also contains the startup code for the example programs. The included platforms are generic enough that they may be easy to port to other platforms and processor architectures. For example: The bsp/mcf5235-rtems board support package was ported to an ARM processor running RTEMS with minimal effort. | | osal/src/os | The os directory is the heart of the OSAL, containing the implementation of the OSAL for each supported operating system. There is a sub-directory for each supported operating system in this directory. The OSAL include files are also contained in this directory (src/os/inc). | -| osal/src/inc | The inc directory contains system wide include files that are used by the OSAL on all platforms. | -| osal/build | The build directory contains the classic framework for building an OSAL application. The files in this directory allow easy customization and configuration for any supported OS or platform for the OSAL. By changing two variables in a file, the OSAL examples and test can be built for any of the supported platforms. | -| osal/doc | The doc directory contains the documentation and release notes for the OSAL. | +| osal/src/inc | The inc directory contains system wide include files that are used by the OSAL on all platforms. | +| osal/doc | The doc directory contains the documentation and release notes for the OSAL. | The osal directory can go just about anywhere on a host development -system. +system. #### Example directory structure locations -| **Host Operating System** | **Example Directory** | **Notes** | +| **Host Operating System** | **Example Directory** | **Notes** | |---|---|---| | Windows/vxWorks 6 Development Shell | C:\\osalproject\\osal | Building on Windows with the vxWorks 6.x development tools requires using the "vxWorks Development Shell". The system will not build on a standard Cygwin Shell, or a windows DOS prompt. | -| Linux | /home/osaluser/osal| | +| Linux | /home/osaluser/osal| | ## Configure the OSAL Parameter File -The file **osconfig.h** has configuration parameters for tailoring the -OSAL parameters. Most parameters set upper bounds on the number of OS -objects that can be created. The OSAL keeps track of allocated OS -objects using fixed size tables. The OSAL source distribution contains a -sample osconfig.h file in the "osal/src/bsp/\/config" directory, -which can either be used as-is or tuned for specific project needs. The -osconfig.h file is required regardless of the build system in use -(classic or cmake). - -#### OSAL configuration parameters - -| **Parameter** | **Description** | -|---|---| -| OS_MAX_TASKS | The maximum number of tasks that can be created in the running OSAL application. | -| OS_MAX_QUEUES | The maximum number of queues that can be created in the running OSAL application. | -| OS_MAX_COUNT_SEMAPHORES | The maximum number of counting semaphores that can be created in the running OSAL application. | -| OS_MAX_BIN_SEMAPHORES | The maximum number of binary semaphores that can be created in the running OSAL application. | -| OS_MAX_MUTEXES | The maximum number of mutexes that can be created in the running OSAL application. | -|OS_MAX_PATH_LEN |The maximum length for an absolute path length in the OSAL File API.| -|OS_MAX_API_NAME|The maximum length for an individual file name in the OSAL File API.| |OS_BUFFER_SIZE|The maximum size of a formatted text message for the OS_printf API.| |OS_BUFFER_MSG_DEPTH|The maximum number of messages buffered by the OS_printf API.| -|OS_UTILITY_TASK_ON |Turns on a utility task that will read the statements to print from the OS_printf function. If this define is commented out OS_printf will print the text under the context of the caller.| -|OS_UTILITYTASK_STACK_SIZE|The size of the stack for the utility task.| |OS_UTILITYTASK_PRIORITY|The priority of the utility task.| -|OSAL_SOCKET_QUEUE |If this is defined, the posix port will use the socket implementation for message queues, rather than the POSIX message queue implementation.| |OS_MAX_MODULES |Used for defining the maximum number of loadable modules that the OS AL can keep track of. This is used for the new Module Load and Symbol API.| -|OS_MAX_SYM_LEN|Used for setting the maximum length of a symbol name in the symbol API .| -|OS_MAX_TIMERS|Used for defining the maximum number of timers in the OSAL.| - +The file `default_config.cmake` contains all available configuration parameters that +allow the OSAL build configuration to be tailored for a particular target environment. +Most parameters set upper bounds on the number of OS objects that can be created, as +the OSAL keeps track of allocated OS objects using fixed size tables. -## Setting up "classic" build +If customization is desired, one should not modify the `default_config.cmake` file directly, +but rather provide a alternative values by one of the override methods: -The following procedures are relevant only when using the classic -makefile build. For the equivalent cmake instructions, see the next -section. - -### Create System Environment Variable - -The OSAL development environment requires one system environment -variable to be set in order to build the example programs. The directory -also contains a shell script "setvars.sh" to set the environment to the -current OSAL directory. - -#### Environment Variables needed by the cFE - -| **Environment Variable** | **Value (in Linux as an example)** | **Notes** | -|---|---|---| -| OSAL_SRC | /home/osaluser/osal | The location of the OS Abstraction Layer source code. This directory can be moved anywhere as long as the environment variable is set accordingly. | +- If configuring OSAL as a standalone build for testing, values for options can be + specified as `-D` options on the cmake command. This is a common method of specifying + options in a CMake project; see `man cmake` for more information on the command line options. +- If integrating OSAL into a larger application build, or if numerous values need to be configured + and/or the configuration needs to be version controlled, a separate configuration file can be used. + The path to this file is specified via the `OSAL_CONFIGURATION_FILE` option. +When using a configuration file, the contents should be in the form of CMake "set" commands +for the various options that need to be configured. It is generally only necessary to specify +values which need to be changed from the default. For any value _not_ specified in the configuration +file, the default value from `default_config.cmake` will be used. -#### Example Environment Variable for Different Development Hosts - -| **Host Operating System** | **Example Environment Variables** | **Notes** | -|---|---|---| -| Windows/vxWorks 6 Development Shell | \% set OSAL_SRC=C:/osalproject/osal | 1\. These environment variables can be set in the Windows control panel under system/environment variables. 2\. Note the forward slash directory separators in the DOS environment variables. Because the vxWorks tools are half DOS and half-Unix, they don't seem to like the DOS style backslash.| -| Linux| \$ export OSAL_SRC=/home/osaluser/osal | These settings can be set in the user's .bash_profile | - -### Configure the Build Directory for the OSAL application - -The build directory is where the OSAL is configured and compiled for a -particular processor, board, and OS. The build directory is designed to -hold the OSAL configuration for the selected platform. The **core** -directory is where the core OS code, and bsp code are built. They are -left in the core directory for the applications to link against. The -build directory can have multiple OSAL applications to build for a -particular platform. The OSAL distribution contains directories for -example and test applications. Multiple build directories can be used to -configure the OSAL for different platforms in the same environment, each -with its own unique OSAL configuration. - -### Configure the 'build' Directory - -In order to build the OSAL for one of the supported platforms, the OSAL -build directory must be properly configured. This involves editing a -couple of configuration files and setting up one or more sample -applications that use the OSAL API. - -### Define the CPU, Operating System, and Processor Board +#### OSAL configuration parameters -In the build directory, edit the **'osal-config.mak'** file and set the -options for your target. The default settings in the osal-config.mak are -for running vxWorks6.4 on a generic PowerPC board. +This is a list of commonly-used tuning parameters, but it is _not_ a complete list. The specific set of +configurable options may vary between versions of OSAL. For a complete list of options supported by this +version of OSAL, refer to the `default_config.cmake` file in the top level directory. +| **Parameter** | **Description** | +|---|---| +| `OSAL_CONFIG_MAX_TASKS` | The maximum number of tasks that can be created in the running OSAL application. | +| `OSAL_CONFIG_MAX_QUEUES` | The maximum number of queues that can be created in the running OSAL application. | +| `OSAL_CONFIG_MAX_COUNT_SEMAPHORES` | The maximum number of counting semaphores that can be created in the running OSAL application. | +| `OSAL_CONFIG_MAX_BIN_SEMAPHORES` | The maximum number of binary semaphores that can be created in the running OSAL application. | +| `OSAL_CONFIG_MAX_MUTEXES` | The maximum number of mutexes that can be created in the running OSAL application. | +| `OSAL_CONFIG_MAX_PATH_LEN` | The maximum length for an absolute path length in the OSAL File API.| +| `OSAL_CONFIG_MAX_FILE_NAME` | The maximum length for an individual file name in the OSAL File API.| +| `OSAL_CONFIG_MAX_MODULES` | Used for defining the maximum number of loadable modules that OSAL can have loaded simultaneously. | +| `OSAL_CONFIG_MAX_SYM_LEN` | Used for setting the maximum length of a symbol name in the symbol API.| +| `OSAL_CONFIG_MAX_TIMERS` | Used for defining the maximum number of timers in the OSAL.| + +All configurable CMake parameters are translated to a generated configuration header file +called `osconfig.h`, which replaces the directly-managed header file that was found in previous +OSAL versions. For compatibility with existing code, the directives provided in the header file +have an `OS_` prefix to match the preprocessor directives in previous versions. -#### osal-config.mak Settings - -| **osal-config.mak variable** | **Valid selections** | **Notes** | -|---|---|---| -| OS | vxworks6, rtems, posix | 1\. VxWorks 5.5 is no longer supported. 2\. posix is tested for 32 bit linux 2.6.x | -| BSP | genppc-vxworks6.4, mac-posix, pc-posix, mcf5235-rtems, sis-rtems | Use posix for linux | -| OSAL_M32 | -m32 (or commented out) | See below. | - -Note that not all combinations are valid. See the Platform Specific -Section for more information on each supported cFE target. - -In some cases, developers may find their compiler toolchain producing -"64-bit" images, when "32-bit" images are needed -- for example, when -using "native" GCC on a 64-bit X86 Linux. The OSAL build files support -use of an **OSAL_M32** build variable to insert the appropriate "please -build 32-bit images" compiler parameter into all compilation and linkage -commands. - -In this use case, the setting of the **OSAL_M32** build variable should -be uncommented in the **osal-config.mak** file, and set to the correct -flag for the compiler toolchain in use. The build system will also honor -settings of this variable made in the developer's shell environment or -on the "make" command line.. - -Usage of this flag may require an optional "multilib" (or similar) -package to be installed. Refer to your operating system and toolchain -documentation for details, if adding the appropriate flag causes your -builds to fail due to (for example) missing 32-bit or multilib related -headers or libraries. ## Setting up the "cmake" build This section covers how to set up the host machine for building OSAL using the cmake build system. Rather than using pre-written makefiles as -the classic build does, the cmake build generates makefiles entirely -from instructions specified in files contained with the source code -itself. This has several advantages: +the classic build of previous OSAL versions had, the cmake build generates +makefiles entirely from instructions specified in files contained with the +source code itself. This has several advantages: - Enhanced script-like capabilities @@ -277,7 +206,7 @@ Typically, OSAL is not built by itself, but rather as a library to be used within a larger application. The OSAL cmake build system allows both options; building as a standalone entity for testing purposes, or building as a sub-component within a larger project. The same scripts -are used in both cases, and no modification is required. +are used in both cases, and no modification is required. ### Prerequisites @@ -287,74 +216,106 @@ available via the respective Linux distribution package management system, i.e. "yum" on RedHat and derivatives, or "apt-get" on Debian and derivatives. For other operating systems, the cmake tool is available in source and binary form from . OSAL requires at least -version 2.6.4 of the cmake tool. +version 3.5 of the cmake tool. + +**RHEL/CentOS users**: For RHEL releases prior to 8.0, a compatible +cmake version is available via the EPEL repository in a package called +"cmake3". If using this package, the `cmake` command in the examples in +this document should be replaced with `cmake3`. ### Variables that must be specified The OSAL cmake build is controlled by several user-supplied variables -when the build is first provisioned: +when the build is first provisioned: | **CMake variable** | **Valid selections** | **Notes** | |---|---|---| -| OSAL_SYSTEM_OSTYPE | Any directory name that exists under osal/src/os |All OS-specific source files in this directory will be built. An optional, OS-specific "build-options.cmake" file will also be included which may add necessary compiler options specific to that OS. | -| OSAL_SYSTEM_BSPTYPE | Any directory name that exists under osal/src/bsp | All BSP-specific source files in this directory will be built. An optional, BSP-specific "build-options.cmake" file will also be included which may add necessary compiler options specific to that BSP. | -| OSAL_INCLUDEDIR | Any directory on the host system (absolute path) | Optional; if specified, this will be included in the compiler include file search path. Typically this is used to specify the location of "osconfig.h" for standalone OSAL builds. | -| ENABLE_UNIT_TESTS | TRUE or FALSE | Optional; defaults to "FALSE" if not specified. If set to TRUE, the included unit test code will also be built in addition to the runtime library. | -| OSAL_USER_C\_FLAGS | Any valid switches for the compiler in use. | Optional; the user may specify any arbitrary compiler switches to use. | +| `OSAL_EXT_SOURCE_DIR` | Any directory name | Optional. If specified, indicates an external filesystem directory that contains user-defined OS or BSP implementations | +| `OSAL_SYSTEM_BSPTYPE` | Any directory name that exists under `osal/src/bsp` or `${OSAL_EXT_SOURCE_DIR}` | Selects the BSP to use. All BSP-specific source files in this directory will be built. An optional, BSP-specific "build-options.cmake" file will also be included which may add necessary compiler options specific to that BSP. | +| `OSAL_SYSTEM_OSTYPE` | Any directory name that exists under `osal/src/os` or `${OSAL_EXT_SOURCE_DIR}` | Optional. Selects the OS abstraction to use. This variable is typically implied by the BSP selection in `OSAL_SYSTEM_BSPTYPE` but may be forced/overridden using this option. | +| `OSAL_CONFIGURATION_FILE` | A file providing compile-time configuration settings | Optional; also may be a list. If specified, the file(s) specified will be included prior to configuring/building OSAL. The files should contain SET directives (in CMake syntax) for compile options listed in `default_config.cmake` for tuning the OSAL build. This is an alternative to specifying individual options via `-D` CMake parameters when configuring OSAL. | +| `ENABLE_UNIT_TESTS` | TRUE or FALSE | Optional; defaults to "FALSE" if not specified. If set to TRUE, the included unit test code will also be built in addition to the runtime library. | +| `OSAL_USER_C_FLAGS` | Any valid switches for the compiler in use. | Optional; the user may specify any arbitrary compiler switches to use. | It is important to note that the values specified for these variables are **automatically cached** by the cmake build system. It is only necessary to specify these values when first provisioning/configuring a -build; these are *not* required when simply building the binaries. +build; these are *not* required when simply building the binaries. This caching function removes the need for environment variables to be -set as in the "setvars.sh" file in the classic build. The cmake build -does not require the user to set environment variables; all necessary -context information is automatically stored in the cache when the build -is first provisioned. +set in the development shell. The generated makefiles do not require the +user to set any environment variables, as all necessary context information +is automatically stored in the cache when the build is first provisioned. ### Setting up a standalone OSAL build The OSAL may be built standalone in order to evaluate the library for a -particular target and/or execute the included unit tests. +particular target and/or execute the included unit tests. In the cmake build system, all generated files are placed in a dedicated "binary" directory that is separate from the source tree. To provision a build, the user must first create the binary directory by issuing the "mkdir" command (on Linux), preferably outside the OSAL source tree. Then, the "cmake" provisioning tool is invoked to generate the actual -makefiles, supplying values for the required variables: +makefiles, supplying values for the required variables. + +The following example will generate a build tree that allows testing +of the OSAL library on a standard Linux workstation: ``` $ mkdir build $ cd build -$ cmake –DOSAL_SYSTEM_OSTYPE=posix –DOSAL_SYSTEM_BSPTYPE=pc-linux \ - –DENABLE_UNIT_TESTS=TRUE –DOSAL_INCLUDEDIR=/path/to/user/config \ - /path/to/osal/source - +$ cmake \ + -DCMAKE_BUILD_TYPE=debug \ + -DENABLE_UNIT_TESTS=true \ + -DOSAL_SYSTEM_BSPTYPE=generic-linux \ + -DOSAL_CONFIG_DEBUG_PERMISSIVE_MODE=true \ + /path/to/osal/source ``` - The cmake provisioning tool generates standard makefiles in the build directory. To build the OSAL binaries, simply run "make" in the build -directory. +directory. + +Note that the OSAL is not typically built as a standalone library; although a standalone +build can be done for testing and development purposes, it is expected that the OSAL will +be utilized as a component in a larger application. ### Integrating OSAL into a larger build Modularity is a key feature of the cmake system. As such, the OSAL cmake build system can be directly used as a component within a larger "mission" build, as long as the same variables are supplied via the -parent cmake script: +parent cmake script: ``` -SET(OSAL_SYSTEM_OSTYPE “posix”) SET(OSAL_SYSTEM_BSPTYPE “pc-linux”) ADD_SUBDIRECTORY(path/to/osal) ``` The values for the variables can be obtained by any means, shown here is -just a simplified example of how it can be done for a known target. +just a simplified example of how it can be done for a known target. + +This example assumes the parent application project also uses the CMake build +system. This is the preferred method, as any required compiler definitions +and/or include directories are automatically propagated to any executable +that links with the OSAL library. This is done via the TARGET_LINK_LIBRARIES +command, for example: + +``` +ADD_EXECUTABLE(my_program my_program.c) +TARGET_LINK_LIBRARIES(my_program osal) +``` + +This way, the program sources will be built with the public API include directories +from OSAL, as well as any compile definitions required by the selected OS/BSP. + +Otherwise, if the application does not use CMake, OSAL can be built as a standalone library +and "installed" to a designated directory where the application can use the library. In +this type of setup, the developer must manually propagate the include directories (i.e. +the path to the `src/os/inc` subdirectory) and any necessary compile definitions to the +parent application. ### Cross compiling with Cmake @@ -364,7 +325,7 @@ that may be required. Documentation for the toolchain files is available on the cmake website at . The toolchain file is specified when the build is provisioned. No OSAL build scripts need to be modified in order to cross compile or add extra machine-specific -options. +options. ## Check over or customize the OSAL BSP directory @@ -372,14 +333,14 @@ The glue logic that ties an OSAL application to a specific processor board and platform is in the src/bsp directory. This directory contains the BSP code, which contains all of the specific rules, glue code, and startup code to make an OSAL application run on a particular board with -a particular OS. +a particular OS. The platforms supported in the OSAL distribution should run out of the box. They provide a starting point for a complete port to a new -processor board. +processor board. This section will be expanded in the future to include information -needed for new OSAL ports. +needed for new OSAL ports. ## Configure one or more OSAL Applications @@ -390,69 +351,59 @@ src/examples directory, or the applications can be contained completely within the build directory. The OSAL source distribution has a set of test and example applications in the src/examples and src/tests directories and a set of corresponding application directories and -makefiles in build directory. +makefiles in build directory. ### Configure a sample application in the build directory The following show the files needed for a sample OSAL application in the -build directory. +build directory. #### Sample OSAL Applications and the associated files | **File** | **Description** | |---|---| -| build/examples/tasking-example | Directory for the included OSAL example Application. | -| build/examples/tasking-example/Makefile | Makefile for the example OSAL app. Because the source is in the src/examples/tasking-example directory, there is no need to include it here. The Makefile will find it using the OSAL_SRC environment variable. The source could be copied here in order to customize it. | -| build/examples/new_osal_app | Directory for a new OSAL application. | -| build/examples/new_osal_app/Makefile | Makefile for a new OSAL application. | -| build/examples/new_osal_app/new_osal_app.c | Source file for the new OSAL application. | -| build/examples/new_osal_app/new_osal_app.h | Header file for the new OSAL application. | +| `build/examples/tasking-example` | Directory for the included OSAL example Application. | +| `build/examples/tasking-example/Makefile` | Makefile for the example OSAL app. Because the source is in the src/examples/tasking-example directory, there is no need to include it here. The Makefile will find it using the OSAL_SRC environment variable. The source could be copied here in order to customize it. | +| `build/examples/new_osal_app` | Directory for a new OSAL application. | +| `build/examples/new_osal_app/Makefile` | Makefile for a new OSAL application. | +| `build/examples/new_osal_app/new_osal_app.c` | Source file for the new OSAL application. | +| `build/examples/new_osal_app/new_osal_app.h` | Header file for the new OSAL application. | The Application Makefiles have a specific format, so it is best to copy one of the application Makefiles from the build directory, such as -build/examples/tasking-example. +build/examples/tasking-example. ### Configure the application's main entry point The OSAL development environment provides the main entry point/startup code for the Application. This code is located in the src/\/src directory. The startup code will call the Application's entry point -which is named: void OS_Application_Startup(void) +which is named: void OS_Application_Startup(void) ## Build the OSAL core and Applications Once the OSAL Core and Applications are set up in a build directory, everything can be compiled. The OSAL Core or any of the Applications can be built from individual make files, or they can be built from the -top-level Makefile in the build directory. +top-level Makefile in the build directory. #### Build Commands -| **Shell command** | **Description** | -|---|---| -| **\$ cd build** | Change to the build directory. | -| **\$ make** | Build the OSAL Core, and all Applications. | -| **\$ make clean** | Clean the OSAL Core, and all Applications. | - - -The following additional make targets apply only to the "classic" build; -the cmake build handles configuration and dependencies automatically. - | **Shell command** | **Description** | |---|---| -| **\$ make config** | Copy the osconfig.h for the BSP to the build directory. | -| **\$ cd examples/tasking-example; make** | Build the tasking-example Application only. | -| **\$ make depend** | Recalculate the dependencies on the OSAL Core files and apps. | +| **\$ cd build** | Change to the build directory. | +| **\$ make** | Build the OSAL Core, and all Applications. | +| **\$ make clean** | Clean the OSAL Core, and all Applications. | Once the OSAL Applications are built, they are ready to load and execute on the target. The filename of the executable is dependent on the OS it -is built for. +is built for. #### OSAL Application executable name -| **Target Operating System** | **Application executable name** | **Notes** | +| **Target Operating System** | **Application executable name** | **Notes** | |---|---|---| | vxWorks 6.x dynamic link | example1.elf | The vxWorks PowerPC platforms use a dynamically loaded object without the kernel. | | Linux | example1.bin | | @@ -464,7 +415,7 @@ is built for. Depending on the Target, it is usually straightforward to run an OSAL Application on a target platform. On desktop platforms, it is just a matter of running the executable program. On vxWorks, the example -programs are loadable modules. +programs are loadable modules. ### Load the OSAL Application Executable on the Target @@ -475,7 +426,7 @@ targets, the Application can be loaded into the EEPROM or Flash disk after the vxWorks kernel is booted. On RTEMS targets, the Application can be loaded using the CEXP dynamic loader or it can be linked in with an RTEMS Binary. See the target specific sections for details on each -platform. +platform. ### Setup the Target File Systems @@ -484,7 +435,7 @@ deal with different file system types and different paths. The OSAL accomplishes this by using a file system abstraction. The abstracted OSAL file system is similar to a UNIX file system, where the root directory starts with "/" and all disks are mounted on directory trees. -For example: +For example: - /ram0/apps/ RAM disk 0, apps subdirectory @@ -499,106 +450,85 @@ Using the host vxWorks tools, the path to the same file would be: development workstation, the file might be located at: "/tmp/ramdev1/data/datafile1.dat". The important part is that the OSAL Application can access the files using a generic path, allowing the -software to remain portable. +software to remain portable. There are a few ways to map these host file systems to OSAL file -systems: +systems: - **Map existing target file systems to a OSAL path**. This is one of the most common ways to map the Non-Volatile disk to the OSAL. The OSAL relies on the target OS to create/mount a file system and it simply is -given a mapping to the disk to allow the OSAL to access it. +given a mapping to the disk to allow the OSAL to access it. - **Create EEPROM/Flash/ATA File systems**. The OSAL has the ability on some targets to format or initialize a EEPROM or ATA disk device. -This is less commonly used. +This is less commonly used. - **Create RAM File Systems**. The OSAL can create RAM disks on the vxWorks targets. The OSAL will create or re-initialize the RAM disk for -the vxWorks targets. +the vxWorks targets. + +#### OSAL File system mapping + +In new OSAL versions, no filesystem mappings are assumed or "hard-coded" by +default. OSAL no longer requires a Volume Table object to be provided by the +application to specify the fixed filesystem mappings. + +Instead, the application is expected to configure all required file system +mappings via API calls during its startup. This may be done any time after calling +`OS_API_Init()`. -**RTEMS Note**: The RTEMS OS provides a base file system, called IMFS -that provides the root directory. Because this closely matches what the -OSAL file system abstraction provides, the RTEMS directories and -filenames are a one to one mapping. In other words the path on RTEMS is -the same as the path in the OSAL. +For example, for Core Flight System (cFS) configurations that require persistent +storage to be provided under a virual directory called `/cf`, the platform-specific +CFE PSP layer configures the mapping in an appropriate manner by calling +the `OS_FileSysAddFixedMap()` API during its OS_Application_Startup() implementation. The following table shows examples of these file system mappings on various hosts. **Note** the change in the way the POSIX ports are mapped. Linux will no longer remove or create sub-directories based on the volume name. The path mapping for the FS_BASED option is now a simple mapping from an OSAL path to a host path. This makes the OSAL -easier to use on linux platforms: - -#### OSAL File system mapping - -| **Target Operating system** | **cFE File system path** | **Target OS File system path** | **Notes** | -|---|---|---|---| -| vxWorks 6.x | /ram | RAM:0/ | Most vxWorks targets | -| | /cf | CF:0/ or CF:1/ | MCP750| -|| /cf | EEP:0/| RAD750 target | -| Linux | /ram | ./ram0 | Note the "." This will map the RAM disk to the current working directory + the "ram0" subdirectory. | -|| /cf | ./cf | Again, starts with the current working directory. | -| RTEMS | /ram | /ram | RTEMS has 1-1 mapping with the OSAL | -|| /cf | /cf || +easier to use on linux platforms: ### Start the OSAL Application on the Target -Starting an OSAL Application is a highly target dependant activity. The +Starting an OSAL Application is a highly target-dependent activity. The following table gives examples of how to start an Application on various -platforms. For full details see the notes for each section. +platforms. For full details see the notes for each section. #### How to start an OSAL Application on Various Target Systems: | **"Target" operating system** | **How to start the cFE** | |---|---| -|RTEMS / mcf5235 | Loaded through GDB/BDM using a shell script: "debug.sh" | +|RTEMS / mcf5235 | Loaded through GDB/BDM using a shell script: "debug.sh" | | RTEMS / SIS | Loaded through GDB/SIS simulator: \$ sparc-rtems4.10-gdb tasking-example.n (gdb) target sim (gdb) load (gdb) run | | vxWorks 6.2 / RAD750 | Started from the vxWorks Target Shell commands: Vx\> ld \< tasking-example.elf Vx\> OS_BSPMain | | Linux | Start directly from the linux shell: \$ ./tasking-example.bin | -# Target Specific Instructions +# Target Specific Instructions This section provides details on how to load and run each of the -supported OSAL configurations. - -## Generic PPC / vxWorks 6.4 Platform: - -The Generic PPC applications will work on both the Motorola MCP750 and -the BAE RAD750 running vxWorks 6.4. On this platform, the OSAL -Applications are built as dynamic loadable vxWorks modules, rather than -being linked to the vxWorks kernel/BSP. The OSAL Applications are loaded -into the compact flash disk on the MCP750, so it can be started from a -vxWorks shell or startup script after the kernel comes up. +supported OSAL configurations. -### OSAL Configuration for the Generic PPC / VxWorks 6.4 +## Generic vxWorks Platform: -#### osal-config.mak Settings +The test applications are tested on the Motorola MCP750 running vxWorks 6.9, +but should work similarly on other platforms/versions. -| **osal-config.mak variable** | **Required selection** | **Notes** | - |---|---|---| -| OS | vxworks6 || -| BSP | genppc-vxworks6.4|| +On this platform, the OSAL Applications are built as dynamic loadable vxWorks +modules, rather than being linked to the vxWorks kernel/BSP. The OSAL Applications +are loaded into the compact flash disk on the MCP750, so it can be started from a +vxWorks shell or startup script after the kernel comes up. -### File System Mappings on the MCP750 PPC Board - -The cFE uses the following file system mappings for the MCP750 PPC -Board. The file system mappings are defined in the bsp_voltab.c file in -the src/arch/ppc/genppc/vxworks6.4/bsp directory: - -#### OSAL File System Mappings - -| **OSAL "device"** | **File System Type** | **OSAL Path** | **Host Path** | **Notes** | -|---|---|---|---|---| -| /ramdev0|Real RAM Disk ( vxWorks )|/ram|RAM:0/| -| /eedev0|File System Mapped (FS_BASED)|/cf|eep:0/|This is the Compact Flash drive on the MCP750| -|/ramdev1 -- /ramdev5|Real RAM Disk|N/A|N/A|Unused table entries for applications to create new RAM disks| -| /ssedev0 - /ssrdev2|File System Mapped (FS_BASED)|N/A|/ssr:0/SSR1 - /ssr:0/SSR3|Unused table entries for applications to map Hard Disk device directories to "pseudo" SSR file systems.| +Building for this platform requires use of a CMake toolchain to specify the +correct cross compiler and configuration to use. For examples of toolchain +files including a toolchain file that may be used to build this platform, see +the NASA cFS software repository. ### How to run the OSAL Applications on the MCP750 or RAD750 -1\. Load the kernel. The custom vxWorks kernel is loaded into the MCP750 +1. Load the kernel. The custom vxWorks kernel is loaded into the MCP750 via TFTP. We use a vxWorks boot image (Rather than the Motorola boot monitor/loader ) to boot the MCP750 board, TFTP the "real" kernel to RAM, and execute it. This vxWorks boot image also sets the network @@ -606,253 +536,177 @@ settings for the "real" kernel image. On our OSAL/cFE development system, we keep the loadable vxWorks kernel image in a TFTP directory on the development workstation. So the vxWorks kernel image goes in /tftpboot/cpu1/cfecpu1.st. **( \$ cp -/opt/workspace/mcp750image/default/vxWorks /tftpboot/cpu1/cfecpu1.st )** +/opt/workspace/mcp750image/default/vxWorks /tftpboot/cpu1/cfecpu1.st )** -2\. Copy the "example1.elf" ( or other executable name ) loadable module +2. Copy the application program file ( or other executable name ) loadable module into the non-volatile disk. On the MCP750, this is done simply by FTPing -the tasking-example.elf file to the target: +the file to the target: ``` $ ftp 192.168.1.4 -ftp\> username: target +ftp> username: target -ftp\> password: password +ftp> password: password -ftp\> cd "CF:0" +ftp> cd "CF:0" -ftp\> binary +ftp> binary -ftp\> put tasking-example.elf +ftp> put tasking-example.elf ``` -3\. Load the example Application in the vxWorks shell: +3. Load the example Application in the vxWorks shell: ``` -vx\> cd "CF:0" +vx> cd "CF:0" -vx\> ld \< tasking-example.elf +vx> ld < tasking-example.elf ``` -4\. Run the example Application in the vxWorks shell: +4. Run the example Application in the vxWorks shell: ``` -vx\> OS_BSPMain +vx> OS_BSPMain ``` (The entry point for the examples and test programs is always -OS_BSPMain) +OS_BSPMain) -## Axiom M5235 BCC / RTEMS 4.10: +## QEMU + pc686 / RTEMS 4.11 - 5.x: -The OSAL supports the Axiom 5235 BCC single board computer with an RTEMS -4.10 board support package. The 4.10.2 version of RTEMS was used (as of -December 2012) along with the RTEMS 4.10 compiler for the m68k/coldfire. -The tests and examples are built as static RTEMS executable programs for -the board and can be loaded using the DBUG monitor or BDM port. When -developing for RTEMS, the libraries and BSP code is usually located in -/opt/rtems-4.10. The OSAL Makefiles use an environment variable -"RTEMS_BSP_BASE" to determine where the RTEMS libraries and BSPs are -installed. This variable is set from the "setvars.sh" file along with an -example of how to set the variable.. +OSAL supports the RTEMS OS, which can be easily tested without any specific +hardware using the QEMU hypervisor/virtualization software. This relies +on using the "pc-rtems" BSP. -### OSAL Configuration for the Axiom M5235 BCC / RTEMS 4.10 +Like VxWorks, this requires use of a cross compile toolchain to build +applications for this target. Example toolchains can also be found in the +NASA cFS project(s). -#### osal-config.mak Settings - -| **osal-config.mak variable** | **Required selection** | **Notes** | -|---|---|---| -| OS|rtems|| -| BSP|rtems-mcf5235|| +In particular the OS_SYSTEM_BSPTYPE should be set to "pc-rtems" by the toolchain +to enable this BSP/OS abstraction layer. +### How to run the OSAL Applications on QEMU with RTEMS 4.11 - 5.x -### File System Mappings on the Axiom M5235 BCC / RTEMS 4.10 +By default, RTEMS applications are built as a single, monolithic kernel + application +image. This simplifies development and testing. However, even in the default setup, +applications may still utilize the module load API to extend or replace logic. However, +by modifying the BSP and build rules, the kernel can also be built separately, with +the application also built as a loadable module. -The RTEMS port of the OSAL has a one to one file system mapping. The -OSAL RAM disk will format an RTEMS NVRAM disk with the RFS file -system.The file system mappings are defined in the bsp_voltab.c file in -the src/bsp/mcf5235-rtems/src directory: +The monolithic image is trivial to boot in the QEMU hypervisor, as follows: -#### OSAL File System Mappings - - |**OSAL "device"**|**File System Type**|**OSAL Path**|**Host Path**| **Notes**| -|---|---|---|---|---| -| /ramdev0|RAM_DISK ( NVRAM/RFS )|/ram|/ram|Mapped to the IMFS root directory| -| /eedev0|File System Mapped (FS_BASED)|/cf|/cf|Mapped to the IMFS root directory| -| /ramdev1 -- /ramdev5|Unused|N/A|N/A|Unused table entries for applications to create new RAM disks. RTEMS does not currently have support for creating new RAM disks.| -| /ssedev0 - /ssrdev2|File System Mapped (FS_BASED)|N/A|N/A|Unused table entries for applications to map Hard Disk device directories to "pseudo" SSR file systems.| - -### How to run the OSAL Applications on the Axiom M5235 BCC with RTEMS 4.10 - -When the example application and test programs are all built as static -executables for the M5235BCC board. The example programs can be loaded -in the following ways: - -Using the BDM port through the GNU debugger. If the board is connected -to the host PC with a BDM debugger cable, then the example programs can -be loaded and run from there. For our environment we use the Gnu -Debugger that was included with the RTEMS 4.10 tools and the -m68k-bdm-gdbserver from the BDM Tools project: - . The gdb-init script and a debug.sh -file are included in the src/bsp/mcf5235-rtems/bsp/rtems-support -directories. The debug.sh script gives the proper command line to load -the application to the board using the GDB debugger and BDM interface. - -## SPARC SIS Simulator / RTEMS 4.10: - -The OSAL supports the SPARC SIS simulator built into GDB with the sis -RTEMS 4.10 board support package. The 4.10.1 version of RTEMS was used -(as of December 2011) along with the RTEMS 4.10 compiler for the sparc. -The tests and examples are built as static RTEMS executable programs for -the simulator. The OSAL Makefiles use an environment variable -"RTEMS_BSP_BASE" to determine where the RTEMS libraries and BSPs are -installed. This variable is set from the "setvars.sh" file along with an -example of how to set the variable. - -### OSAL Configuration for the SPARC SIS Simulator / RTEMS 4.10 - -#### osal-config.mak Settings - - | **osal-config.mak variable** | **Required selection** | **Notes**| -|---|---|---| -| OS|rtems|| -| BSP|sis-rtems|| - -### File System Mappings on the SPARC SIS Simulator / RTEMS 4.10 - -The RTEMS port of the OSAL has a one to one file system mapping. The -OSAL RAM disk will format an RTEMS NVRAM disk with the RFS file system. -The file system mappings are defined in the bsp_voltab.c file in the -src/bsp/sis-rtems/src directory: - -#### OSAL File System Mappings - -| **OSAL "device"**|**File System Type**|**OSAL Path** | **Host Path** | **Notes**| -|---|---|---|---|---| -| /ramdev0 |RAM_DISK ( NVRAM/RFS )|/ram|/ram|Mapped to the IMFS root directory| -| /eedev0|File System Mapped (FS_BASED)|/cf|/cf|Mapped to the IMFS root directory| -| /ramdev1 -- /ramdev5|Unused|N/A|N/A|Unused table entries for applications to create new RAM disks. RTEMS does not currently have support for creating new RAM disks.| -| /ssedev0 - /ssrdev2|File System Mapped (FS_BASED)|N/A|N/A|Unused table entries for applications to map Hard Disk device directories to "pseudo" SSR file systems.| - -### How to run the OSAL Applications on the SPARC SIS Simulator with RTEMS 4.10 - -When the example application and test programs are all built as static -executables for the SIS Simulator built into the sparc-rtems4.10-gdb -executable. - -To run an example or test, simply do the following: ``` -**\$ sparc-rtems4.10-gdb tasking-example.nxe** - -**(gdb) target sim** - -**(gdb) load** - -**(gdb) run** +qemu-system-i386 -m 128 -no-reboot -display none -serial stdio \ + -kernel .exe ``` -When you are finished running/debugging, hit \-c and quit the -debugger. +Where `.exe` refers to any of the test programs or applications +that are provided with OSAL. This command puts the virual console on +the same terminal where the QEMU emulator is started. The program +should run automatically after the kernel boots. The system may be +stopped by issuing the "shutdown" command at the shell, or by pressing +the CTRL+A followed by CTRL+C which terminates QEMU. -## PC / Linux Platform +## Generc Linux Platform -The OSAL can run on linux distributions. Testing is done with CentOS 6.5 -32 bit and Ubuntu 13.10 64 bit. Newer versions of the Linux 2.6 -kernel have POSIX message queues, which can be used for the OSAL Queue -implementation. If the POSIX message queues are not available, then the -OSAL Queues can use UDP sockets. (see the OS_SOCKET_QUEUE configuration -parameter). In general, the older versions of linux (2.4 kernel) are not -supported, but most modern Linux releases such as Ubuntu 12.10 and -later, and Cent OS/Redhat Enterprise Linux 5 and later should work. The -OSAL has also been used on the Raspberry Pi computer with the Raspbian -Debian based linux. The OSAL is primarily run on 32 bit linux -distributions, but it should compile and run as a 32 bit application on -64 bit linux. +The OSAL can run on many Linux distributions. Testing is done with currently +supported Ubuntu LTS versions (up through 20.04 at the time of the current +release) as well as supported RHEL/CentOS versions (7.x and 8.x series), +and Linux-based embedded development boards such as the Raspberry Pi and +BeagleBone series. -### OSAL Configuration for the PC / Linux Platform +The generic-linux BSP should also operate with customized Linux builds +built from the Yocto/OpenEmbedded development environment, Buildroot, or +PTXdist. Any reasonably recent Linux kernel/library version should work, +however it must have support for native POSIX threads (NPTL) and POSIX +message queues (mqueue). -#### osal-config.mak Settings - -| **Prolog.mak variable** | **Required selection** | **Notes**| -|---|---|---| -| OS|posix|| -| BSP|pc-linux|| - -Additional configuration notes: - -To enable the POSIX message queues, make sure the OS_SOCKET_QUEUE -parameter is not defined in osconfig.h. - -If the OS_SOCKET_QUEUE option is not used, the OSAL will use POSIX -message queues. If POSIX message queues are used, your application may -need to run as root in order to create the queues you need. There are -kernel parameters that can be adjusted in order to avoid running as -root. ### How to Run the OSAL on the PC / Linux Platform -1\. To run an OSAL Application, simply execute the binary from a shell -prompt: +1. To run an OSAL Application, simply execute the binary from a shell +prompt: ``` -build/examples/tasking-example\]\$ ./tasking-example.bin +build/examples/tasking-example$ ./tasking-example.bin ``` -# OSAL Unit Tests +# OSAL Unit Tests and UT assert The OSAL distribution includes a suite of black box unit tests, white box unit tests (/src/unit-test-coverage), and functional tests (/src/tests). Tam Ngo at NASA Johnson Space Flight Center developed the -suite of black box unit tests located in the /src/unit_tests directory. -This section describes how to build and run the suite of black box unit -tests using the "classic" build. Note: it is assumed the steps in -Section 2 How to Configure, Build, and Run the OSAL have been followed -to setup the build environment for the "classic" build. The unit tests -run on Linux, but could also be configured to run on other operating -systems (and will in future releases). - -Currently the osprintf tests are not compiled and run, and the ARINC 653 -tests are not used. A future release of the OSAL will contain support -for the ARINC653 operating system API. - -## OSAL Unit Test Configuration for the PC / Linux Platform - -#### osal-config.mak Settings - -| **Prolog.mak variable** | **Required selection** | **Notes**| -|---|---|---| -|OS|posix|Unit tests are for the POSIX port| -| BSP|pc-linux-ut|This is a special BSP for the unit tests| +suite of black box unit tests located in the /src/unit-tests directory. + +Additionally, OSAL provides a framework for testing called "UT assert". +The test framework actually uses some of the OSAL BSP facilities to +execute the tests in a platform-independent manner. + +Unit tests are built based on the `ENABLE_UNIT_TESTS` CMake configuration +variable. When this is set to TRUE, extra test programs are built to +validate all of OSAL functionality. + +The "black box" functional tests under /src/tests and /src/unit-tests +operate with an unmodified OSAL library, using a real instance of the OSAL +to run the tests. + +The "white box" coverage test under /src/unit-test-coverage does not use +OSAL, it only uses the BSP for start up and low-level console access, +combined with UT assert for the basic framework. In this testing mode, +each OSAL subsystem is specially compiled with special flags to enable +profiling (to track line and branch coverage) and linked with _stub_ +implementations of all other dependencies. This way, test cases can +trigger error paths from library calls that would otherwise not be possible +in a black box test enviornment. + +These test programs are executed just as any other application program. + +Complete coverage testing is only available for the "shared" layer and +the "VxWorks" low level implementation layer. However, because all platforms +share the same "shared" layer, this coverage test applies to all platforms. +The low level (OS-specific) implementation layers should be only to translate +the OSAL calls to the specific C library/OS API provided by that platform, +while all basic state/table maintenance and error checking is performed at +the shared layer. + +**Note**: The coverage tests are built for the same platform as all other +applications. Notably, because the coverage test does not actually use +the facilities provided by the OS (all OS calls are replaced with stubs), +the OS-specific coverage test can execute on any platform, it is not limited +to running on the platform that it is abstracting. As a result, the VxWorks +coverage test is typically executed on a Linux host. ## How to Run the OSAL Unit Tests on the PC / Linux Platform To build and run the OSAL unit tests, run the following commands from -the "build" directory: +the "build" directory: #### Build Commands | **Shell command** | **Description**| |---|---| -| **\$ cd build**|Change to the build directory.| -| **\$ make clean-unit-tests**| Clean the OSAL Core, and all Applications| -|**\$ make config**|Copy the osconfig.h for the BSP to the build directory| -| **\$ make unit-tests**|Build all of the unit tests.| -| **\$ make gcov**|Run the unit tests, collecting code coverage information.| +| `$ cd build/unit-test-coverage` | Change to the build directory containing coverage tests | +| `$ make` | Build the OSAL Core, and all tests | +| `$ make test` | Execute all of the tests programs | -Once the unit tests have run, the log files are available in the -individual unit test binary directories +Note that the "ctest" program shows a quiet output by default, indicating only the test name +and a pass/fail status. To see a complete log of tests executed, the test program may be run +directly from the command line. #### OSAL Unit Test Directories | **Directory**|**Description**| |---|---| - | build|The top level OSAL build directory.| - | build/unit-tests|The top level unit test build directory.| - | build/unit-tests/oscore-test|Contains the test binary, log, and gcov files for the OSAL core tests| | build/unit-tests/osfile-test|Contains the test binary, log, and gcov files for the OSAL file API tests| - | build/unit-tests/osfilesys-test|Contains the test binary, log, and gcov files for the OSAL file system tests| - | build/unit-tests/osloader-test|Contains the test binary, log, and gcov files for the OSAL loader tests| - |build/unit-tests/ostimer-test|Contains the test binary, log, and gcov files for the OSAL timer tests| + | `build` | The top level OSAL build directory. | + | `build/unit-tests` | The top level unit test build directory. | + | `build/unit-tests/oscore-test` | Contains the test binary, log, and gcov files for the OSAL core tests | + | `build/unit-tests/osfile-test` | Contains the test binary, log, and gcov files for the OSAL file API tests | + | `build/unit-tests/osfilesys-test` | Contains the test binary, log, and gcov files for the OSAL file system tests | + | `build/unit-tests/osloader-test` | Contains the test binary, log, and gcov files for the OSAL loader tests | + | `build/unit-tests/osnetwork-test` | Contains the test binary, log, and gcov files for the OSAL network tests | + | `build/unit-tests/ostimer-test` | Contains the test binary, log, and gcov files for the OSAL timer tests | # Revision History From b9c9b29d35c2a25738652cc36891130be3361ec4 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 4 May 2021 10:09:21 -0400 Subject: [PATCH 4/9] Fix #331, scrub return values Confirm consistency between the return values generated by each OSAL API and the doxygen documentation. Each explicitly-returned status code should have a corresponding "retval" entry in the documentation. Also confirms that each explicitly-returned status code has a matching case in the coverage tests that specifically checks for that return value. Some were actually missing, where as some were just being reported incorrectly. Finally this also corrects one argument name mismatch in QueueCreate where it was prototyped as "data_size" but implemented as "max_size". --- src/os/inc/osapi-clock.h | 2 ++ src/os/inc/osapi-common.h | 3 +- src/os/inc/osapi-dir.h | 2 ++ src/os/inc/osapi-error.h | 3 ++ src/os/inc/osapi-file.h | 8 +++++ src/os/inc/osapi-filesys.h | 17 ++++++++++ src/os/inc/osapi-heap.h | 1 + src/os/inc/osapi-idmap.h | 2 ++ src/os/inc/osapi-module.h | 2 ++ src/os/inc/osapi-network.h | 2 ++ src/os/inc/osapi-queue.h | 1 + src/os/inc/osapi-select.h | 4 +++ src/os/inc/osapi-shell.h | 1 + src/os/inc/osapi-sockets.h | 14 +++++++++ src/os/inc/osapi-task.h | 2 ++ src/os/inc/osapi-timebase.h | 9 ++++++ src/os/inc/osapi-timer.h | 5 +++ src/os/shared/src/osapi-queue.c | 6 ++-- .../shared/src/coveragetest-errors.c | 9 ++---- .../shared/src/coveragetest-file.c | 10 +++--- .../shared/src/coveragetest-filesys.c | 8 +++++ .../shared/src/coveragetest-idmap.c | 31 ++++++++++++++++--- .../shared/src/coveragetest-network.c | 9 ++---- .../shared/src/coveragetest-select.c | 2 ++ .../shared/src/coveragetest-sockets.c | 3 ++ .../shared/src/coveragetest-time.c | 13 ++------ .../shared/src/coveragetest-timebase.c | 8 +++-- 27 files changed, 135 insertions(+), 42 deletions(-) diff --git a/src/os/inc/osapi-clock.h b/src/os/inc/osapi-clock.h index e13d06635..e620adc13 100644 --- a/src/os/inc/osapi-clock.h +++ b/src/os/inc/osapi-clock.h @@ -83,6 +83,7 @@ enum * @param[out] time_struct An OS_time_t that will be set to the current time * * @return Get local time status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if time_struct is null */ int32 OS_GetLocalTime(OS_time_t *time_struct); @@ -97,6 +98,7 @@ int32 OS_GetLocalTime(OS_time_t *time_struct); * @param[in] time_struct An OS_time_t containing the current time * * @return Set local time status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if time_struct is null */ int32 OS_SetLocalTime(const OS_time_t *time_struct); diff --git a/src/os/inc/osapi-common.h b/src/os/inc/osapi-common.h index d910a2aa6..d81613240 100644 --- a/src/os/inc/osapi-common.h +++ b/src/os/inc/osapi-common.h @@ -162,8 +162,6 @@ int32 OS_API_Init(void); * For example, while this will attempt to unload all dynamically-loaded modules, doing * so may not be possible and/or may induce undefined behavior if resources are in use by * tasks/functions outside of OSAL. - * - * @return None */ void OS_API_Teardown(void); @@ -234,6 +232,7 @@ void OS_ApplicationExit(int32 Status); * @return Execution status, see @ref OSReturnCodes. * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERROR @copybrief OS_ERROR + * @retval #OS_INVALID_POINTER if handler is NULL */ int32 OS_RegisterEventHandler(OS_EventHandler_t handler); diff --git a/src/os/inc/osapi-dir.h b/src/os/inc/osapi-dir.h index 4d7963ca0..7b2acf0f7 100644 --- a/src/os/inc/osapi-dir.h +++ b/src/os/inc/osapi-dir.h @@ -57,6 +57,7 @@ typedef struct * @param[in] path The directory to open * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if dir_id or path is NULL */ int32 OS_DirectoryOpen(osal_id_t *dir_id, const char *path); @@ -94,6 +95,7 @@ int32 OS_DirectoryRewind(osal_id_t dir_id); * @param[out] dirent Buffer to store directory entry information * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if dirent argument is NULL */ int32 OS_DirectoryRead(osal_id_t dir_id, os_dirent_t *dirent); diff --git a/src/os/inc/osapi-error.h b/src/os/inc/osapi-error.h index b94982993..3b1b85fe2 100644 --- a/src/os/inc/osapi-error.h +++ b/src/os/inc/osapi-error.h @@ -116,6 +116,9 @@ typedef char os_err_name_t[OS_ERROR_NAME_LENGTH]; * @param[out] err_name Buffer to store error string * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_SUCCESS if successfully converted to a string + * @retval #OS_INVALID_POINTER if err_name is NULL + * @retval #OS_ERROR if error could not be converted */ int32 OS_GetErrorName(int32 error_num, os_err_name_t *err_name); /**@}*/ diff --git a/src/os/inc/osapi-file.h b/src/os/inc/osapi-file.h index 0b05b1df6..71b1b9007 100644 --- a/src/os/inc/osapi-file.h +++ b/src/os/inc/osapi-file.h @@ -135,6 +135,7 @@ typedef enum * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERROR if the command was not executed properly + * @retval #OS_INVALID_POINTER if pointer argument was NULL */ int32 OS_OpenCreate(osal_id_t *filedes, const char *path, int32 flags, int32 access_mode); @@ -236,6 +237,8 @@ int32 OS_write(osal_id_t filedes, const void *buffer, size_t nbytes); * @returns Byte count on success or appropriate error code, see @ref OSReturnCodes * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid + * @retval #OS_ERR_INVALID_SIZE if the passed-in size is not valid + * @retval #OS_INVALID_POINTER if the passed-in buffer is not valid * @retval 0 if at end of file/stream data */ int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout); @@ -269,6 +272,8 @@ int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout * @return A non-negative byte count or appropriate error code, see @ref OSReturnCodes * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid + * @retval #OS_ERR_INVALID_SIZE if the passed-in size is not valid + * @retval #OS_INVALID_POINTER if the passed-in buffer is not valid * @retval 0 if file/stream cannot accept any more data */ int32 OS_TimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, int32 timeout); @@ -432,6 +437,7 @@ int32 OS_mv(const char *src, const char *dest); * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid + * @retval #OS_INVALID_POINTER if the fd_prop argument is NULL */ int32 OS_FDGetInfo(osal_id_t filedes, OS_file_prop_t *fd_prop); @@ -446,6 +452,7 @@ int32 OS_FDGetInfo(osal_id_t filedes, OS_file_prop_t *fd_prop); * * @return OS_SUCCESS if the file is open, or appropriate error code * @retval #OS_ERROR if the file is not open + * @retval #OS_INVALID_POINTER if the filename argument is NULL */ int32 OS_FileOpenCheck(const char *Filename); @@ -475,6 +482,7 @@ int32 OS_CloseAllFiles(void); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_FS_ERR_PATH_INVALID if the file is not found * @retval #OS_ERROR if the file close returned an error + * @retval #OS_INVALID_POINTER if the filename argument is NULL */ int32 OS_CloseFileByName(const char *Filename); /**@}*/ diff --git a/src/os/inc/osapi-filesys.h b/src/os/inc/osapi-filesys.h index c9d0d567b..c1790e3f9 100644 --- a/src/os/inc/osapi-filesys.h +++ b/src/os/inc/osapi-filesys.h @@ -84,6 +84,9 @@ typedef struct * @param[in] virt_path The virtual mount point of this filesystem * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_FS_ERR_PATH_TOO_LONG if the overall phys_path is too long + * @retval #OS_ERR_NAME_TOO_LONG if the phys_path basename (filesystem name) is too long + * @retval #OS_INVALID_POINTER if any argument is NULL */ int32 OS_FileSysAddFixedMap(osal_id_t *filesys_id, const char *phys_path, const char *virt_path); @@ -113,6 +116,7 @@ int32 OS_FileSysAddFixedMap(osal_id_t *filesys_id, const char *phys_path, const * @retval #OS_SUCCESS on creating the disk */ int32 OS_mkfs(char *address, const char *devname, const char *volname, size_t blocksize, osal_blockcount_t numblocks); + /*-------------------------------------------------------------------------------------*/ /** * @brief Mounts a file system @@ -123,6 +127,9 @@ int32 OS_mkfs(char *address, const char *devname, const char *volname, size_t bl * @param[in] mountpoint The name to call this disk from now on * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_ERR_NAME_NOT_FOUND if the device name does not exist in OSAL + * @retval #OS_FS_ERR_PATH_TOO_LONG if the mount point string is too long + * @retval #OS_INVALID_POINTER if any argument is NULL */ int32 OS_mount(const char *devname, const char *mountpoint); @@ -165,6 +172,8 @@ int32 OS_initfs(char *address, const char *devname, const char *volname, size_t * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if devname is NULL + * @retval #OS_FS_ERR_PATH_TOO_LONG if the devname is too long + * @retval #OS_ERR_NAME_NOT_FOUND if the devname does not exist in OSAL * @retval #OS_ERROR is the drive specified cannot be located */ int32 OS_rmfs(const char *devname); @@ -185,6 +194,7 @@ int32 OS_rmfs(const char *devname); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if name is NULL * @retval #OS_FS_ERR_PATH_TOO_LONG if the absolute path given is too long + * @retval #OS_ERR_NAME_NOT_FOUND if the mountpoint is not mounted in OSAL * @retval #OS_ERROR if the OS calls failed */ int32 OS_unmount(const char *mountpoint); @@ -209,6 +219,7 @@ int32 OS_unmount(const char *mountpoint); * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if name or statbuf is NULL + * @retval #OS_FS_ERR_PATH_TOO_LONG if the name is too long * @retval #OS_ERROR if the OS call failed */ int32 OS_FileSysStatVolume(const char *name, OS_statvfs_t *statbuf); @@ -228,6 +239,7 @@ int32 OS_FileSysStatVolume(const char *name, OS_statvfs_t *statbuf); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER Name is NULL * @retval #OS_ERR_NOT_IMPLEMENTED @copybrief OS_ERR_NOT_IMPLEMENTED + * @retval #OS_FS_ERR_PATH_TOO_LONG if the name is too long * @retval #OS_ERROR @copybrief OS_ERROR */ int32 OS_chkfs(const char *name, bool repair); @@ -245,6 +257,8 @@ int32 OS_chkfs(const char *name, bool repair); * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if either parameter is NULL + * @retval #OS_ERR_NAME_NOT_FOUND if the MountPoint is not mounted in OSAL + * @retval #OS_FS_ERR_PATH_TOO_LONG if the MountPoint is too long * @retval #OS_ERROR if the mountpoint could not be found */ int32 OS_FS_GetPhysDriveName(char *PhysDriveName, const char *MountPoint); @@ -261,6 +275,9 @@ int32 OS_FS_GetPhysDriveName(char *PhysDriveName, const char *MountPoint); * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if either parameter is NULL + * @retval #OS_FS_ERR_NAME_TOO_LONG if the filename component is too long + * @retval #OS_FS_ERR_PATH_INVALID if either parameter cannot be interpreted as a path + * @retval #OS_FS_ERR_PATH_TOO_LONG if either input or output pathnames are too long */ int32 OS_TranslatePath(const char *VirtualPath, char *LocalPath); diff --git a/src/os/inc/osapi-heap.h b/src/os/inc/osapi-heap.h index 690b95e82..5313bfdd3 100644 --- a/src/os/inc/osapi-heap.h +++ b/src/os/inc/osapi-heap.h @@ -53,6 +53,7 @@ typedef struct * @param[out] heap_prop Storage buffer for heap info * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if the heap_prop argument is NULL */ int32 OS_HeapGetInfo(OS_heap_prop_t *heap_prop); /**@}*/ diff --git a/src/os/inc/osapi-idmap.h b/src/os/inc/osapi-idmap.h index 345446227..d0f7c1fb1 100644 --- a/src/os/inc/osapi-idmap.h +++ b/src/os/inc/osapi-idmap.h @@ -228,6 +228,8 @@ int32 OS_ConvertToArrayIndex(osal_id_t object_id, osal_index_t *ArrayIndex); * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INCORRECT_OBJ_TYPE @copybrief OS_ERR_INCORRECT_OBJ_TYPE + * @retval #OS_ERR_INVALID_ID if the object_id argument is not valid + * @retval #OS_INVALID_POINTER if the ArrayIndex is NULL * */ int32 OS_ObjectIdToArrayIndex(osal_objtype_t idtype, osal_id_t object_id, osal_index_t *ArrayIndex); diff --git a/src/os/inc/osapi-module.h b/src/os/inc/osapi-module.h index 634b981b2..25cbd14da 100644 --- a/src/os/inc/osapi-module.h +++ b/src/os/inc/osapi-module.h @@ -174,6 +174,7 @@ int32 OS_ModuleSymbolLookup(osal_id_t module_id, cpuaddr *symbol_address, const * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_NOT_IMPLEMENTED @copybrief OS_ERR_NOT_IMPLEMENTED + * @retval #OS_INVALID_POINTER if the filename argument is NULL * @retval #OS_ERROR if the symbol table could not be read or dumped */ int32 OS_SymbolTableDump(const char *filename, size_t size_limit); @@ -199,6 +200,7 @@ int32 OS_SymbolTableDump(const char *filename, size_t size_limit); * @retval #OS_INVALID_POINTER if one of the parameters is NULL * @retval #OS_ERR_NO_FREE_IDS if the module table is full * @retval #OS_ERR_NAME_TAKEN if the name is in use + * @retval #OS_ERR_NAME_TOO_LONG if the module_name is too long */ int32 OS_ModuleLoad(osal_id_t *module_id, const char *module_name, const char *filename, uint32 flags); diff --git a/src/os/inc/osapi-network.h b/src/os/inc/osapi-network.h index bce88e364..a805ef80b 100644 --- a/src/os/inc/osapi-network.h +++ b/src/os/inc/osapi-network.h @@ -65,6 +65,8 @@ int32 OS_NetworkGetID(void); * @param[in] name_len Maximum length of host name buffer * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_ERR_INVALID_SIZE if the name_len is zero + * @retval #OS_INVALID_POINTER if the host_name is NULL */ int32 OS_NetworkGetHostName(char *host_name, size_t name_len); diff --git a/src/os/inc/osapi-queue.h b/src/os/inc/osapi-queue.h index 69a9222dc..14f9387d4 100644 --- a/src/os/inc/osapi-queue.h +++ b/src/os/inc/osapi-queue.h @@ -62,6 +62,7 @@ typedef struct * @retval #OS_ERR_NAME_TOO_LONG name length including null terminator greater than #OS_MAX_API_NAME * @retval #OS_ERR_NO_FREE_IDS if there are already the max queues created * @retval #OS_ERR_NAME_TAKEN if the name is already being used on another queue + * @retval #OS_ERR_INVALID_SIZE if data_size is 0 * @retval #OS_QUEUE_INVALID_SIZE if the queue depth exceeds the limit * @retval #OS_ERROR if the OS create call fails */ diff --git a/src/os/inc/osapi-select.h b/src/os/inc/osapi-select.h index e0c74a863..ac3b0c296 100644 --- a/src/os/inc/osapi-select.h +++ b/src/os/inc/osapi-select.h @@ -116,6 +116,7 @@ int32 OS_SelectMultiple(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs); * the OS_TimedRead/OS_TimedWrite calls. * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SelectSingle(osal_id_t objid, uint32 *StateFlags, int32 msecs); @@ -126,6 +127,7 @@ int32 OS_SelectSingle(osal_id_t objid, uint32 *StateFlags, int32 msecs); * After this call the set will contain no OSAL IDs * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SelectFdZero(OS_FdSet *Set); @@ -136,6 +138,7 @@ int32 OS_SelectFdZero(OS_FdSet *Set); * After this call the set will contain the given OSAL ID * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SelectFdAdd(OS_FdSet *Set, osal_id_t objid); @@ -146,6 +149,7 @@ int32 OS_SelectFdAdd(OS_FdSet *Set, osal_id_t objid); * After this call the set will no longer contain the given OSAL ID * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SelectFdClear(OS_FdSet *Set, osal_id_t objid); diff --git a/src/os/inc/osapi-shell.h b/src/os/inc/osapi-shell.h index c51169efd..613f75bc2 100644 --- a/src/os/inc/osapi-shell.h +++ b/src/os/inc/osapi-shell.h @@ -47,6 +47,7 @@ * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERROR if the command was not executed properly + * @retval #OS_INVALID_POINTER if Cmd argument is NULL * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid */ int32 OS_ShellOutputToFile(const char *Cmd, osal_id_t filedes); diff --git a/src/os/inc/osapi-sockets.h b/src/os/inc/osapi-sockets.h index 09e3b5a75..61ba847af 100644 --- a/src/os/inc/osapi-sockets.h +++ b/src/os/inc/osapi-sockets.h @@ -139,6 +139,7 @@ typedef struct * @param[in] Domain The address family * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if Addr argument is NULL */ int32 OS_SocketAddrInit(OS_SockAddr_t *Addr, OS_SocketDomain_t Domain); @@ -159,6 +160,8 @@ int32 OS_SocketAddrInit(OS_SockAddr_t *Addr, OS_SocketDomain_t Domain); * @param[in] Addr The network address buffer to convert * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL + * @retval #OS_ERR_INVALID_SIZE if passed-in buflen is not valid */ int32 OS_SocketAddrToString(char *buffer, size_t buflen, const OS_SockAddr_t *Addr); @@ -181,6 +184,7 @@ int32 OS_SocketAddrToString(char *buffer, size_t buflen, const OS_SockAddr_t *Ad * @param[in] string The string to initialize the address from. * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketAddrFromString(OS_SockAddr_t *Addr, const char *string); @@ -196,6 +200,7 @@ int32 OS_SocketAddrFromString(OS_SockAddr_t *Addr, const char *string); * @param[in] Addr The network address buffer * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketAddrGetPort(uint16 *PortNum, const OS_SockAddr_t *Addr); @@ -211,6 +216,7 @@ int32 OS_SocketAddrGetPort(uint16 *PortNum, const OS_SockAddr_t *Addr); * @param[out] Addr The network address buffer * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketAddrSetPort(OS_SockAddr_t *Addr, uint16 PortNum); /**@}*/ @@ -242,6 +248,7 @@ int32 OS_SocketAddrSetPort(OS_SockAddr_t *Addr, uint16 PortNum); * @param[in] Type The type of the socket (STREAM or DATAGRAM) * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketOpen(osal_id_t *sock_id, OS_SocketDomain_t Domain, OS_SocketType_t Type); @@ -260,6 +267,7 @@ int32 OS_SocketOpen(osal_id_t *sock_id, OS_SocketDomain_t Domain, OS_SocketType_ * @param[in] Addr The local address to bind to * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketBind(osal_id_t sock_id, const OS_SockAddr_t *Addr); @@ -276,6 +284,7 @@ int32 OS_SocketBind(osal_id_t sock_id, const OS_SockAddr_t *Addr); * @param[in] timeout The maximum amount of time to wait, or OS_PEND to wait forever * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if Addr argument is NULL */ int32 OS_SocketConnect(osal_id_t sock_id, const OS_SockAddr_t *Addr, int32 timeout); @@ -297,6 +306,7 @@ int32 OS_SocketConnect(osal_id_t sock_id, const OS_SockAddr_t *Addr, int32 timeo * @param[in] timeout The maximum amount of time to wait, or OS_PEND to wait forever * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL */ int32 OS_SocketAccept(osal_id_t sock_id, osal_id_t *connsock_id, OS_SockAddr_t *Addr, int32 timeout); @@ -314,6 +324,8 @@ int32 OS_SocketAccept(osal_id_t sock_id, osal_id_t *connsock_id, OS_SockAddr_t * * @param[in] timeout The maximum amount of time to wait, or OS_PEND to wait forever * * @return Count of actual bytes received or error status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL + * @retval #OS_ERR_INVALID_SIZE if passed-in buflen is not valid */ int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, int32 timeout); @@ -331,6 +343,8 @@ int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockA * @param[in] RemoteAddr Buffer containing the remote network address to send to * * @return Count of actual bytes sent or error status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL + * @retval #OS_ERR_INVALID_SIZE if passed-in buflen is not valid */ int32 OS_SocketSendTo(osal_id_t sock_id, const void *buffer, size_t buflen, const OS_SockAddr_t *RemoteAddr); diff --git a/src/os/inc/osapi-task.h b/src/os/inc/osapi-task.h index 6437f8f0f..53abde4c9 100644 --- a/src/os/inc/osapi-task.h +++ b/src/os/inc/osapi-task.h @@ -93,6 +93,7 @@ typedef osal_task((*osal_task_entry)(void)); /**< @brief For task entry point */ * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_INVALID_POINTER if any of the necessary pointers are NULL + * @retval #OS_ERR_INVALID_SIZE if the stack_size argument is zero * @retval #OS_ERR_NAME_TOO_LONG name length including null terminator greater than #OS_MAX_API_NAME * @retval #OS_ERR_INVALID_PRIORITY if the priority is bad * @retval #OS_ERR_NO_FREE_IDS if there can be no more tasks created @@ -234,6 +235,7 @@ int32 OS_TaskGetInfo(osal_id_t task_id, OS_task_prop_t *task_prop); * * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS + * @retval #OS_INVALID_POINTER if a pointer argument is NULL */ int32 OS_TaskFindIdBySystemData(osal_id_t *task_id, const void *sysdata, size_t sysdata_size); diff --git a/src/os/inc/osapi-timebase.h b/src/os/inc/osapi-timebase.h index 3d2dd74a6..0c5939feb 100644 --- a/src/os/inc/osapi-timebase.h +++ b/src/os/inc/osapi-timebase.h @@ -78,6 +78,9 @@ typedef struct * @param[in] external_sync A synchronization function for BSP hardware-based timer ticks * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context + * @retval #OS_ERR_NAME_TOO_LONG if the timebase_name is too long + * @retval #OS_INVALID_POINTER if a pointer argument is NULL */ int32 OS_TimeBaseCreate(osal_id_t *timebase_id, const char *timebase_name, OS_TimerSync_t external_sync); @@ -100,6 +103,8 @@ int32 OS_TimeBaseCreate(osal_id_t *timebase_id, const char *timebase_name, OS_Ti * @param[in] interval_time The amount of delay between ticks, in microseconds. * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context + * @retval #OS_TIMER_ERR_INVALID_ARGS if start_time or interval_time are out of range */ int32 OS_TimeBaseSet(osal_id_t timebase_id, uint32 start_time, uint32 interval_time); @@ -113,6 +118,7 @@ int32 OS_TimeBaseSet(osal_id_t timebase_id, uint32 start_time, uint32 interval_t * @param[in] timebase_id The timebase resource to delete * * @return Execution status, see @ref OSReturnCodes + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimeBaseDelete(osal_id_t timebase_id); @@ -130,6 +136,7 @@ int32 OS_TimeBaseDelete(osal_id_t timebase_id); * @retval #OS_INVALID_POINTER if timebase_id or timebase_name are NULL pointers * @retval #OS_ERR_NAME_TOO_LONG name length including null terminator greater than #OS_MAX_API_NAME * @retval #OS_ERR_NAME_NOT_FOUND if the name was not found in the table + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimeBaseGetIdByName(osal_id_t *timebase_id, const char *timebase_name); @@ -150,6 +157,7 @@ int32 OS_TimeBaseGetIdByName(osal_id_t *timebase_id, const char *timebase_name); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INVALID_ID if the id passed in is not a valid timebase * @retval #OS_INVALID_POINTER if the timebase_prop pointer is null + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimeBaseGetInfo(osal_id_t timebase_id, OS_timebase_prop_t *timebase_prop); @@ -182,6 +190,7 @@ int32 OS_TimeBaseGetInfo(osal_id_t timebase_id, OS_timebase_prop_t *timebase_pro * @return Execution status, see @ref OSReturnCodes * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INVALID_ID if the id passed in is not a valid timebase + * @retval #OS_INVALID_POINTER if pointer argument is NULL */ int32 OS_TimeBaseGetFreeRun(osal_id_t timebase_id, uint32 *freerun_val); diff --git a/src/os/inc/osapi-timer.h b/src/os/inc/osapi-timer.h index eaf9148d6..464e0f03c 100644 --- a/src/os/inc/osapi-timer.h +++ b/src/os/inc/osapi-timer.h @@ -151,6 +151,8 @@ int32 OS_TimerAdd(osal_id_t *timer_id, const char *timer_name, osal_id_t timebas * @retval #OS_ERR_INVALID_ID if the timer_id is not valid. * @retval #OS_TIMER_ERR_INTERNAL if there was an error programming the OS timer. * @retval #OS_ERROR if both start time and interval time are zero. + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context + * @retval #OS_TIMER_ERR_INVALID_ARGS if the start_time or interval_time is out of range */ int32 OS_TimerSet(osal_id_t timer_id, uint32 start_time, uint32 interval_time); @@ -167,6 +169,7 @@ int32 OS_TimerSet(osal_id_t timer_id, uint32 start_time, uint32 interval_time); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INVALID_ID if the timer_id is invalid. * @retval #OS_TIMER_ERR_INTERNAL if there was a problem deleting the timer in the host OS. + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimerDelete(osal_id_t timer_id); @@ -184,6 +187,7 @@ int32 OS_TimerDelete(osal_id_t timer_id); * @retval #OS_INVALID_POINTER if timer_id or timer_name are NULL pointers * @retval #OS_ERR_NAME_TOO_LONG name length including null terminator greater than #OS_MAX_API_NAME * @retval #OS_ERR_NAME_NOT_FOUND if the name was not found in the table + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimerGetIdByName(osal_id_t *timer_id, const char *timer_name); @@ -206,6 +210,7 @@ int32 OS_TimerGetIdByName(osal_id_t *timer_id, const char *timer_name); * @retval #OS_SUCCESS @copybrief OS_SUCCESS * @retval #OS_ERR_INVALID_ID if the id passed in is not a valid timer * @retval #OS_INVALID_POINTER if the timer_prop pointer is null + * @retval #OS_ERR_INCORRECT_OBJ_STATE if called from timer/timebase context */ int32 OS_TimerGetInfo(osal_id_t timer_id, OS_timer_prop_t *timer_prop); /**@}*/ diff --git a/src/os/shared/src/osapi-queue.c b/src/os/shared/src/osapi-queue.c index e8f8c4f46..f50278f8e 100644 --- a/src/os/shared/src/osapi-queue.c +++ b/src/os/shared/src/osapi-queue.c @@ -87,7 +87,7 @@ int32 OS_QueueAPI_Init(void) * See description in API and header file for detail * *-----------------------------------------------------------------*/ -int32 OS_QueueCreate(osal_id_t *queue_id, const char *queue_name, osal_blockcount_t queue_depth, size_t max_size, +int32 OS_QueueCreate(osal_id_t *queue_id, const char *queue_name, osal_blockcount_t queue_depth, size_t data_size, uint32 flags) { int32 return_code; @@ -97,7 +97,7 @@ int32 OS_QueueCreate(osal_id_t *queue_id, const char *queue_name, osal_blockcoun /* validate inputs */ OS_CHECK_POINTER(queue_id); OS_CHECK_APINAME(queue_name); - OS_CHECK_SIZE(max_size); + OS_CHECK_SIZE(data_size); ARGCHECK(queue_depth <= OS_QUEUE_MAX_DEPTH, OS_QUEUE_INVALID_SIZE); /* Note - the common ObjectIdAllocate routine will lock the object type and leave it locked. */ @@ -110,7 +110,7 @@ int32 OS_QueueCreate(osal_id_t *queue_id, const char *queue_name, osal_blockcoun OS_OBJECT_INIT(token, queue, queue_name, queue_name); queue->max_depth = queue_depth; - queue->max_size = max_size; + queue->max_size = data_size; /* Now call the OS-specific implementation. This reads info from the queue table. */ return_code = OS_QueueCreate_Impl(&token, flags); diff --git a/src/unit-test-coverage/shared/src/coveragetest-errors.c b/src/unit-test-coverage/shared/src/coveragetest-errors.c index 3afea3e05..dcd70c3a8 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-errors.c +++ b/src/unit-test-coverage/shared/src/coveragetest-errors.c @@ -40,13 +40,8 @@ void Test_OS_GetErrorName(void) UtAssert_True(actual == expected, "OS_GetErrorName(%s) (%ld) == OS_SUCCESS", "OS_ERROR", (long)actual); UtAssert_True(strcmp(err_name, "OS_ERROR") == 0, "string(%s) == OS_ERROR", err_name); - expected = OS_ERROR; - actual = OS_GetErrorName(-555555, &err_name); - UtAssert_True(actual == expected, "OS_GetErrorName(%s) (%ld) == OS_SUCCESS", err_name, (long)actual); - - expected = OS_INVALID_POINTER; - actual = OS_GetErrorName(-555555, NULL); - UtAssert_True(actual == expected, "OS_GetErrorName(NULL) (%ld) == OS_SUCCESS", (long)actual); + OSAPI_TEST_FUNCTION_RC(OS_GetErrorName(-555555, &err_name), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_GetErrorName(-555555, NULL), OS_INVALID_POINTER); } /* Osapi_Test_Setup diff --git a/src/unit-test-coverage/shared/src/coveragetest-file.c b/src/unit-test-coverage/shared/src/coveragetest-file.c index 7d819166e..91f26cfa1 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-file.c +++ b/src/unit-test-coverage/shared/src/coveragetest-file.c @@ -113,9 +113,8 @@ void Test_OS_TimedRead(void) UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); UtAssert_True(memcmp(Buf, SrcBuf, actual) == 0, "buffer content match"); - expected = OS_INVALID_POINTER; - actual = OS_TimedRead(UT_OBJID_1, NULL, sizeof(Buf), 10); - UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_TimedRead(UT_OBJID_1, NULL, sizeof(Buf), 10), OS_INVALID_POINTER); + OSAPI_TEST_FUNCTION_RC(OS_TimedRead(UT_OBJID_1, Buf, 0, 10), OS_ERR_INVALID_SIZE); } void Test_OS_TimedWrite(void) @@ -135,9 +134,8 @@ void Test_OS_TimedWrite(void) UtAssert_True(actual == expected, "OS_TimedWrite() (%ld) == %ld", (long)actual, (long)expected); UtAssert_True(memcmp(Buf, DstBuf, actual) == 0, "buffer content match"); - expected = OS_INVALID_POINTER; - actual = OS_TimedWrite(UT_OBJID_1, NULL, sizeof(Buf), 10); - UtAssert_True(actual == expected, "OS_TimedWrite() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_TimedWrite(UT_OBJID_1, NULL, sizeof(Buf), 10), OS_INVALID_POINTER); + OSAPI_TEST_FUNCTION_RC(OS_TimedWrite(UT_OBJID_1, Buf, 0, 10), OS_ERR_INVALID_SIZE); } void Test_OS_read(void) diff --git a/src/unit-test-coverage/shared/src/coveragetest-filesys.c b/src/unit-test-coverage/shared/src/coveragetest-filesys.c index d70381573..751a65f52 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-filesys.c +++ b/src/unit-test-coverage/shared/src/coveragetest-filesys.c @@ -301,6 +301,14 @@ void Test_OS_FileSysStatVolume(void) expected = OS_ERR_OPERATION_NOT_SUPPORTED; actual = OS_FileSysStatVolume("/cf", &statbuf); UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_ERR_OPERATION_NOT_SUPPORTED", (long)actual); + UT_ResetState(UT_KEY(OS_FileSysStatVolume_Impl)); + + /* Verify OS_FS_ERR_PATH_TOO_LONG */ + UT_SetDefaultReturnValue(UT_KEY(OCS_memchr), -1); + expected = OS_FS_ERR_PATH_TOO_LONG; + actual = OS_FileSysStatVolume("/cf", &statbuf); + UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_FS_ERR_PATH_TOO_LONG", (long)actual); + UT_ResetState(UT_KEY(OCS_memchr)); } void Test_OS_chkfs(void) diff --git a/src/unit-test-coverage/shared/src/coveragetest-idmap.c b/src/unit-test-coverage/shared/src/coveragetest-idmap.c index 70b6e7329..c15c9ea97 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-idmap.c +++ b/src/unit-test-coverage/shared/src/coveragetest-idmap.c @@ -79,10 +79,7 @@ void Test_OS_ObjectIdInit(void) * Test Case For: * int32 OS_ObjectIdInit(void) */ - int32 expected = OS_SUCCESS; - int32 actual = OS_ObjectIdInit(); - - UtAssert_True(actual == expected, "OS_ObjectIdInit() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_ObjectIdInit(), OS_SUCCESS); } void Test_OS_LockUnlockGlobal(void) @@ -156,6 +153,10 @@ void Test_OS_ObjectIdConvertToken(void) OS_common_record_t *record; osal_id_t objid; + /* confirm that calling w/invalid token returns OS_ERR_INCORRECT_OBJ_STATE */ + memset(&token, 0, sizeof(token)); + OSAPI_TEST_FUNCTION_RC(OS_ObjectIdConvertToken(&token), OS_ERR_INCORRECT_OBJ_STATE); + /* get a valid (fake) OSAL ID to start with */ OS_ObjectIdAllocateNew(OS_OBJECT_TYPE_OS_TASK, "ut", &token); objid = token.obj_id; @@ -660,6 +661,28 @@ void Test_OS_ObjectIdFindNextFree(void) /* verify that the wrap occurred */ UtAssert_True(i < (OS_OBJECT_INDEX_MASK + 2), "OS_ObjectIdFindNextFree() wrap around occurred"); + + /* Now fill the task table */ + memset(&token2, 0, sizeof(token2)); + token2.obj_type = OS_OBJECT_TYPE_OS_TASK; + for (i = 0; i < OS_MAX_TASKS; ++i) + { + token2.obj_idx = i; + + rec2 = OS_OBJECT_TABLE_GET(OS_global_task_table, token2); + OS_ObjectIdCompose_Impl(OS_OBJECT_TYPE_OS_TASK, i, &rec2->active_id); + } + + /* Attempt to allocate another task, should result in OS_ERR_NO_FREE_IDS */ + OSAPI_TEST_FUNCTION_RC(OS_ObjectIdFindNextFree(&token2), OS_ERR_NO_FREE_IDS); + + /* Clear the task table */ + memset(OS_global_task_table, 0, sizeof(OS_common_record_t) * OS_MAX_TASKS); + + /* Try to allocate an instance of an objtype which is not implemented */ + memset(&token2, 0, sizeof(token2)); + token2.obj_type = 22; + OSAPI_TEST_FUNCTION_RC(OS_ObjectIdFindNextFree(&token2), OS_ERR_NOT_IMPLEMENTED); } void Test_OS_ObjectIdAllocateNew(void) diff --git a/src/unit-test-coverage/shared/src/coveragetest-network.c b/src/unit-test-coverage/shared/src/coveragetest-network.c index 8a076a551..a9876236b 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-network.c +++ b/src/unit-test-coverage/shared/src/coveragetest-network.c @@ -57,13 +57,8 @@ void Test_OS_NetworkGetHostName(void) actual = OS_NetworkGetHostName(Buffer, sizeof(Buffer)); UtAssert_True(actual == expected, "OS_NetworkGetHostName(impl error) (%ld) == -4444", (long)actual); - expected = OS_INVALID_POINTER; - actual = OS_NetworkGetHostName(NULL, sizeof(Buffer)); - UtAssert_True(actual == expected, "OS_NetworkGetHostName(Ptr=NULL) (%ld) == OS_INVALID_POINTER", (long)actual); - - expected = OS_ERR_INVALID_SIZE; - actual = OS_NetworkGetHostName(Buffer, 0); - UtAssert_True(actual == expected, "OS_NetworkGetHostName(Size=0) (%ld) == OS_ERROR", (long)actual); + OSAPI_TEST_FUNCTION_RC(OS_NetworkGetHostName(NULL, sizeof(Buffer)), OS_INVALID_POINTER); + OSAPI_TEST_FUNCTION_RC(OS_NetworkGetHostName(Buffer, 0), OS_ERR_INVALID_SIZE); } void Test_OS_NetworkGetID(void) diff --git a/src/unit-test-coverage/shared/src/coveragetest-select.c b/src/unit-test-coverage/shared/src/coveragetest-select.c index e5c848257..7f43131e4 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-select.c +++ b/src/unit-test-coverage/shared/src/coveragetest-select.c @@ -47,6 +47,8 @@ void Test_OS_SelectSingle(void) /* Verify Outputs */ UtAssert_True(actual == expected, "OS_SelectSingle() (%ld) == OS_SUCCESS", (long)actual); + + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle(UT_OBJID_1, NULL, 0), OS_INVALID_POINTER); } void Test_OS_SelectMultiple(void) diff --git a/src/unit-test-coverage/shared/src/coveragetest-sockets.c b/src/unit-test-coverage/shared/src/coveragetest-sockets.c index ea73c12b9..b1bf71556 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-sockets.c +++ b/src/unit-test-coverage/shared/src/coveragetest-sockets.c @@ -306,6 +306,9 @@ void Test_OS_SocketRecvFrom(void) actual = OS_SocketRecvFrom(UT_OBJID_1, &Buf, sizeof(Buf), &Addr, 0); UtAssert_True(actual == expected, "OS_SocketRecvFrom() non-bound (%ld) == OS_ERR_INCORRECT_OBJ_STATE", (long)actual); + + /* Fail w/OS_ERR_INVALID_SIZE */ + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom(UT_OBJID_1, &Buf, 0, &Addr, 0), OS_ERR_INVALID_SIZE); } /***************************************************************************** diff --git a/src/unit-test-coverage/shared/src/coveragetest-time.c b/src/unit-test-coverage/shared/src/coveragetest-time.c index 1911196e3..00c541e07 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-time.c +++ b/src/unit-test-coverage/shared/src/coveragetest-time.c @@ -281,18 +281,11 @@ void Test_OS_TimerGetIdByName(void) UtAssert_True(actual == expected, "OS_TimerGetIdByName() (%ld) == OS_SUCCESS", (long)actual); UT_ClearDefaultReturnValue(UT_KEY(OS_ObjectIdFindByName)); - expected = OS_ERR_NAME_NOT_FOUND; - actual = OS_TimerGetIdByName(&objid, "NF"); - UtAssert_True(actual == expected, "OS_TimerGetIdByName() (%ld) == %ld", (long)actual, (long)expected); - - expected = OS_INVALID_POINTER; - actual = OS_TimerGetIdByName(NULL, "NF"); - UtAssert_True(actual == expected, "OS_TimerGetIdByName() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_TimerGetIdByName(&objid, "NF"), OS_ERR_NAME_NOT_FOUND); + OSAPI_TEST_FUNCTION_RC(OS_TimerGetIdByName(NULL, "NF"), OS_INVALID_POINTER); UT_SetDefaultReturnValue(UT_KEY(OS_TaskGetId_Impl), 1 | (OS_OBJECT_TYPE_OS_TIMEBASE << OS_OBJECT_TYPE_SHIFT)); - expected = OS_ERR_INCORRECT_OBJ_STATE; - actual = OS_TimerGetIdByName(&objid, "NF"); - UtAssert_True(actual == expected, "OS_TimerGetIdByName() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_TimerGetIdByName(&objid, "NF"), OS_ERR_INCORRECT_OBJ_STATE); UT_ClearDefaultReturnValue(UT_KEY(OS_TaskGetId_Impl)); } diff --git a/src/unit-test-coverage/shared/src/coveragetest-timebase.c b/src/unit-test-coverage/shared/src/coveragetest-timebase.c index fbfb10d35..b2b28a6bd 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-timebase.c +++ b/src/unit-test-coverage/shared/src/coveragetest-timebase.c @@ -168,9 +168,11 @@ void Test_OS_TimeBaseGetIdByName(void) OSAPI_TEST_OBJID(objid, !=, OS_OBJECT_ID_UNDEFINED); UT_ClearDefaultReturnValue(UT_KEY(OS_ObjectIdFindByName)); - expected = OS_ERR_NAME_NOT_FOUND; - actual = OS_TimeBaseGetIdByName(&objid, "NF"); - UtAssert_True(actual == expected, "OS_TimeBaseGetIdByName() (%ld) == %ld", (long)actual, (long)expected); + OSAPI_TEST_FUNCTION_RC(OS_TimeBaseGetIdByName(&objid, "NF"), OS_ERR_NAME_NOT_FOUND); + + UT_SetDefaultReturnValue(UT_KEY(OCS_memchr), -1); + OSAPI_TEST_FUNCTION_RC(OS_TimeBaseGetIdByName(&objid, "TL"), OS_ERR_NAME_TOO_LONG); + UT_ResetState(UT_KEY(OCS_memchr)); /* test error paths */ expected = OS_INVALID_POINTER; From 1f1cf53422db091896e4a34ebd3635428ec67ca0 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Thu, 6 May 2021 10:38:45 -0400 Subject: [PATCH 5/9] Update #978, incorporate comments/feedback into document Adds various review items into the document, adds some new sections regarding the sample Makefile wrapper. --- doc/OSAL-Configuration-Guide.md | 121 ++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/doc/OSAL-Configuration-Guide.md b/doc/OSAL-Configuration-Guide.md index 7aae314ea..c5f092d2a 100644 --- a/doc/OSAL-Configuration-Guide.md +++ b/doc/OSAL-Configuration-Guide.md @@ -120,15 +120,16 @@ machine. The source distribution has the following directories: | **Directory** | **Description** | |---|---| -| osal | The top level OSAL source distribution directory. OSAL version 2.10 is being used as an example. | -| osal/src | The src directory contains the OSAL source, and make rules. | -| osal/src/examples | The sample directory contains the sample applications for the osal. | -| osal/src/tests | The tests directory contains a small number of OSAL tests that can run on the targets. | -| osal/src/unit-tests |The unit-tests directory contains a suite of OSAL unit tests. | -| osal/src/bsp | The bsp directory contains the platform specific code for the OSAL as well as code to make the OSAL run on a particular platform. Everything in this directory is used to adapt the OSAL and Applications to a particular hardware platform. This directory also contains the startup code for the example programs. The included platforms are generic enough that they may be easy to port to other platforms and processor architectures. For example: The bsp/mcf5235-rtems board support package was ported to an ARM processor running RTEMS with minimal effort. | -| osal/src/os | The os directory is the heart of the OSAL, containing the implementation of the OSAL for each supported operating system. There is a sub-directory for each supported operating system in this directory. The OSAL include files are also contained in this directory (src/os/inc). | -| osal/src/inc | The inc directory contains system wide include files that are used by the OSAL on all platforms. | -| osal/doc | The doc directory contains the documentation and release notes for the OSAL. | +| `osal` | The top level OSAL source distribution directory. | +| `osal/src` | The src directory contains the OSAL source, and make rules. | +| `osal/src/examples` | The sample directory contains the sample applications for the osal. | +| `osal/src/tests` | Contains a suite of tests intended to validate the general functionality of OSAL services | +| `osal/src/unit-tests` | Contains a suite of OSAL unit tests intended to validate the OSAL API, checking inputs, return codes, and outputs for each function. | +| `osal/src/unit-test-coverage` | Contains a suite of tests intended to execute every possible branch/error handling path in the OSAL implementation. | +| `osal/src/bsp` | The bsp directory contains the platform specific code for the OSAL as well as code to make the OSAL run on a particular platform. Everything in this directory is used to adapt the OSAL and Applications to a particular hardware platform. This directory also contains the startup code for the example programs. The included platforms are generic enough that they may be easy to port to other platforms and processor architectures. For example: The bsp/mcf5235-rtems board support package was ported to an ARM processor running RTEMS with minimal effort. | +| `osal/src/os` | The os directory is the heart of the OSAL, containing the implementation of the OSAL for each supported operating system. There is a sub-directory for each supported operating system in this directory. The OSAL include files are also contained in this directory (src/os/inc). | +| `osal/src/inc` | The inc directory contains system wide include files that are used by the OSAL on all platforms. | +| `osal/doc` | The doc directory contains the documentation and release notes for the OSAL. | The osal directory can go just about anywhere on a host development @@ -181,6 +182,7 @@ version of OSAL, refer to the `default_config.cmake` file in the top level direc | `OSAL_CONFIG_MAX_MODULES` | Used for defining the maximum number of loadable modules that OSAL can have loaded simultaneously. | | `OSAL_CONFIG_MAX_SYM_LEN` | Used for setting the maximum length of a symbol name in the symbol API.| | `OSAL_CONFIG_MAX_TIMERS` | Used for defining the maximum number of timers in the OSAL.| +| `OSAL_CONFIG_DEBUG_PERMISSIVE_MODE` | For debugging as a normal/non-root user, causes OSAL to ignore/bypass certain errors related to lack of permission. | All configurable CMake parameters are translated to a generated configuration header file called `osconfig.h`, which replaces the directly-managed header file that was found in previous @@ -248,7 +250,7 @@ set in the development shell. The generated makefiles do not require the user to set any environment variables, as all necessary context information is automatically stored in the cache when the build is first provisioned. -### Setting up a standalone OSAL build +### Setting up a standalone OSAL build manually The OSAL may be built standalone in order to evaluate the library for a particular target and/or execute the included unit tests. @@ -282,6 +284,43 @@ Note that the OSAL is not typically built as a standalone library; although a st build can be done for testing and development purposes, it is expected that the OSAL will be utilized as a component in a larger application. +### Setting up a standalone OSAL build using the Makefile wrapper + +To simplify the process of invoking the cmake tool for typical standalone test/debug builds, +a sample Makefile wrapper script `Makefile.sample` is provided in the OSAL root directory. +This is similar to the sample script provided with CFE. It provides several simple targets +which in turn invoke CMake with a set of typically-used options. + +All makefile operations operate on an output directory referred to by the `O` variable, which +is set to `build` by default. + +| **Makefile Target** | **Task Description** | +|---------------------|----------------------| +| `prep` | Invokes the `cmake` command to set up a new build, or regenerate existing makefiles in the $(O) directory | +| `all` | Calls `make all` in the $(O) directory | +| `install` | Calls `make install` in the $(O) directory | +| `clean` | Calls `make clean` in the $(O) directory | +| `test` | Calls `make test` in the $(O) directory | +| `lcov` | Invokes the `lcov` and `genhtml` tools to generate a coverage report | +| `distclean` | Entirely removes the $(O) directory, bringing back to a fully clean slate | + +Variables recognized/used by `Makefile.sample`: + +| **Variable** | **Default Value** | **Description** | +|---------------------|-------------------|----------------------| +| `O` | `build` | Name of the build directory to operate on | +| `BSPTYPE` | `generic-linux` | The name of the target board (BSP) to build OSAL for, also implies OS type | +| `BUILDTYPE` | `debug` | Translated to the `CMAKE_BUILD_TYPE` variable (set to `release` to build with optimization) | +| `INSTALLPREFIX` | `build` | Translated to the `CMAKE_INSTALL_PREFIX` variable | +| `DESTDIR` | `$(O)` | Local destination directory for `install` | +| `ENABLE_UNIT_TESTS` | false/off | If set to "true" then all tests will be built in addition to the basic OSAL libraries | +| `PERMISSIVE_MODE` | false/off | Translated to the `OSAL_CONFIG_DEBUG_PERMISSIVE_MODE` variable (see above) | + +For more information on the `BUILDTYPE` and `INSTALLPREFIX`, see the CMake documentation: + +https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html + + ### Integrating OSAL into a larger build Modularity is a key feature of the cmake system. As such, the OSAL cmake @@ -678,35 +717,55 @@ the OS-specific coverage test can execute on any platform, it is not limited to running on the platform that it is abstracting. As a result, the VxWorks coverage test is typically executed on a Linux host. -## How to Run the OSAL Unit Tests on the PC / Linux Platform +## How to Run the OSAL Tests on the PC / Linux Platform -To build and run the OSAL unit tests, run the following commands from -the "build" directory: +To build and run the OSAL unit tests, first make sure OSAL was initially configured +with the `ENABLE_UNIT_TESTS` option enabled. Test programs are simply separate application +executables that can then be executed as normal. The test programs are built along with +the OSAL library as part of a normal `make all` or `make install` command. During `install`, +the test programs will be copied to the output location/staging area. -#### Build Commands +### Option 1: Execute single test directly from a build tree + +The tests can be executed directly in-place in the build directory. This method often useful +when debugging, as the exectuable can also be run in a debugger (i.e. gdb) this way. + +The following example executes the task subsystem coverage test for the shared layer, but any +other test can be run in a similar fashion. | **Shell command** | **Description**| |---|---| -| `$ cd build/unit-test-coverage` | Change to the build directory containing coverage tests | -| `$ make` | Build the OSAL Core, and all tests | -| `$ make test` | Execute all of the tests programs | +| `$ cd build/unit-test-coverage/shared` | Change to the build directory containing coverage tests | +| `$ make` | Build the test program(s) if not already done | +| `$ ./coverage-shared-task-testrunner` | Execute the shared task coverage test application | + + +### Option 2: Execute tests in batch mode using ctest and/or makefile wrapper target + +The Makefiles include a "test" wrapper target which in turn invokes the "ctest" program +that will execute all test programs in a batch mode. Note that the "ctest" program shows a quiet output by default, indicating only the test name and a pass/fail status. To see a complete log of tests executed, the test program may be run -directly from the command line. - -#### OSAL Unit Test Directories - - | **Directory**|**Description**| - |---|---| - | `build` | The top level OSAL build directory. | - | `build/unit-tests` | The top level unit test build directory. | - | `build/unit-tests/oscore-test` | Contains the test binary, log, and gcov files for the OSAL core tests | - | `build/unit-tests/osfile-test` | Contains the test binary, log, and gcov files for the OSAL file API tests | - | `build/unit-tests/osfilesys-test` | Contains the test binary, log, and gcov files for the OSAL file system tests | - | `build/unit-tests/osloader-test` | Contains the test binary, log, and gcov files for the OSAL loader tests | - | `build/unit-tests/osnetwork-test` | Contains the test binary, log, and gcov files for the OSAL network tests | - | `build/unit-tests/ostimer-test` | Contains the test binary, log, and gcov files for the OSAL timer tests | +directly from the command line (see above). + +For example: + +`make test` + +**Note**: The "test" target may also be invoked in a build subdirectory, to invoke only the tests +defined/built in (or below) that subdirectory. + +### Code Coverage analysis + +The top level sample Makefile also include an "lcov" wrapper target which in turn invokes the "lcov" and +"genhtml" programs to collect branch/path coverage information into an HTML report. + +For example: + +`make lcov` + +**Note**: The "test" target should be executed before running the "lcov" target. # Revision History From 6951d971e89b5ac2c01ab006da53b9a0ed6bc57c Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 7 May 2021 13:05:37 -0400 Subject: [PATCH 6/9] Fix #989, add local mutex to BSP console Adds a real mutex for use with low level BSP console output. This needs to be actually implemented in the BSP layer, so it will be used by UtAssert outputs (pass/fail message) in addition to OS_printf(). This also converts OS_DEBUG to use the same console output rather than calling fprintf directly. The combination of a mutex and all common print outputs (UtAssert, OS_printf, OS_DEBUG) going through the same path makes the test output on VxWorks much more coherent. --- src/bsp/generic-linux/src/bsp_start.c | 55 ++++++++++++++++++- .../src/generic_linux_bsp_internal.h | 5 +- src/bsp/generic-vxworks/src/bsp_start.c | 47 ++++++++++++++++ .../src/generic_vxworks_bsp_internal.h | 17 ++++++ src/bsp/pc-rtems/src/bsp_start.c | 39 +++++++++++++ src/bsp/pc-rtems/src/pcrtems_bsp_internal.h | 7 ++- src/bsp/shared/inc/bsp-impl.h | 22 ++++++++ src/os/portable/os-impl-console-bsp.c | 5 ++ src/os/shared/src/osapi-debug.c | 19 ++++++- .../ut-stubs/inc/OCS_bsp-impl.h | 6 ++ .../ut-stubs/override_inc/bsp-impl.h | 2 + .../ut-stubs/src/bsp-console-impl-stubs.c | 16 ++++++ ut_assert/src/utbsp.c | 7 +++ 13 files changed, 239 insertions(+), 8 deletions(-) diff --git a/src/bsp/generic-linux/src/bsp_start.c b/src/bsp/generic-linux/src/bsp_start.c index 71b6afeb3..4900f2259 100644 --- a/src/bsp/generic-linux/src/bsp_start.c +++ b/src/bsp/generic-linux/src/bsp_start.c @@ -49,8 +49,10 @@ OS_BSP_GenericLinuxGlobalData_t OS_BSP_GenericLinuxGlobal; --------------------------------------------------------- */ void OS_BSP_Initialize(void) { - FILE *fp; - char buffer[32]; + FILE * fp; + char buffer[32]; + pthread_mutexattr_t mutex_attr; + int status; /* * If not running as root, check /proc/sys/fs/mqueue/msg_max @@ -76,6 +78,53 @@ void OS_BSP_Initialize(void) fclose(fp); } } + + /* Initialize the low level access mutex (w/priority inheritance) */ + status = pthread_mutexattr_init(&mutex_attr); + if (status < 0) + { + BSP_DEBUG("pthread_mutexattr_init: %s\n", strerror(status)); + } + status = pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); + if (status < 0) + { + BSP_DEBUG("pthread_mutexattr_setprotocol: %s\n", strerror(status)); + } + status = pthread_mutex_init(&OS_BSP_GenericLinuxGlobal.AccessMutex, &mutex_attr); + if (status < 0) + { + BSP_DEBUG("pthread_mutex_init: %s\n", strerror(status)); + } +} + +/*---------------------------------------------------------------- + OS_BSP_Lock_Impl + See full description in header + ------------------------------------------------------------------*/ +void OS_BSP_Lock_Impl(void) +{ + int status; + + status = pthread_mutex_lock(&OS_BSP_GenericLinuxGlobal.AccessMutex); + if (status < 0) + { + BSP_DEBUG("pthread_mutex_lock: %s\n", strerror(status)); + } +} + +/*---------------------------------------------------------------- + OS_BSP_Unlock_Impl + See full description in header + ------------------------------------------------------------------*/ +void OS_BSP_Unlock_Impl(void) +{ + int status; + + status = pthread_mutex_unlock(&OS_BSP_GenericLinuxGlobal.AccessMutex); + if (status < 0) + { + BSP_DEBUG("pthread_mutex_unlock: %s\n", strerror(status)); + } } /* --------------------------------------------------------- @@ -166,7 +215,7 @@ int main(int argc, char *argv[]) } /* - * Auto-Create any missing FS_BASED mount points specified in OS_VolumeTable + * Perform any other BSP-specific initialization */ OS_BSP_Initialize(); diff --git a/src/bsp/generic-linux/src/generic_linux_bsp_internal.h b/src/bsp/generic-linux/src/generic_linux_bsp_internal.h index 716c09b50..d61a1e478 100644 --- a/src/bsp/generic-linux/src/generic_linux_bsp_internal.h +++ b/src/bsp/generic-linux/src/generic_linux_bsp_internal.h @@ -33,12 +33,15 @@ #include "osapi-error.h" #include "bsp-impl.h" +#include + /* ** BSP types */ typedef struct { - bool EnableTermControl; /**< Will be set "true" when invoked from a TTY device, false otherwise */ + bool EnableTermControl; /**< Will be set "true" when invoked from a TTY device, false otherwise */ + pthread_mutex_t AccessMutex; } OS_BSP_GenericLinuxGlobalData_t; /* diff --git a/src/bsp/generic-vxworks/src/bsp_start.c b/src/bsp/generic-vxworks/src/bsp_start.c index 55d56c4fc..caa33a333 100644 --- a/src/bsp/generic-vxworks/src/bsp_start.c +++ b/src/bsp/generic-vxworks/src/bsp_start.c @@ -30,9 +30,44 @@ */ #include #include +#include #include "generic_vxworks_bsp_internal.h" +OS_BSP_GenericVxWorksGlobalData_t OS_BSP_GenericVxWorksGlobal; + +/* --------------------------------------------------------- + OS_BSP_Lock_Impl() + + Helper function to get exclusive access to BSP + --------------------------------------------------------- */ +void OS_BSP_Lock_Impl(void) +{ + int status; + + status = semTake(OS_BSP_GenericVxWorksGlobal.AccessMutex, WAIT_FOREVER); + if (status != OK) + { + BSP_DEBUG("semTake: errno=%d\n", errno); + } +} + +/* --------------------------------------------------------- + OS_BSP_Unlock_Impl() + + Helper function to release exclusive access to BSP + --------------------------------------------------------- */ +void OS_BSP_Unlock_Impl(void) +{ + int status; + + status = semGive(OS_BSP_GenericVxWorksGlobal.AccessMutex); + if (status != OK) + { + BSP_DEBUG("semGive: errno=%d\n", errno); + } +} + /* --------------------------------------------------------- OS_BSP_Shutdown_Impl() @@ -63,6 +98,18 @@ int OS_BSPMain(void) * Initially clear the global object (this contains return code) */ memset(&OS_BSP_Global, 0, sizeof(OS_BSP_Global)); + memset(&OS_BSP_GenericVxWorksGlobal, 0, sizeof(OS_BSP_GenericVxWorksGlobal)); + + /* + * Initialize the low level access sem + */ + OS_BSP_GenericVxWorksGlobal.AccessMutex = + semMInitialize(OS_BSP_GenericVxWorksGlobal.AccessMutexMem, SEM_Q_PRIORITY | SEM_INVERSION_SAFE); + + if (OS_BSP_GenericVxWorksGlobal.AccessMutex == (SEM_ID)0) + { + BSP_DEBUG("semMInitalize: errno=%d\n", errno); + } /* * Call application specific entry point. diff --git a/src/bsp/generic-vxworks/src/generic_vxworks_bsp_internal.h b/src/bsp/generic-vxworks/src/generic_vxworks_bsp_internal.h index 084c0345e..d6d5e6a50 100644 --- a/src/bsp/generic-vxworks/src/generic_vxworks_bsp_internal.h +++ b/src/bsp/generic-vxworks/src/generic_vxworks_bsp_internal.h @@ -33,4 +33,21 @@ */ #include "bsp-impl.h" +#include + +/* +** BSP types +*/ +typedef struct +{ + SEM_ID AccessMutex; + VX_MUTEX_SEMAPHORE(AccessMutexMem); + +} OS_BSP_GenericVxWorksGlobalData_t; + +/* + * Global Data object + */ +extern OS_BSP_GenericVxWorksGlobalData_t OS_BSP_GenericVxWorksGlobal; + #endif /* GENERIC_VXWORKS_BSP_INTERNAL_H */ diff --git a/src/bsp/pc-rtems/src/bsp_start.c b/src/bsp/pc-rtems/src/bsp_start.c index cb2e43542..1d0ef9789 100644 --- a/src/bsp/pc-rtems/src/bsp_start.c +++ b/src/bsp/pc-rtems/src/bsp_start.c @@ -169,6 +169,17 @@ void OS_BSP_Setup(void) } } + /* + * Initialize the low level access sem + */ + status = rtems_semaphore_create(rtems_build_name('B', 'S', 'P', '\0'), 1, + RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY, 0, + &OS_BSP_PcRtemsGlobal.AccessMutex); + if (status != RTEMS_SUCCESSFUL) + { + BSP_DEBUG("rtems_semaphore_create: %s\n", rtems_status_text(status)); + } + /* ** Create the RTEMS Root file system */ @@ -248,6 +259,34 @@ void OS_BSP_Setup(void) printf("\n\n"); } +/*---------------------------------------------------------------- + OS_BSP_Lock_Impl + See full description in header + ------------------------------------------------------------------*/ +void OS_BSP_Lock_Impl(void) +{ + rtems_status_code status; + status = rtems_semaphore_obtain(OS_BSP_PcRtemsGlobal.AccessMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (status != RTEMS_SUCCESSFUL) + { + BSP_DEBUG("rtems_semaphore_obtain: %s\n", rtems_status_text(status)); + } +} + +/*---------------------------------------------------------------- + OS_BSP_Unlock_Impl + See full description in header + ------------------------------------------------------------------*/ +void OS_BSP_Unlock_Impl(void) +{ + rtems_status_code status; + status = rtems_semaphore_release(OS_BSP_PcRtemsGlobal.AccessMutex); + if (status != RTEMS_SUCCESSFUL) + { + BSP_DEBUG("rtems_semaphore_release: %s\n", rtems_status_text(status)); + } +} + /* --------------------------------------------------------- OS_BSP_GetReturnStatus() diff --git a/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h b/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h index 653c62fb6..90669c809 100644 --- a/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h +++ b/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h @@ -33,6 +33,8 @@ */ #include "bsp-impl.h" +#include + /* * BSP compile-time tuning */ @@ -64,8 +66,9 @@ */ typedef struct { - char UserArgBuffer[RTEMS_MAX_CMDLINE]; - bool BatchMode; + char UserArgBuffer[RTEMS_MAX_CMDLINE]; + bool BatchMode; + rtems_id AccessMutex; } OS_BSP_PcRtemsGlobalData_t; /* diff --git a/src/bsp/shared/inc/bsp-impl.h b/src/bsp/shared/inc/bsp-impl.h index d6aa87da5..d2e7cfcbc 100644 --- a/src/bsp/shared/inc/bsp-impl.h +++ b/src/bsp/shared/inc/bsp-impl.h @@ -108,6 +108,28 @@ extern OS_BSP_GlobalData_t OS_BSP_Global; /* INTERNAL BSP IMPLEMENTATION FUNCTIONS */ /********************************************************************/ +/*---------------------------------------------------------------- + Function: OS_BSP_Lock_Impl + + Purpose: Get exclusive access to a BSP-provided service or object + + Useful in conjuction with console output functions to avoid strings + from multiple tasks getting mixed together in the final output. + + ------------------------------------------------------------------*/ +void OS_BSP_Lock_Impl(void); + +/*---------------------------------------------------------------- + Function: OS_BSP_Unlock_Impl + + Purpose: Release exclusive access to a BSP-provided service or object + + This must be called after a call to OS_BSP_Lock_Impl() once + access is complete, to allow other tasks to use the resource. + + ------------------------------------------------------------------*/ +void OS_BSP_Unlock_Impl(void); + /*---------------------------------------------------------------- Function: OS_BSP_ConsoleOutput_Impl diff --git a/src/os/portable/os-impl-console-bsp.c b/src/os/portable/os-impl-console-bsp.c index c0ba15325..cf628950c 100644 --- a/src/os/portable/os-impl-console-bsp.c +++ b/src/os/portable/os-impl-console-bsp.c @@ -65,6 +65,9 @@ void OS_ConsoleOutput_Impl(const OS_object_token_t *token) console = OS_OBJECT_TABLE_GET(OS_console_table, *token); StartPos = console->ReadPos; EndPos = console->WritePos; + + OS_BSP_Lock_Impl(); + while (StartPos != EndPos) { if (StartPos > EndPos) @@ -87,6 +90,8 @@ void OS_ConsoleOutput_Impl(const OS_object_token_t *token) } } + OS_BSP_Unlock_Impl(); + /* Update the global with the new read location */ console->ReadPos = StartPos; } /* end OS_ConsoleOutput_Impl */ diff --git a/src/os/shared/src/osapi-debug.c b/src/os/shared/src/osapi-debug.c index f6eef77ac..5a3e2fa5f 100644 --- a/src/os/shared/src/osapi-debug.c +++ b/src/os/shared/src/osapi-debug.c @@ -41,8 +41,10 @@ */ #include "os-shared-globaldefs.h" #include "os-shared-common.h" +#include "bsp-impl.h" #define OS_DEBUG_OUTPUT_STREAM stdout +#define OS_DEBUG_MAX_LINE_LEN 132 /*---------------------------------------------------------------- * @@ -53,14 +55,27 @@ *-----------------------------------------------------------------*/ void OS_DebugPrintf(uint32 Level, const char *Func, uint32 Line, const char *Format, ...) { + char buffer[OS_DEBUG_MAX_LINE_LEN]; va_list va; if (OS_SharedGlobalVars.DebugLevel >= Level) { + /* + * Lock the console so this appears coherently, + * not mixed with other chars from other tasks + */ + OS_BSP_Lock_Impl(); + + snprintf(buffer, sizeof(buffer), "%s():%lu:", Func, (unsigned long)Line); + OS_BSP_ConsoleOutput_Impl(buffer, strlen(buffer)); + va_start(va, Format); - fprintf(OS_DEBUG_OUTPUT_STREAM, "%s():%lu:", Func, (unsigned long)Line); - vfprintf(OS_DEBUG_OUTPUT_STREAM, Format, va); + vsnprintf(buffer, sizeof(buffer), Format, va); va_end(va); + + OS_BSP_ConsoleOutput_Impl(buffer, strlen(buffer)); + + OS_BSP_Unlock_Impl(); } } /* end OS_DebugPrintf */ diff --git a/src/unit-test-coverage/ut-stubs/inc/OCS_bsp-impl.h b/src/unit-test-coverage/ut-stubs/inc/OCS_bsp-impl.h index d76e3fc75..b6eaa255f 100644 --- a/src/unit-test-coverage/ut-stubs/inc/OCS_bsp-impl.h +++ b/src/unit-test-coverage/ut-stubs/inc/OCS_bsp-impl.h @@ -55,6 +55,12 @@ /* INTERNAL BSP IMPLEMENTATION FUNCTIONS */ /********************************************************************/ +/* + * Lock and unlock stubs + */ +void OCS_OS_BSP_Lock_Impl(void); +void OCS_OS_BSP_Unlock_Impl(void); + /*---------------------------------------------------------------- Function: OS_BSP_ConsoleOutput_Impl diff --git a/src/unit-test-coverage/ut-stubs/override_inc/bsp-impl.h b/src/unit-test-coverage/ut-stubs/override_inc/bsp-impl.h index 74d7d6039..ed77d95d1 100644 --- a/src/unit-test-coverage/ut-stubs/override_inc/bsp-impl.h +++ b/src/unit-test-coverage/ut-stubs/override_inc/bsp-impl.h @@ -36,8 +36,10 @@ #define OS_BSP_CONSOLEMODE_BLUE OCS_OS_BSP_CONSOLEMODE_BLUE #define OS_BSP_CONSOLEMODE_HIGHLIGHT OCS_OS_BSP_CONSOLEMODE_HIGHLIGHT +#define OS_BSP_Lock_Impl OCS_OS_BSP_Lock_Impl #define OS_BSP_ConsoleOutput_Impl OCS_OS_BSP_ConsoleOutput_Impl #define OS_BSP_ConsoleSetMode_Impl OCS_OS_BSP_ConsoleSetMode_Impl +#define OS_BSP_Unlock_Impl OCS_OS_BSP_Unlock_Impl /********************* END bsp-impl.h diff --git a/src/unit-test-coverage/ut-stubs/src/bsp-console-impl-stubs.c b/src/unit-test-coverage/ut-stubs/src/bsp-console-impl-stubs.c index d3ed86ea3..23f369b20 100644 --- a/src/unit-test-coverage/ut-stubs/src/bsp-console-impl-stubs.c +++ b/src/unit-test-coverage/ut-stubs/src/bsp-console-impl-stubs.c @@ -30,6 +30,22 @@ #include "OCS_bsp-impl.h" +/*---------------------------------------------------------------- + Stub for OS_BSP_Lock_Impl + ------------------------------------------------------------------*/ +void OCS_OS_BSP_Lock_Impl(void) +{ + UT_DEFAULT_IMPL(OCS_OS_BSP_Lock_Impl); +} + +/*---------------------------------------------------------------- + Stub for OS_BSP_Unlock_Impl + ------------------------------------------------------------------*/ +void OCS_OS_BSP_Unlock_Impl(void) +{ + UT_DEFAULT_IMPL(OCS_OS_BSP_Unlock_Impl); +} + /*---------------------------------------------------------------- Function: OS_BSP_ConsoleOutput_Impl diff --git a/ut_assert/src/utbsp.c b/ut_assert/src/utbsp.c index 3de0efae4..d5f1b1d1b 100644 --- a/ut_assert/src/utbsp.c +++ b/ut_assert/src/utbsp.c @@ -113,6 +113,8 @@ void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) if (MsgEnabled & 1) { + OS_BSP_Lock_Impl(); + switch (MessageType) { case UTASSERT_CASETYPE_ABORT: @@ -182,6 +184,8 @@ void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) OS_BSP_ConsoleOutput_Impl(" ", 1); OS_BSP_ConsoleOutput_Impl(OutputMessage, strlen(OutputMessage)); OS_BSP_ConsoleOutput_Impl("\n", 1); + + OS_BSP_Unlock_Impl(); } /* @@ -209,7 +213,10 @@ void UT_BSP_EndTest(const UtAssert_TestCounter_t *TestCounters) snprintf(Message, sizeof(Message), "COMPLETE: %u tests Segment(s) executed\n\n", (unsigned int)TestCounters->TestSegmentCount); + + OS_BSP_Lock_Impl(); OS_BSP_ConsoleOutput_Impl(Message, strlen(Message)); + OS_BSP_Unlock_Impl(); if ((TestCounters->CaseCount[UTASSERT_CASETYPE_FAILURE] > 0) || (TestCounters->CaseCount[UTASSERT_CASETYPE_TSF] > 0) || (TestCounters->CaseCount[UTASSERT_CASETYPE_TTF] > 0)) From 1d6a6536b5dd78841bf962670d169a0194e85c43 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 7 May 2021 15:55:36 -0400 Subject: [PATCH 7/9] Fix #988, do not require nonblock mode In some versions of VxWorks the fcntl F_GETFL/F_SETFL opcodes do not appear to be implemented, and thus it is not possible to set O_NONBLOCK mode. However, this mode is not necessarily required, it is more of a backup/failsafe. The "selectable" flag should not be dependent on whether O_NONBLOCK flag got set. This also adjust some timeouts and adds some delays to improve the reliability of network-api-test on VxWorks. The timeouts were only 10ms, and this is much too short as messages are getting written on a 9600 baud console (avg 1ms/char). A single log message can easily take 50-60ms alone. --- src/os/portable/os-impl-bsd-sockets.c | 20 +++--- src/os/posix/inc/os-impl-sockets.h | 5 ++ src/os/rtems/inc/os-impl-sockets.h | 5 ++ src/os/vxworks/inc/os-impl-sockets.h | 12 ++++ src/tests/network-api-test/network-api-test.c | 72 ++++++++++++------- .../portable/src/coveragetest-bsd-sockets.c | 8 --- 6 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/os/portable/os-impl-bsd-sockets.c b/src/os/portable/os-impl-bsd-sockets.c index c992ea78b..39ae4fa6b 100644 --- a/src/os/portable/os-impl-bsd-sockets.c +++ b/src/os/portable/os-impl-bsd-sockets.c @@ -155,6 +155,10 @@ int32 OS_SocketOpen_Impl(const OS_object_token_t *token) * Set the standard options on the filehandle by default -- * this may set it to non-blocking mode if the implementation supports it. * any blocking would be done explicitly via the select() wrappers + * + * NOTE: The implementation still generally works without this flag set, but + * nonblock mode does improve robustness in the event that multiple tasks + * attempt to accept new connections from the same server socket at the same time. */ os_flags = fcntl(impl->fd, F_GETFL); if (os_flags == -1) @@ -170,12 +174,10 @@ int32 OS_SocketOpen_Impl(const OS_object_token_t *token) /* No recourse if F_SETFL fails - just report the error and move on. */ OS_DEBUG("fcntl(F_SETFL): %s\n", strerror(errno)); } - else - { - impl->selectable = ((os_flags & O_NONBLOCK) != 0); - } } + impl->selectable = OS_IMPL_SOCKET_SELECTABLE; + return OS_SUCCESS; } /* end OS_SocketOpen_Impl */ @@ -434,6 +436,10 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ * Set the standard options on the filehandle by default -- * this may set it to non-blocking mode if the implementation supports it. * any blocking would be done explicitly via the select() wrappers + * + * NOTE: The implementation still generally works without this flag set, but + * nonblock mode does improve robustness in the event that multiple tasks + * attempt to read from the same socket at the same time. */ os_flags = fcntl(conn_impl->fd, F_GETFL); if (os_flags == -1) @@ -449,11 +455,9 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ /* No recourse if F_SETFL fails - just report the error and move on. */ OS_DEBUG("fcntl(F_SETFL): %s\n", strerror(errno)); } - else - { - conn_impl->selectable = ((os_flags & O_NONBLOCK) != 0); - } } + + conn_impl->selectable = OS_IMPL_SOCKET_SELECTABLE; } } } diff --git a/src/os/posix/inc/os-impl-sockets.h b/src/os/posix/inc/os-impl-sockets.h index 29812594b..bf40de942 100644 --- a/src/os/posix/inc/os-impl-sockets.h +++ b/src/os/posix/inc/os-impl-sockets.h @@ -38,6 +38,11 @@ #define OS_NETWORK_SUPPORTS_IPV6 +/* + * Socket descriptors should be usable with the select() API + */ +#define OS_IMPL_SOCKET_SELECTABLE true + /* * A full POSIX-compliant I/O layer should support using * nonblocking I/O calls in combination with select(). diff --git a/src/os/rtems/inc/os-impl-sockets.h b/src/os/rtems/inc/os-impl-sockets.h index 085860ab8..569c47fd5 100644 --- a/src/os/rtems/inc/os-impl-sockets.h +++ b/src/os/rtems/inc/os-impl-sockets.h @@ -37,6 +37,11 @@ #include #include +/* + * Socket descriptors should be usable with the select() API + */ +#define OS_IMPL_SOCKET_SELECTABLE true + /* * A RTEMS socket I/O layer should support using * nonblocking I/O calls in combination with select(). diff --git a/src/os/vxworks/inc/os-impl-sockets.h b/src/os/vxworks/inc/os-impl-sockets.h index 663651bf6..bf7c716f6 100644 --- a/src/os/vxworks/inc/os-impl-sockets.h +++ b/src/os/vxworks/inc/os-impl-sockets.h @@ -38,8 +38,20 @@ #include #include +/* + * Socket descriptors should be usable with the select() API + */ +#define OS_IMPL_SOCKET_SELECTABLE true + /* * Use the O_NONBLOCK flag on sockets + * + * NOTE: the fcntl() F_GETFL/F_SETFL opcodes that set descriptor flags may not + * work correctly on some version of VxWorks. + * + * This flag is not strictly required, things still mostly work without it, + * but lack of this mode does introduce some potential race conditions if more + * than one task attempts to use the same descriptor handle at the same time. */ #define OS_IMPL_SOCKET_FLAGS O_NONBLOCK diff --git a/src/tests/network-api-test/network-api-test.c b/src/tests/network-api-test/network-api-test.c index 70a4bf99a..2eaaccc39 100644 --- a/src/tests/network-api-test/network-api-test.c +++ b/src/tests/network-api-test/network-api-test.c @@ -34,6 +34,16 @@ #define UT_EXIT_LOOP_MAX 100 +/* + * Timeouts for various socket ops in the test cases + * + * Note that the act of calling any "assert" routine causes console output, which + * can easily take tens or even hundreds of milliseconds to execute on platforms + * where the console is on a slow serial port. Therefore this timeout must + * not be too short. + */ +#define UT_TIMEOUT 1000 + /* * Variations of client->server connections to create. * This tests that the server socket can accept multiple connections, @@ -248,7 +258,7 @@ void TestDatagramNetworkApi(void) /* Recieve data from peer1 to peer2 */ expected = sizeof(Buf2); - actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, sizeof(Buf2), &l_addr, 100); + actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, sizeof(Buf2), &l_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() Passed. sizeof(Buf2) (%ld) == 1", (long)actual); UtAssert_True(Buf1 == Buf2, "Buf1 (%ld) == Buf2 (%ld)", (long)Buf1, (long)Buf2); @@ -275,7 +285,7 @@ void TestDatagramNetworkApi(void) /* Recieve data from peer2 to peer1 */ expected = sizeof(Buf4); - actual = OS_SocketRecvFrom(p1_socket_id, &Buf4, sizeof(Buf4), &l_addr, 100); + actual = OS_SocketRecvFrom(p1_socket_id, &Buf4, sizeof(Buf4), &l_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() Passed. sizeof(Buf3) (%ld) == 1", (long)actual); UtAssert_True(Buf3 == Buf4, "Buf3 (%ld) == Buf4 (%ld)", (long)Buf3, (long)Buf4); @@ -328,7 +338,7 @@ void TestDatagramNetworkApi(void) /* OS_SocketRecvFrom */ expected = OS_INVALID_POINTER; - actual = OS_SocketRecvFrom(p2_socket_id, NULL, OSAL_SIZE_C(1), NULL, 100); + actual = OS_SocketRecvFrom(p2_socket_id, NULL, OSAL_SIZE_C(1), NULL, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() (%ld) == OS_INVALID_POINTER", (long)actual); expected = OS_INVALID_POINTER; @@ -337,15 +347,15 @@ void TestDatagramNetworkApi(void) expected = OS_ERR_INVALID_ID; objid = OS_ObjectIdFromInteger(0xFFFFFFFF); - actual = OS_SocketRecvFrom(objid, &Buf2, sizeof(Buf2), &l_addr, 100); + actual = OS_SocketRecvFrom(objid, &Buf2, sizeof(Buf2), &l_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() (%ld) == OS_ERR_INVALID_ID", (long)actual); expected = OS_ERR_INVALID_SIZE; - actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, OSAL_SIZE_C(0), &l_addr, 100); + actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, OSAL_SIZE_C(0), &l_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() (%ld) == OS_ERR_INVALID_SIZE", (long)actual); expected = OS_ERR_INVALID_SIZE; - actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, OSAL_SIZE_C(0), NULL, 100); + actual = OS_SocketRecvFrom(p2_socket_id, &Buf2, OSAL_SIZE_C(0), NULL, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketRecvFrom() (%ld) == OS_ERR_INVALID_SIZE", (long)actual); /* OS_SocketAddrToString */ @@ -433,6 +443,8 @@ void Server_Fn(void) for (iter = UT_STREAM_CONNECTION_INITIAL; iter < UT_STREAM_CONNECTION_MAX; ++iter) { + UtPrintf("SERVER: accepting connection %u", (unsigned int)iter); + /* Accept incoming connections */ Status = OS_SocketAccept(s_socket_id, &connsock_id, &addr, OS_PEND); if (Status != OS_SUCCESS) @@ -442,6 +454,8 @@ void Server_Fn(void) break; } + UtPrintf("SERVER: handling connection %u", (unsigned int)iter); + /* Recieve incoming data from client - * should be exactly 4 bytes on most cycles, but 0 bytes on the cycle * where write shutdown was done by client side prior to initial write. */ @@ -453,7 +467,7 @@ void Server_Fn(void) { ExpectedStatus = 4; } - Status = OS_TimedRead(connsock_id, Buf_trans, sizeof(Buf_trans), 10); + Status = OS_TimedRead(connsock_id, Buf_trans, sizeof(Buf_trans), UT_TIMEOUT); if (Status != ExpectedStatus) { snprintf(ServerFn_ErrorString, sizeof(ServerFn_ErrorString), "OS_TimedRead() iter=%u, return code=%d/%d", @@ -472,7 +486,7 @@ void Server_Fn(void) * 2. Original value recieved above (4 bytes) * 3. String of all possible 8-bit chars [0-255] (256 bytes) */ - Status = OS_TimedWrite(connsock_id, &iter, sizeof(iter), 10); + Status = OS_TimedWrite(connsock_id, &iter, sizeof(iter), UT_TIMEOUT); if (Status != sizeof(iter)) { snprintf(ServerFn_ErrorString, sizeof(ServerFn_ErrorString), @@ -480,7 +494,7 @@ void Server_Fn(void) break; } - Status = OS_TimedWrite(connsock_id, Buf_trans, 4, 10); + Status = OS_TimedWrite(connsock_id, Buf_trans, 4, UT_TIMEOUT); if (Status != 4) { snprintf(ServerFn_ErrorString, sizeof(ServerFn_ErrorString), @@ -488,7 +502,7 @@ void Server_Fn(void) break; } - Status = OS_TimedWrite(connsock_id, Buf_each_char_s, sizeof(Buf_each_char_s), 10); + Status = OS_TimedWrite(connsock_id, Buf_each_char_s, sizeof(Buf_each_char_s), UT_TIMEOUT); if (Status != sizeof(Buf_each_char_s)) { snprintf(ServerFn_ErrorString, sizeof(ServerFn_ErrorString), @@ -593,6 +607,10 @@ void TestStreamNetworkApi(void) */ for (iter = UT_STREAM_CONNECTION_INITIAL; iter < UT_STREAM_CONNECTION_MAX; ++iter) { + /* An extra delay here to increases the chance that the server task has reached the "accept" call */ + OS_TaskDelay(UT_TIMEOUT); + UtPrintf("CLIENT: initiating connection %u", (unsigned int)iter); + /* Open a client socket */ expected = OS_SUCCESS; c_socket_id = OS_OBJECT_ID_UNDEFINED; @@ -601,7 +619,7 @@ void TestStreamNetworkApi(void) UtAssert_True(actual == expected, "OS_SocketOpen() (%ld) == OS_SUCCESS", (long)actual); UtAssert_True(OS_ObjectIdDefined(c_socket_id), "c_socket_id (%lu) != 0", OS_ObjectIdToInteger(c_socket_id)); - actual = OS_SocketConnect(c_socket_id, &s_addr, 10); + actual = OS_SocketConnect(c_socket_id, &s_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketConnect() (%ld) == OS_SUCCESS", (long)actual); /* @@ -614,11 +632,11 @@ void TestStreamNetworkApi(void) /* OS_TimedRead */ expected = OS_ERR_INVALID_ID; temp_id = OS_ObjectIdFromInteger(0xFFFFFFFF); - actual = OS_TimedRead(temp_id, Buf_rcv_c, sizeof(Buf_rcv_c), 10); + actual = OS_TimedRead(temp_id, Buf_rcv_c, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); expected = OS_INVALID_POINTER; - actual = OS_TimedRead(c_socket_id, NULL, sizeof(Buf_rcv_c), 10); + actual = OS_TimedRead(c_socket_id, NULL, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); expected = OS_ERROR_TIMEOUT; @@ -628,11 +646,11 @@ void TestStreamNetworkApi(void) /* OS_TimedWrite */ expected = OS_ERR_INVALID_ID; temp_id = OS_ObjectIdFromInteger(0xFFFFFFFF); - actual = OS_TimedWrite(temp_id, Buf_rcv_c, sizeof(Buf_rcv_c), 10); + actual = OS_TimedWrite(temp_id, Buf_rcv_c, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedWrite() (%ld) == %ld", (long)actual, (long)expected); expected = OS_INVALID_POINTER; - actual = OS_TimedWrite(c_socket_id, NULL, sizeof(Buf_rcv_c), 10); + actual = OS_TimedWrite(c_socket_id, NULL, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedWrite() (%ld) == %ld", (long)actual, (long)expected); /* OS_SocketAccept */ @@ -641,16 +659,16 @@ void TestStreamNetworkApi(void) UtAssert_True(actual == expected, "OS_SocketAccept() (%ld) == OS_INVALID_POINTER", (long)actual); expected = OS_INVALID_POINTER; - actual = OS_SocketAccept(s_socket_id, NULL, &temp_addr, 10); + actual = OS_SocketAccept(s_socket_id, NULL, &temp_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketAccept() (%ld) == OS_INVALID_POINTER", (long)actual); expected = OS_INVALID_POINTER; - actual = OS_SocketAccept(s_socket_id, &temp_id, NULL, 10); + actual = OS_SocketAccept(s_socket_id, &temp_id, NULL, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketAccept() (%ld) == OS_INVALID_POINTER", (long)actual); /* OS_SocketConnect */ expected = OS_INVALID_POINTER; - actual = OS_SocketConnect(c_socket_id, NULL, 10); + actual = OS_SocketConnect(c_socket_id, NULL, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketConnect() (%ld) == OS_INVALID_POINTER", (long)actual); expected = OS_ERR_INCORRECT_OBJ_STATE; @@ -660,7 +678,7 @@ void TestStreamNetworkApi(void) expected = OS_ERR_INVALID_ID; temp_id = OS_ObjectIdFromInteger(0xFFFFFFFF); - actual = OS_SocketConnect(temp_id, &s_addr, 10); + actual = OS_SocketConnect(temp_id, &s_addr, UT_TIMEOUT); UtAssert_True(actual == expected, "OS_SocketConnect() (%ld) == OS_ERR_INVALID_ID", (long)actual); } @@ -694,7 +712,7 @@ void TestStreamNetworkApi(void) /* Attempt to read data, would block/timeout normally, but * due to read shutdown it should immediately return instead. */ expected = 0; - actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), 10); + actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() after read shutdown (%ld) == %ld", (long)actual, (long)expected); } @@ -703,7 +721,7 @@ void TestStreamNetworkApi(void) { /* Send data to server - this should still work after read shutdown, but not after write shutdown */ expected = sizeof(Buf_send_c); - actual = OS_TimedWrite(c_socket_id, Buf_send_c, sizeof(Buf_send_c), 10); + actual = OS_TimedWrite(c_socket_id, Buf_send_c, sizeof(Buf_send_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedWrite() (%ld) == %ld", (long)actual, (long)expected); } @@ -720,7 +738,7 @@ void TestStreamNetworkApi(void) { /* If write shutdown worked as expected, write should return an error */ expected = OS_ERROR; - actual = OS_TimedWrite(c_socket_id, Buf_send_c, sizeof(Buf_send_c), 10); + actual = OS_TimedWrite(c_socket_id, Buf_send_c, sizeof(Buf_send_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedWrite() after SHUT_WRITE (%ld) == %ld", (long)actual, (long)expected); } @@ -731,26 +749,26 @@ void TestStreamNetworkApi(void) { /* Recieve back data from server, first is loop count */ expected = sizeof(loopcnt); - actual = OS_TimedRead(c_socket_id, &loopcnt, sizeof(loopcnt), 10); + actual = OS_TimedRead(c_socket_id, &loopcnt, sizeof(loopcnt), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); UtAssert_UINT32_EQ(iter, loopcnt); /* Recieve back data from server, next is original string */ expected = sizeof(Buf_rcv_c); - actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), 10); + actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); UtAssert_True(strcmp(Buf_send_c, Buf_rcv_c) == 0, "Buf_rcv_c (%s) == Buf_send_c (%s)", Buf_rcv_c, Buf_send_c); /* Recieve back data from server, next is 8-bit charset */ expected = sizeof(Buf_each_char_rcv); - actual = OS_TimedRead(c_socket_id, Buf_each_char_rcv, sizeof(Buf_each_char_rcv), 10); + actual = OS_TimedRead(c_socket_id, Buf_each_char_rcv, sizeof(Buf_each_char_rcv), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); UtAssert_MemCmpCount(Buf_each_char_rcv, sizeof(Buf_each_char_rcv), "Verify byte count pattern"); /* Server should close the socket, reads will return 0 indicating EOF */ expected = 0; - actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), 10); + actual = OS_TimedRead(c_socket_id, Buf_rcv_c, sizeof(Buf_rcv_c), UT_TIMEOUT); UtAssert_True(actual == expected, "OS_TimedRead() (%ld) == %ld", (long)actual, (long)expected); } @@ -767,7 +785,7 @@ void TestStreamNetworkApi(void) loopcnt = 0; while ((OS_TaskGetInfo(s_task_id, &taskprop) == OS_SUCCESS) && (loopcnt < UT_EXIT_LOOP_MAX)) { - OS_TaskDelay(10); + OS_TaskDelay(UT_TIMEOUT); loopcnt++; } UtAssert_True(loopcnt < UT_EXIT_LOOP_MAX, "Task exited after %ld iterations", (long)loopcnt); diff --git a/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c b/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c index 3cc10d031..e2e41af96 100644 --- a/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c +++ b/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c @@ -108,8 +108,6 @@ void Test_OS_SocketOpen_Impl(void) UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 1, -1); OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (&token), OS_SUCCESS); UtAssert_STUB_COUNT(OCS_fcntl, 1); - UtAssert_True(!UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), - "Socket not selectable without O_NONBLOCK flag"); /* Failure in fcntl() SETFL */ UT_PortablePosixIOTest_ResetImpl(token.obj_idx); @@ -117,8 +115,6 @@ void Test_OS_SocketOpen_Impl(void) UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 2, -1); OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (&token), OS_SUCCESS); UtAssert_STUB_COUNT(OCS_fcntl, 2); - UtAssert_True(!UT_PortablePosixIOTest_Get_Selectable(token.obj_idx), - "Socket not selectable without O_NONBLOCK flag"); } void Test_OS_SocketBind_Impl(void) @@ -266,8 +262,6 @@ void Test_OS_SocketAccept_Impl(void) UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 1, -1); OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS); UtAssert_STUB_COUNT(OCS_fcntl, 1); - UtAssert_True(!UT_PortablePosixIOTest_Get_Selectable(conn_token.obj_idx), - "Socket not selectable without O_NONBLOCK flag"); /* Failure in fcntl() SETFL */ UT_PortablePosixIOTest_ResetImpl(conn_token.obj_idx); @@ -275,8 +269,6 @@ void Test_OS_SocketAccept_Impl(void) UT_SetDeferredRetcode(UT_KEY(OCS_fcntl), 2, -1); OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS); UtAssert_STUB_COUNT(OCS_fcntl, 2); - UtAssert_True(!UT_PortablePosixIOTest_Get_Selectable(conn_token.obj_idx), - "Socket not selectable without O_NONBLOCK flag"); } void Test_OS_SocketRecvFrom_Impl(void) From e98a75c23e5124dce948333ffcd5af014588e6e5 Mon Sep 17 00:00:00 2001 From: "Gerardo E. Cruz-Ortiz" <59618057+astrogeco@users.noreply.github.com> Date: Mon, 10 May 2021 22:24:43 -0400 Subject: [PATCH 8/9] Fix nasa#995, Enable cppcheck results output Removes --quiet option from cppcheck workflow --- .github/workflows/static-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index b81b11aa5..5016ac33f 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -32,7 +32,7 @@ jobs: - name: Run bundle cppcheck if: ${{matrix.cppcheck =='all'}} - run: cppcheck --force --inline-suppr --quiet . 2> ${{matrix.cppcheck}}_cppcheck_err.txt + run: cppcheck --force --inline-suppr . 2> ${{matrix.cppcheck}}_cppcheck_err.txt # Run strict static analysis for embedded portions of osal - name: osal strict cppcheck From 7cba4b8bb9948d6f3be2834faa87735e3b24cd0b Mon Sep 17 00:00:00 2001 From: "Gerardo E. Cruz-Ortiz" <59618057+astrogeco@users.noreply.github.com> Date: Wed, 12 May 2021 11:25:46 -0400 Subject: [PATCH 9/9] IC:2021-05-11, Bump to v5.1.0-rc1+dev434 --- README.md | 10 ++++++++++ src/os/inc/osapi-version.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index def26b8eb..7ec3d55e2 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,16 @@ The autogenerated OSAL user's guide can be viewed at and + ### Development Build: v5.1.0-rc1+dev417 - Fixes infinite loop in `UtPrintx()`. Adds the data's memory address to output. Note, UtPrintf displays the the file/line of the `UtPrintx` function, **not the actual test location**; it is better to call `UT_BSP_DoText` directly. diff --git a/src/os/inc/osapi-version.h b/src/os/inc/osapi-version.h index 25138e42c..9b9805085 100644 --- a/src/os/inc/osapi-version.h +++ b/src/os/inc/osapi-version.h @@ -34,7 +34,7 @@ /* * Development Build Macro Definitions */ -#define OS_BUILD_NUMBER 417 +#define OS_BUILD_NUMBER 434 #define OS_BUILD_BASELINE "v5.1.0-rc1" /*