--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_platform_types_posix.h\r
+ * @brief Definitions of platform layer types on POSIX systems.\r
+ */\r
+\r
+#ifndef _IOT_PLATFORM_TYPES_AFR_H_\r
+#define _IOT_PLATFORM_TYPES_AFR_H_\r
+\r
+#include "timers.h"\r
+\r
+typedef struct iot_mutex_internal\r
+{\r
+ StaticSemaphore_t xMutex; /**< FreeRTOS mutex. */\r
+ BaseType_t recursive; /**< Type; used for indicating if this is reentrant or normal. */\r
+} iot_mutex_internal_t;\r
+\r
+/**\r
+ * @brief The native mutex type on AFR systems.\r
+ */\r
+typedef iot_mutex_internal_t _IotSystemMutex_t;\r
+\r
+typedef struct iot_sem_internal\r
+{\r
+ StaticSemaphore_t xSemaphore; /**< FreeRTOS semaphore. */\r
+} iot_sem_internal_t;\r
+\r
+/**\r
+ * @brief The native semaphore type on AFR systems.\r
+ */\r
+typedef iot_sem_internal_t _IotSystemSemaphore_t;\r
+\r
+/**\r
+ * @brief Holds information about an active detached thread so that we can\r
+ * delete the FreeRTOS task when it completes\r
+ */\r
+typedef struct threadInfo\r
+{\r
+ void * pArgument; /**< @brief Argument to `threadRoutine`. */\r
+ void ( *threadRoutine )( void * );/**< @brief Thread function to run. */\r
+} threadInfo_t;\r
+\r
+/**\r
+ * @brief Holds information about an active timer.\r
+ */\r
+typedef struct timerInfo\r
+{\r
+ TimerHandle_t timer; /**< @brief Underlying timer. */\r
+ void ( *threadRoutine )( void * ); /**< @brief Thread function to run on timer expiration. */\r
+ void * pArgument; /**< @brief First argument to threadRoutine. */\r
+ StaticTimer_t xTimerBuffer; /**< Memory that holds the FreeRTOS timer. */\r
+ TickType_t xTimerPeriod; /**< Period of this timer. */\r
+} timerInfo_t;\r
+\r
+/**\r
+ * @brief Represents an #IotTimer_t on AFR systems.\r
+ */\r
+typedef timerInfo_t _IotSystemTimer_t;\r
+\r
+#endif /* ifndef _IOT_PLATFORM_TYPES_POSIX_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_clock.h\r
+ * @brief Time-related functions used by libraries in this SDK.\r
+ */\r
+\r
+#ifndef IOT_CLOCK_H_\r
+#define IOT_CLOCK_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/* Platform layer types include. */\r
+#include "types/iot_platform_types.h"\r
+\r
+/**\r
+ * @functionspage{platform_clock,platform clock component,Clock}\r
+ * - @functionname{platform_clock_function_gettimestring}\r
+ * - @functionname{platform_clock_function_gettimems}\r
+ * - @functionname{platform_clock_function_sleepms}\r
+ * - @functionname{platform_clock_function_timercreate}\r
+ * - @functionname{platform_clock_function_timerdestroy}\r
+ * - @functionname{platform_clock_function_timerarm}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotClock_GetTimestring,platform_clock,gettimestring}\r
+ * @functionpage{IotClock_GetTimeMs,platform_clock,gettimems}\r
+ * @functionpage{IotClock_SleepMs,platform_clock,sleepms}\r
+ * @functionpage{IotClock_TimerCreate,platform_clock,timercreate}\r
+ * @functionpage{IotClock_TimerDestroy,platform_clock,timerdestroy}\r
+ * @functionpage{IotClock_TimerArm,platform_clock,timerarm}\r
+ */\r
+\r
+/**\r
+ * @brief Generates a human-readable timestring, such as "01 Jan 2018 12:00".\r
+ *\r
+ * This function uses the system clock to generate a human-readable timestring.\r
+ * This timestring is printed by the [logging functions](@ref logging_functions).\r
+ *\r
+ * @param[out] pBuffer A buffer to store the timestring in.\r
+ * @param[in] bufferSize The size of `pBuffer`.\r
+ * @param[out] pTimestringLength The actual length of the timestring stored in\r
+ * `pBuffer`.\r
+ *\r
+ * @return `true` if a timestring was successfully generated; `false` otherwise.\r
+ *\r
+ * @warning The implementation of this function must not call any [logging functions]\r
+ * (@ref logging_functions).\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * char timestring[ 32 ];\r
+ * size_t timestringLength = 0;\r
+ *\r
+ * if( IotClock_GetTimestring( timestring, 32, ×tringLength ) == true )\r
+ * {\r
+ * printf( "Timestring: %.*s", timestringLength, timestring );\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_clock_gettimestring] */\r
+bool IotClock_GetTimestring( char * pBuffer,\r
+ size_t bufferSize,\r
+ size_t * pTimestringLength );\r
+/* @[declare_platform_clock_gettimestring] */\r
+\r
+/**\r
+ * @brief Returns a nonzero, monotonically-increasing system time in milliseconds.\r
+ *\r
+ * This function reads a millisecond-resolution system clock. The clock should\r
+ * always be monotonically-increasing; therefore, real-time clocks that may be\r
+ * set by another process are not suitable for this function's implementation.\r
+ *\r
+ * @return The value of the system clock. This function is not expected to fail.\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * // Get current time.\r
+ * uint64_t currentTime = IotClock_GetTimeMs();\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_clock_gettimems] */\r
+uint64_t IotClock_GetTimeMs( void );\r
+/* @[declare_platform_clock_gettimems] */\r
+\r
+/**\r
+ * @brief Delay for the given number of milliseconds.\r
+ *\r
+ * This function suspends its calling thread for at least `sleepTimeMs` milliseconds.\r
+ *\r
+ * @param[in] sleepTimeMs Sleep time (in milliseconds).\r
+ */\r
+/* @[declare_platform_clock_sleepms] */\r
+void IotClock_SleepMs( uint32_t sleepTimeMs );\r
+/* @[declare_platform_clock_sleepms] */\r
+\r
+/**\r
+ * @brief Create a new timer.\r
+ *\r
+ * This function creates a new, unarmed timer. It must be called on an uninitialized\r
+ * #IotTimer_t. This function must not be called on an already-initialized #IotTimer_t.\r
+ *\r
+ * @param[out] pNewTimer Set to a new timer handle on success.\r
+ * @param[in] expirationRoutine The function to run when this timer expires. This\r
+ * function should be called in its own <i>detached</i> thread.\r
+ * @param[in] pArgument The argument to pass to `expirationRoutine`.\r
+ *\r
+ * @return `true` if the timer is successfully created; `false` otherwise.\r
+ *\r
+ * @see @ref platform_clock_function_timerdestroy, @ref platform_clock_function_timerarm\r
+ */\r
+/* @[declare_platform_clock_timercreate] */\r
+bool IotClock_TimerCreate( IotTimer_t * pNewTimer,\r
+ IotThreadRoutine_t expirationRoutine,\r
+ void * pArgument );\r
+/* @[declare_platform_clock_timercreate] */\r
+\r
+/**\r
+ * @brief Free resources used by a timer.\r
+ *\r
+ * This function frees resources used by a timer. It must be called on an initialized\r
+ * #IotTimer_t. No other timer functions should be called on `pTimer` after calling\r
+ * this function (unless the timer is re-created).\r
+ *\r
+ * This function will stop the `pTimer` if it is armed.\r
+ *\r
+ * @param[in] pTimer The timer to destroy.\r
+ *\r
+ * @see @ref platform_clock_function_timercreate, @ref platform_clock_function_timerarm\r
+ */\r
+/* @[declare_platform_clock_timerdestroy] */\r
+void IotClock_TimerDestroy( IotTimer_t * pTimer );\r
+/* @[declare_platform_clock_timerdestroy] */\r
+\r
+/**\r
+ * @brief Arm a timer to expire at the given relative timeout.\r
+ *\r
+ * This function arms a timer to run its expiration routine at the given time.\r
+ *\r
+ * If `periodMs` is nonzero, the timer should expire periodically at intervals\r
+ * such as:\r
+ * - `relativeTimeoutMs`\r
+ * - `relativeTimeoutMs + periodMs`\r
+ * - `relativeTimeoutMs + 2 * periodMs`\r
+ * - Etc. (subject to some jitter).\r
+ *\r
+ * Setting `periodMs` to `0` arms a one-shot, non-periodic timer.\r
+ *\r
+ * @param[in] pTimer The timer to arm.\r
+ * @param[in] relativeTimeoutMs When the timer should expire, relative to the time\r
+ * this function is called.\r
+ * @param[in] periodMs How often the timer should expire again after `relativeTimerMs`.\r
+ *\r
+ * @return `true` if the timer was successfully armed; `false` otherwise.\r
+ *\r
+ * @see @ref platform_clock_function_timercreate, @ref platform_clock_function_timerdestroy\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ *\r
+ * void timerExpirationRoutine( void * pArgument );\r
+ *\r
+ * void timerExample( void )\r
+ * {\r
+ * IotTimer_t timer;\r
+ *\r
+ * if( IotClock_TimerCreate( &timer, timerExpirationRoutine, NULL ) == true )\r
+ * {\r
+ * // Set the timer to periodically expire every 10 seconds.\r
+ * if( IotClock_TimerArm( &timer, 10000, 10000 ) == true )\r
+ * {\r
+ * // Wait for timer to expire.\r
+ * }\r
+ *\r
+ * IotClock_TimerDestroy( &timer );\r
+ * }\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_clock_timerarm] */\r
+bool IotClock_TimerArm( IotTimer_t * pTimer,\r
+ uint32_t relativeTimeoutMs,\r
+ uint32_t periodMs );\r
+/* @[declare_platform_clock_timerarm] */\r
+\r
+#endif /* ifndef IOT_CLOCK_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_metrics.h\r
+ * @brief Functions for retrieving [Device Defender](@ref defender) metrics.\r
+ *\r
+ * The functions in this header are only required by Device Defender. They do not\r
+ * need to be implemented if Device Defender is not used.\r
+ */\r
+\r
+#ifndef IOT_METRICS_H_\r
+#define IOT_METRICS_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+\r
+/* Linear containers (lists and queues) include. */\r
+#include "iot_linear_containers.h"\r
+\r
+/**\r
+ * @functionspage{platform_metrics,platform metrics component,Metrics}\r
+ * - @functionname{platform_metrics_function_init}\r
+ * - @functionname{platform_metrics_function_cleanup}\r
+ * - @functionname{platform_metrics_function_gettcpconnections}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotMetrics_Init,platform_metrics,init}\r
+ * @functionpage{IotMetrics_Cleanup,platform_metrics,cleanup}\r
+ * @functionpage{IotMetrics_GetTcpConnections,platform_metrics,gettcpconnections}\r
+ */\r
+\r
+/**\r
+ * @brief One-time initialization function for the platform metrics component.\r
+ *\r
+ * This function initializes the platform metrics component. <b>It must be called\r
+ * once (and only once) before calling any other metrics or [Device Defender function]\r
+ * (@ref defender_functions).</b> Calling this function more than once without first\r
+ * calling @ref platform_metrics_function_cleanup may result in a crash.\r
+ *\r
+ * @return `true` is initialization succeeded; `false` otherwise.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ */\r
+/* @[declare_platform_metrics_init] */\r
+bool IotMetrics_Init( void );\r
+/* @[declare_platform_metrics_init] */\r
+\r
+/**\r
+ * @brief One-time deinitialization function for the platform metrics component.\r
+ *\r
+ * This function frees resources taken in @ref platform_metrics_function_init.\r
+ * No other metrics or [Device Defender functions](@ref defender_functions) may\r
+ * be called unless @ref platform_metrics_function_init is called again.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ */\r
+/* @[declare_platform_metrics_cleanup] */\r
+void IotMetrics_Cleanup( void );\r
+/* @[declare_platform_metrics_cleanup] */\r
+\r
+/**\r
+ * @brief Retrieve a list of active TCP connections from the system.\r
+ *\r
+ * The provided connections are reported by Device Defender.\r
+ *\r
+ * @param[in] pContext Context passed as the first parameter of `metricsCallback`.\r
+ * @param[in] metricsCallback Called by this function to provide the list of TCP\r
+ * connections. The list given by this function is should not be used after the\r
+ * callback returns.\r
+ */\r
+/* @[declare_platform_metrics_gettcpconnections] */\r
+void IotMetrics_GetTcpConnections( void * pContext,\r
+ void ( * metricsCallback )( void *, const IotListDouble_t * ) );\r
+/* @[declare_platform_metrics_gettcpconnections] */\r
+\r
+#endif /* ifndef IOT_METRICS_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_network.h\r
+ * @brief Abstraction of network functions used by libraries in this SDK.\r
+ */\r
+\r
+#ifndef IOT_NETWORK_H_\r
+#define IOT_NETWORK_H_\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+\r
+/**\r
+ * @ingroup platform_datatypes_enums\r
+ * @brief Return codes for [network functions](@ref platform_network_functions).\r
+ */\r
+typedef enum IotNetworkError\r
+{\r
+ IOT_NETWORK_SUCCESS = 0, /**< Function successfully completed. */\r
+ IOT_NETWORK_FAILURE, /**< Generic failure not covered by other values. */\r
+ IOT_NETWORK_BAD_PARAMETER, /**< At least one parameter was invalid. */\r
+ IOT_NETWORK_NO_MEMORY, /**< Memory allocation failed. */\r
+ IOT_NETWORK_SYSTEM_ERROR /**< An error occurred when calling a system API. */\r
+} IotNetworkError_t;\r
+\r
+/**\r
+ * @page platform_network_functions Networking\r
+ * @brief Functions of the network abstraction component.\r
+ *\r
+ * The network abstraction component does not declare functions, but uses function\r
+ * pointers instead. This allows multiple network stacks to be used at the same time.\r
+ * Libraries that require the network will request an #IotNetworkInterface_t\r
+ * parameter. The members of the #IotNetworkInterface_t will be called whenever\r
+ * the library interacts with the network.\r
+ *\r
+ * The following function pointers are associated with an #IotNetworkInterface_t.\r
+ * Together, they represent a network stack.\r
+ * - @functionname{platform_network_function_create}\r
+ * - @functionname{platform_network_function_setreceivecallback}\r
+ * - @functionname{platform_network_function_send}\r
+ * - @functionname{platform_network_function_receive}\r
+ * - @functionname{platform_network_function_close}\r
+ * - @functionname{platform_network_function_destroy}\r
+ * - @functionname{platform_network_function_receivecallback}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotNetworkInterface_t::create,platform_network,create}\r
+ * @functionpage{IotNetworkInterface_t::setReceiveCallback,platform_network,setreceivecallback}\r
+ * @functionpage{IotNetworkInterface_t::send,platform_network,send}\r
+ * @functionpage{IotNetworkInterface_t::receive,platform_network,receive}\r
+ * @functionpage{IotNetworkInterface_t::close,platform_network,close}\r
+ * @functionpage{IotNetworkInterface_t::destroy,platform_network,destroy}\r
+ * @functionpage{IotNetworkReceiveCallback_t,platform_network,receivecallback}\r
+ */\r
+\r
+/**\r
+ * @brief Provide an asynchronous notification of incoming network data.\r
+ *\r
+ * A function with this signature may be set with @ref platform_network_function_setreceivecallback\r
+ * to be invoked when data is available on the network.\r
+ *\r
+ * @param[in] pConnection The connection on which data is available, defined by\r
+ * the network stack.\r
+ * @param[in] pContext The third argument passed to @ref platform_network_function_setreceivecallback.\r
+ */\r
+/* @[declare_platform_network_receivecallback] */\r
+typedef void ( * IotNetworkReceiveCallback_t )( void * pConnection,\r
+ void * pContext );\r
+/* @[declare_platform_network_receivecallback] */\r
+\r
+/**\r
+ * @ingroup platform_datatypes_paramstructs\r
+ * @brief Represents the functions of a network stack.\r
+ *\r
+ * Functions that match these signatures should be implemented against a system's\r
+ * network stack. See the `platform` directory for existing implementations.\r
+ */\r
+typedef struct IotNetworkInterface\r
+{\r
+ /**\r
+ * @brief Create a new network connection.\r
+ *\r
+ * This function allocates resources and establishes a new network connection.\r
+ * @param[in] pConnectionInfo Represents information needed to set up the\r
+ * new connection, defined by the network stack.\r
+ * @param[in] pCredentialInfo Represents information needed to secure the\r
+ * new connection, defined by the network stack.\r
+ * @param[out] pConnection Set to represent a new connection, defined by the\r
+ * network stack.\r
+ *\r
+ * @return Any #IotNetworkError_t, as defined by the network stack.\r
+ */\r
+ /* @[declare_platform_network_create] */\r
+ IotNetworkError_t ( * create )( void * pConnectionInfo,\r
+ void * pCredentialInfo,\r
+ void ** pConnection );\r
+ /* @[declare_platform_network_create] */\r
+\r
+ /**\r
+ * @brief Register an @ref platform_network_function_receivecallback.\r
+ *\r
+ * Sets an @ref platform_network_function_receivecallback to be called\r
+ * asynchronously when data arrives on the network. The network stack\r
+ * should invoke this function "as if" it were the thread routine of a\r
+ * detached thread.\r
+ *\r
+ * Each network connection may only have one receive callback at any time.\r
+ * @ref platform_network_function_close is expected to remove any active\r
+ * receive callbacks.\r
+ *\r
+ * @param[in] pConnection The connection to associate with the receive callback.\r
+ * @param[in] receiveCallback The function to invoke for incoming network data.\r
+ * @param[in] pContext A value to pass as the first parameter to the receive callback.\r
+ *\r
+ * @return Any #IotNetworkError_t, as defined by the network stack.\r
+ *\r
+ * @see platform_network_function_receivecallback\r
+ */\r
+ /* @[declare_platform_network_setreceivecallback] */\r
+ IotNetworkError_t ( * setReceiveCallback )( void * pConnection,\r
+ IotNetworkReceiveCallback_t receiveCallback,\r
+ void * pContext );\r
+ /* @[declare_platform_network_setreceivecallback] */\r
+\r
+ /**\r
+ * @brief Send data over a return connection.\r
+ *\r
+ * Attempts to transmit `messageLength` bytes of `pMessage` across the\r
+ * connection represented by `pConnection`. Returns the number of bytes\r
+ * actually sent, `0` on failure.\r
+ *\r
+ * @param[in] pConnection The connection used to send data, defined by the\r
+ * network stack.\r
+ * @param[in] pMessage The message to send.\r
+ * @param[in] messageLength The length of `pMessage`.\r
+ *\r
+ * @return The number of bytes successfully sent, `0` on failure.\r
+ */\r
+ /* @[declare_platform_network_send] */\r
+ size_t ( * send )( void * pConnection,\r
+ const uint8_t * pMessage,\r
+ size_t messageLength );\r
+ /* @[declare_platform_network_send] */\r
+\r
+ /**\r
+ * @brief Block and wait for incoming network data.\r
+ *\r
+ * Wait for a message of size `bytesRequested` to arrive on the network and\r
+ * place it in `pBuffer`.\r
+ *\r
+ * @param[in] pConnection The connection to wait on, defined by the network\r
+ * stack.\r
+ * @param[out] pBuffer Where to place the incoming network data. This buffer\r
+ * must be at least `bytesRequested` in size.\r
+ * @param[in] bytesRequested How many bytes to wait for. `pBuffer` must be at\r
+ * least this size.\r
+ *\r
+ * @return The number of bytes successfully received. This should be\r
+ * `bytesRequested` when successful. Any other value may indicate an error.\r
+ */\r
+ /* @[declare_platform_network_receive] */\r
+ size_t ( * receive )( void * pConnection,\r
+ uint8_t * pBuffer,\r
+ size_t bytesRequested );\r
+ /* @[declare_platform_network_receive] */\r
+\r
+ /**\r
+ * @brief Close a network connection.\r
+ *\r
+ * This function closes the connection, but does not release the resources\r
+ * used by the connection. This allows calls to other networking functions\r
+ * to return an error and handle a closed connection without the risk of\r
+ * crashing. Once it can be guaranteed that `pConnection` will no longer be\r
+ * used, the connection can be destroyed with @ref platform_network_function_destroy.\r
+ *\r
+ * In addition to closing the connection, this function should also remove\r
+ * any active [receive callback](@ref platform_network_function_receivecallback).\r
+ *\r
+ * @param[in] pConnection The network connection to close, defined by the\r
+ * network stack.\r
+ *\r
+ * @return Any #IotNetworkError_t, as defined by the network stack.\r
+ *\r
+ * @note It must be safe to call this function on an already-closed connection.\r
+ */\r
+ /* @[declare_platform_network_close] */\r
+ IotNetworkError_t ( * close )( void * pConnection );\r
+ /* @[declare_platform_network_close] */\r
+\r
+ /**\r
+ * @brief Free resources used by a network connection.\r
+ *\r
+ * This function releases the resources of a closed connection. It should be\r
+ * called after @ref platform_network_function_close.\r
+ *\r
+ * @param[in] pConnection The network connection to destroy, defined by\r
+ * the network stack.\r
+ *\r
+ * @return Any #IotNetworkError_t, as defined by the network stack.\r
+ *\r
+ * @attention No function should be called on the network connection after\r
+ * calling this function. This function must be safe to call from a\r
+ * [receive callback](@ref platform_network_function_receivecallback).\r
+ */\r
+ /* @[declare_platform_network_destroy] */\r
+ IotNetworkError_t ( * destroy )( void * pConnection );\r
+ /* @[declare_platform_network_destroy] */\r
+} IotNetworkInterface_t;\r
+\r
+/**\r
+ * @ingroup platform_datatypes_paramstructs\r
+ * @brief Information on the remote server for connection setup.\r
+ *\r
+ * May be passed to #IotNetworkInterface_t.create as `pConnectionInfo`. This\r
+ * structure contains commonly-used parameters, but may be replaced with an\r
+ * alternative.\r
+ */\r
+typedef struct IotNetworkServerInfo\r
+{\r
+ const char * pHostName; /**< @brief Server host name. Must be NULL-terminated. */\r
+ uint16_t port; /**< @brief Server port in host-order. */\r
+} IotNetworkServerInfo_t;\r
+\r
+/**\r
+ * @ingroup platform_datatypes_paramstructs\r
+ * @brief Contains the credentials necessary for connection setup.\r
+ *\r
+ * May be passed to #IotNetworkInterface_t.create as `pCredentialInfo`. This\r
+ * structure contains commonly-used parameters, but may be replaced with an\r
+ * alternative.\r
+ */\r
+typedef struct IotNetworkCredentials\r
+{\r
+ /**\r
+ * @brief Set this to a non-NULL value to use ALPN.\r
+ *\r
+ * This string must be NULL-terminated.\r
+ *\r
+ * See [this link]\r
+ * (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/)\r
+ * for more information.\r
+ */\r
+ const char * pAlpnProtos;\r
+\r
+ /**\r
+ * @brief Set this to a non-zero value to use TLS max fragment length\r
+ * negotiation (TLS MFLN).\r
+ *\r
+ * @note The network stack may have a minimum value for this parameter and\r
+ * may return an error if this parameter is too small.\r
+ */\r
+ size_t maxFragmentLength;\r
+\r
+ /**\r
+ * @brief Disable server name indication (SNI) for a TLS session.\r
+ */\r
+ bool disableSni;\r
+\r
+ const char * pRootCa; /**< @brief String representing a trusted server root certificate. */\r
+ size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials_t.pRootCa. */\r
+ const char * pClientCert; /**< @brief String representing the client certificate. */\r
+ size_t clientCertSize; /**< @brief Size associated with #IotNetworkCredentials_t.pClientCert. */\r
+ const char * pPrivateKey; /**< @brief String representing the client certificate's private key. */\r
+ size_t privateKeySize; /**< @brief Size associated with #IotNetworkCredentials_t.pPrivateKey. */\r
+} IotNetworkCredentials_t;\r
+\r
+#endif /* ifndef IOT_NETWORK_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_threads.h\r
+ * @brief Threading and synchronization functions used by libraries in this SDK.\r
+ */\r
+\r
+#ifndef IOT_THREADS_H_\r
+#define IOT_THREADS_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+\r
+/* Platform layer types include. */\r
+#include "types/iot_platform_types.h"\r
+\r
+/**\r
+ * @functionspage{platform_threads,platform thread management,Thread Management}\r
+ * - @functionname{platform_threads_function_createdetachedthread}\r
+ * - @functionname{platform_threads_function_mutexcreate}\r
+ * - @functionname{platform_threads_function_mutexdestroy}\r
+ * - @functionname{platform_threads_function_mutexlock}\r
+ * - @functionname{platform_threads_function_mutextrylock}\r
+ * - @functionname{platform_threads_function_mutexunlock}\r
+ * - @functionname{platform_threads_function_semaphorecreate}\r
+ * - @functionname{platform_threads_function_semaphoredestroy}\r
+ * - @functionname{platform_threads_function_semaphoregetcount}\r
+ * - @functionname{platform_threads_function_semaphorewait}\r
+ * - @functionname{platform_threads_function_semaphoretrywait}\r
+ * - @functionname{platform_threads_function_semaphoretimedwait}\r
+ * - @functionname{platform_threads_function_semaphorepost}\r
+ */\r
+\r
+/**\r
+ * @functionpage{Iot_CreateDetachedThread,platform_threads,createdetachedthread}\r
+ * @functionpage{IotMutex_Create,platform_threads,mutexcreate}\r
+ * @functionpage{IotMutex_Destroy,platform_threads,mutexdestroy}\r
+ * @functionpage{IotMutex_Lock,platform_threads,mutexlock}\r
+ * @functionpage{IotMutex_TryLock,platform_threads,mutextrylock}\r
+ * @functionpage{IotMutex_Unlock,platform_threads,mutexunlock}\r
+ * @functionpage{IotSemaphore_Create,platform_threads,semaphorecreate}\r
+ * @functionpage{IotSemaphore_Destroy,platform_threads,semaphoredestroy}\r
+ * @functionpage{IotSemaphore_GetCount,platform_threads,semaphoregetcount}\r
+ * @functionpage{IotSemaphore_Wait,platform_threads,semaphorewait}\r
+ * @functionpage{IotSemaphore_TryWait,platform_threads,semaphoretrywait}\r
+ * @functionpage{IotSemaphore_TimedWait,platform_threads,semaphoretimedwait}\r
+ * @functionpage{IotSemaphore_Post,platform_threads,semaphorepost}\r
+ */\r
+\r
+/**\r
+ * @brief Create a new detached thread, i.e. a thread that cleans up after itself.\r
+ *\r
+ * This function creates a new thread. Threads created by this function exit\r
+ * upon returning from the thread routine. Any resources taken must be freed\r
+ * by the exiting thread.\r
+ *\r
+ * @param[in] threadRoutine The function this thread should run.\r
+ * @param[in] pArgument The argument passed to `threadRoutine`.\r
+ * @param[in] priority Represents the priority of the new thread, as defined by\r
+ * the system. The value #IOT_THREAD_DEFAULT_PRIORITY (i.e. `0`) must be used to\r
+ * represent the system default for thread priority.\r
+ * @param[in] stackSize Represents the stack size of the new thread, as defined\r
+ * by the system. The value #IOT_THREAD_DEFAULT_STACK_SIZE (i.e. `0`) must be used\r
+ * to represent the system default for stack size.\r
+ *\r
+ * @return `true` if the new thread was successfully created; `false` otherwise.\r
+ *\r
+ * @code{c}\r
+ * // Thread routine.\r
+ * void threadRoutine( void * pArgument );\r
+ *\r
+ * // Run threadRoutine in a detached thread, using default priority and stack size.\r
+ * if( Iot_CreateDetachedThread( threadRoutine,\r
+ * NULL,\r
+ * IOT_THREAD_DEFAULT_PRIORITY,\r
+ * IOT_THREAD_DEFAULT_STACK_SIZE ) == true )\r
+ * {\r
+ * // Success\r
+ * }\r
+ * else\r
+ * {\r
+ * // Failure, no thread was created.\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_threads_createdetachedthread] */\r
+bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine,\r
+ void * pArgument,\r
+ int32_t priority,\r
+ size_t stackSize );\r
+/* @[declare_platform_threads_createdetachedthread] */\r
+\r
+/**\r
+ * @brief Create a new mutex.\r
+ *\r
+ * This function creates a new, unlocked mutex. It must be called on an uninitialized\r
+ * #IotMutex_t. This function must not be called on an already-initialized #IotMutex_t.\r
+ *\r
+ * @param[in] pNewMutex Pointer to the memory that will hold the new mutex.\r
+ * @param[in] recursive Set to `true` to create a recursive mutex, i.e. a mutex that\r
+ * may be locked multiple times by the same thread. If the system does not support\r
+ * recursive mutexes, this function should do nothing and return `false`.\r
+ *\r
+ * @return `true` if mutex creation succeeds; `false` otherwise.\r
+ *\r
+ * @see @ref platform_threads_function_mutexdestroy\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * IotMutex_t mutex;\r
+ *\r
+ * // Create non-recursive mutex.\r
+ * if( IotMutex_Create( &mutex, false ) == true )\r
+ * {\r
+ * // Lock and unlock the mutex...\r
+ *\r
+ * // Destroy the mutex when it's no longer needed.\r
+ * IotMutex_Destroy( &mutex );\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_threads_mutexcreate] */\r
+bool IotMutex_Create( IotMutex_t * pNewMutex, bool recursive );\r
+/* @[declare_platform_threads_mutexcreate] */\r
+\r
+/**\r
+ * @brief Free resources used by a mutex.\r
+ *\r
+ * This function frees resources used by a mutex. It must be called on an initialized\r
+ * #IotMutex_t. No other mutex functions should be called on `pMutex` after calling\r
+ * this function (unless the mutex is re-created).\r
+ *\r
+ * @param[in] pMutex The mutex to destroy.\r
+ *\r
+ * @warning This function must not be called on a locked mutex.\r
+ * @see @ref platform_threads_function_mutexcreate\r
+ */\r
+/* @[declare_platform_threads_mutexdestroy] */\r
+void IotMutex_Destroy( IotMutex_t * pMutex );\r
+/* @[declare_platform_threads_mutexdestroy] */\r
+\r
+/**\r
+ * @brief Lock a mutex. This function should only return when the mutex is locked;\r
+ * it is not expected to fail.\r
+ *\r
+ * This function blocks and waits until a mutex is available. It waits forever\r
+ * (deadlocks) if `pMutex` is already locked and never unlocked.\r
+ *\r
+ * @param[in] pMutex The mutex to lock.\r
+ *\r
+ * @see @ref platform_threads_function_mutextrylock for a nonblocking lock.\r
+ */\r
+/* @[declare_platform_threads_mutexlock] */\r
+void IotMutex_Lock( IotMutex_t * pMutex );\r
+/* @[declare_platform_threads_mutexlock] */\r
+\r
+/**\r
+ * @brief Attempt to lock a mutex. Return immediately if the mutex is not available.\r
+ *\r
+ * If `pMutex` is available, this function immediately locks it and returns.\r
+ * Otherwise, this function returns without locking `pMutex`.\r
+ *\r
+ * @param[in] pMutex The mutex to lock.\r
+ *\r
+ * @return `true` if the mutex was successfully locked; `false` if the mutex was\r
+ * not available.\r
+ *\r
+ * @see @ref platform_threads_function_mutexlock for a blocking lock.\r
+ */\r
+/* @[declare_platform_threads_mutextrylock] */\r
+bool IotMutex_TryLock( IotMutex_t * pMutex );\r
+/* @[declare_platform_threads_mutextrylock] */\r
+\r
+/**\r
+ * @brief Unlock a mutex. This function should only return when the mutex is unlocked;\r
+ * it is not expected to fail.\r
+ *\r
+ * Unlocks a locked mutex. `pMutex` must have been locked by the thread calling\r
+ * this function.\r
+ *\r
+ * @param[in] pMutex The mutex to unlock.\r
+ *\r
+ * @note This function should not be called on a mutex that is already unlocked.\r
+ */\r
+/* @[declare_platform_threads_mutexunlock] */\r
+void IotMutex_Unlock( IotMutex_t * pMutex );\r
+/* @[declare_platform_threads_mutexunlock] */\r
+\r
+/**\r
+ * @brief Create a new counting semaphore.\r
+ *\r
+ * This function creates a new counting semaphore with a given intial and\r
+ * maximum value. It must be called on an uninitialized #IotSemaphore_t.\r
+ * This function must not be called on an already-initialized #IotSemaphore_t.\r
+ *\r
+ * @param[in] pNewSemaphore Pointer to the memory that will hold the new semaphore.\r
+ * @param[in] initialValue The semaphore should be initialized with this value.\r
+ * @param[in] maxValue The maximum value the semaphore will reach.\r
+ *\r
+ * @return `true` if semaphore creation succeeds; `false` otherwise.\r
+ *\r
+ * @see @ref platform_threads_function_semaphoredestroy\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * IotSemaphore_t sem;\r
+ *\r
+ * // Create a locked binary semaphore.\r
+ * if( IotSemaphore_Create( &sem, 0, 1 ) == true )\r
+ * {\r
+ * // Unlock the semaphore.\r
+ * IotSemaphore_Post( &sem );\r
+ *\r
+ * // Destroy the semaphore when it's no longer needed.\r
+ * IotSemaphore_Destroy( &sem );\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_platform_threads_semaphorecreate] */\r
+bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore,\r
+ uint32_t initialValue,\r
+ uint32_t maxValue );\r
+/* @[declare_platform_threads_semaphorecreate] */\r
+\r
+/**\r
+ * @brief Free resources used by a semaphore.\r
+ *\r
+ * This function frees resources used by a semaphore. It must be called on an initialized\r
+ * #IotSemaphore_t. No other semaphore functions should be called on `pSemaphore` after\r
+ * calling this function (unless the semaphore is re-created).\r
+ *\r
+ * @param[in] pSemaphore The semaphore to destroy.\r
+ *\r
+ * @warning This function must not be called on a semaphore with waiting threads.\r
+ * @see @ref platform_threads_function_semaphorecreate\r
+ */\r
+/* @[declare_platform_threads_semaphoredestroy] */\r
+void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore );\r
+/* @[declare_platform_threads_semaphoredestroy] */\r
+\r
+/**\r
+ * @brief Query the current count of the semaphore.\r
+ *\r
+ * This function queries a counting semaphore for its current value. A counting\r
+ * semaphore's value is always 0 or positive.\r
+ *\r
+ * @param[in] pSemaphore The semaphore to query.\r
+ *\r
+ * @return The current count of the semaphore. This function should not fail.\r
+ */\r
+/* @[declare_platform_threads_semaphoregetcount] */\r
+uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore );\r
+/* @[declare_platform_threads_semaphoregetcount] */\r
+\r
+/**\r
+ * @brief Wait on (lock) a semaphore. This function should only return when the\r
+ * semaphore wait succeeds; it is not expected to fail.\r
+ *\r
+ * This function blocks and waits until a counting semaphore is positive. It\r
+ * waits forever (deadlocks) if `pSemaphore` has a count `0` that is never\r
+ * [incremented](@ref platform_threads_function_semaphorepost).\r
+ *\r
+ * @param[in] pSemaphore The semaphore to lock.\r
+ *\r
+ * @see @ref platform_threads_function_semaphoretrywait for a nonblocking wait;\r
+ * @ref platform_threads_function_semaphoretimedwait for a wait with timeout.\r
+ */\r
+/* @[declare_platform_threads_semaphorewait] */\r
+void IotSemaphore_Wait( IotSemaphore_t * pSemaphore );\r
+/* @[declare_platform_threads_semaphorewait] */\r
+\r
+/**\r
+ * @brief Attempt to wait on (lock) a semaphore. Return immediately if the semaphore\r
+ * is not available.\r
+ *\r
+ * If the count of `pSemaphore` is positive, this function immediately decrements\r
+ * the semaphore and returns. Otherwise, this function returns without decrementing\r
+ * `pSemaphore`.\r
+ *\r
+ * @param[in] pSemaphore The semaphore to lock.\r
+ *\r
+ * @return `true` if the semaphore wait succeeded; `false` if the semaphore has\r
+ * a count of `0`.\r
+ *\r
+ * @see @ref platform_threads_function_semaphorewait for a blocking wait;\r
+ * @ref platform_threads_function_semaphoretimedwait for a wait with timeout.\r
+ */\r
+/* @[declare_platform_threads_semaphoretrywait] */\r
+bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore );\r
+/* @[declare_platform_threads_semaphoretrywait] */\r
+\r
+/**\r
+ * @brief Attempt to wait on (lock) a semaphore with a timeout.\r
+ *\r
+ * This function blocks and waits until a counting semaphore is positive\r
+ * <i>or</i> its timeout expires (whichever is sooner). It decrements\r
+ * `pSemaphore` and returns `true` if the semaphore is positive at some\r
+ * time during the wait. If `pSemaphore` is always `0` during the wait,\r
+ * this function returns `false`.\r
+ *\r
+ * @param[in] pSemaphore The semaphore to lock.\r
+ * @param[in] timeoutMs Relative timeout of semaphore lock. This function returns\r
+ * false if the semaphore couldn't be locked within this timeout.\r
+ *\r
+ * @return `true` if the semaphore wait succeeded; `false` if it timed out.\r
+ *\r
+ * @see @ref platform_threads_function_semaphoretrywait for a nonblocking wait;\r
+ * @ref platform_threads_function_semaphorewait for a blocking wait.\r
+ */\r
+/* @[declare_platform_threads_semaphoretimedwait] */\r
+bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore,\r
+ uint32_t timeoutMs );\r
+/* @[declare_platform_threads_semaphoretimedwait] */\r
+\r
+/**\r
+ * @brief Post to (unlock) a semaphore. This function should only return when the\r
+ * semaphore post succeeds; it is not expected to fail.\r
+ *\r
+ * This function increments the count of a semaphore. Any thread may call this\r
+ * function to increment a semaphore's count.\r
+ *\r
+ * @param[in] pSemaphore The semaphore to unlock.\r
+ */\r
+/* @[declare_platform_threads_semaphorepost] */\r
+void IotSemaphore_Post( IotSemaphore_t * pSemaphore );\r
+/* @[declare_platform_threads_semaphorepost] */\r
+\r
+#endif /* ifndef IOT_THREADS_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Platform V1.0.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_platform_types.h\r
+ * @brief Types of the platform layer.\r
+ */\r
+\r
+#ifndef IOT_PLATFORM_TYPES_H_\r
+#define IOT_PLATFORM_TYPES_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Linear containers (lists and queues) include for metrics types. */\r
+#include "iot_linear_containers.h"\r
+\r
+/*------------------------- Thread management types -------------------------*/\r
+\r
+/**\r
+ * @brief A value representing the system default for new thread priority.\r
+ */\r
+#ifndef IOT_THREAD_DEFAULT_PRIORITY\r
+ #define IOT_THREAD_DEFAULT_PRIORITY 0\r
+#endif\r
+\r
+/**\r
+ * @brief A value representhing the system default for new thread stack size.\r
+ */\r
+#ifndef IOT_THREAD_DEFAULT_STACK_SIZE\r
+ #define IOT_THREAD_DEFAULT_STACK_SIZE 0\r
+#endif\r
+\r
+/**\r
+ * @ingroup platform_datatypes_handles\r
+ * @brief The type used to represent mutexes, configured with the type\r
+ * `_IotSystemMutex_t`.\r
+ *\r
+ * <span style="color:red;font-weight:bold">\r
+ * `_IotSystemMutex_t` will be automatically configured during build and generally\r
+ * does not need to be defined.\r
+ * </span>\r
+ *\r
+ * Mutexes should only be released by the threads that take them.\r
+ *\r
+ * <b>Example</b> <br>\r
+ * To change the type of #IotMutex_t to `long`:\r
+ * @code{c}\r
+ * typedef long _IotSystemMutex_t;\r
+ * #include "iot_threads.h"\r
+ * @endcode\r
+ */\r
+typedef _IotSystemMutex_t IotMutex_t;\r
+\r
+/**\r
+ * @ingroup platform_datatypes_handles\r
+ * @brief The type used to represent semaphores, configured with the type\r
+ * `_IotSystemSemaphore_t`.\r
+ *\r
+ * <span style="color:red;font-weight:bold">\r
+ * `_IotSystemSemaphore_t` will be automatically configured during build and\r
+ * generally does not need to be defined.\r
+ * </span>\r
+ *\r
+ * Semaphores must be counting, and any thread may take (wait on) or release\r
+ * (post to) a semaphore.\r
+ *\r
+ * <b>Example</b> <br>\r
+ * To change the type of #IotSemaphore_t to `long`:\r
+ * @code{c}\r
+ * typedef long _IotSystemSemaphore_t;\r
+ * #include "iot_threads.h"\r
+ * @endcode\r
+ */\r
+typedef _IotSystemSemaphore_t IotSemaphore_t;\r
+\r
+/**\r
+ * @brief Thread routine function.\r
+ *\r
+ * @param[in] void * The argument passed to the @ref\r
+ * platform_threads_function_createdetachedthread. For application use.\r
+ */\r
+typedef void ( * IotThreadRoutine_t )( void * );\r
+\r
+/*-------------------------- Clock and timer types --------------------------*/\r
+\r
+/**\r
+ * @ingroup platform_datatypes_handles\r
+ * @brief The type used to represent timers, configured with the type\r
+ * `_IotSystemTimer_t`.\r
+ *\r
+ * <span style="color:red;font-weight:bold">\r
+ * `_IotSystemTimer_t` will be automatically configured during build and generally\r
+ * does not need to be defined.\r
+ * </span>\r
+ *\r
+ * <b>Example</b> <br>\r
+ * To change the type of #IotTimer_t to `long`:\r
+ * @code{c}\r
+ * typedef long _IotSystemTimer_t;\r
+ * #include "iot_clock.h"\r
+ * @endcode\r
+ */\r
+typedef _IotSystemTimer_t IotTimer_t;\r
+\r
+/*------------------------------ Metrics types ------------------------------*/\r
+\r
+/**\r
+ * @brief The length of the buffer used to store IP addresses for metrics.\r
+ *\r
+ * This is the length of the longest IPv6 address plus space for the port number\r
+ * and NULL terminator.\r
+ */\r
+#define IOT_METRICS_IP_ADDRESS_LENGTH 54\r
+\r
+/**\r
+ * @brief Represents a TCP connection to a remote IPv4 server.\r
+ *\r
+ * A list of these is provided by @ref platform_metrics_function_gettcpconnections.\r
+ */\r
+typedef struct IotMetricsTcpConnection\r
+{\r
+ IotLink_t link; /**< @brief List link member. */\r
+ void * pNetworkContext; /**< @brief Context that may be used by metrics or Defender. */\r
+ size_t addressLength; /**< @brief The length of the address stored in #IotMetricsTcpConnection_t.pRemoteAddress. */\r
+\r
+ /**\r
+ * @brief NULL-terminated IP address and port in text format.\r
+ *\r
+ * IPv4 addresses will be in the format `xxx.xxx.xxx.xxx:port`.\r
+ * IPv6 addresses will be in the format `[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:port`.\r
+ */\r
+ char pRemoteAddress[ IOT_METRICS_IP_ADDRESS_LENGTH ];\r
+} IotMetricsTcpConnection_t;\r
+\r
+#endif /* ifndef IOT_PLATFORM_TYPES_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_atomic.h\r
+ * @brief Chooses the appropriate atomic operations header.\r
+ *\r
+ * On FreeRTOS, this file chooses the atomic header provided with the FreeRTOS\r
+ * kernel.\r
+ */\r
+\r
+#ifndef IOT_ATOMIC_H_\r
+#define IOT_ATOMIC_H_\r
+\r
+#include "atomic.h"\r
+\r
+#endif /* ifndef IOT_ATOMIC_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_init.h\r
+ * @brief Provides function signatures for common intialization and cleanup of\r
+ * this SDK.\r
+ */\r
+\r
+#ifndef IOT_INIT_H_\r
+#define IOT_INIT_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+\r
+/**\r
+ * @brief One-time initialization function for this SDK.\r
+ *\r
+ * This function initializes common libraries, such as static memory and task\r
+ * pool. <b>It must be called once (and only once) before calling any other\r
+ * function in this SDK.</b> Calling this function more than once without first\r
+ * calling `IotSdk_Cleanup` may result in a crash.\r
+ *\r
+ * @return `true` if initialization succeeded; `false` otherwise. Logs may be\r
+ * printed in case of failure.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ */\r
+bool IotSdk_Init( void );\r
+\r
+/**\r
+ * @brief One-time deinitialization function for all common libraries.\r
+ *\r
+ * This function frees resources taken in `IotSdk_Init`. No other function\r
+ * in this SDK may be called after calling this function unless `IotSdk_Init`\r
+ * is called again.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ */\r
+void IotSdk_Cleanup( void );\r
+\r
+#endif /* IOT_INIT_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_linear_containers.h\r
+ * @brief Declares and implements doubly-linked lists and queues.\r
+ */\r
+\r
+#ifndef IOT_LINEAR_CONTAINERS_H_\r
+#define IOT_LINEAR_CONTAINERS_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * @defgroup linear_containers_datatypes_listqueue List and queue\r
+ * @brief Structures that represent a list or queue.\r
+ */\r
+\r
+/**\r
+ * @ingroup linear_containers_datatypes_listqueue\r
+ * @brief Link member placed in structs of a list or queue.\r
+ *\r
+ * All elements in a list or queue must contain one of these members. The macro\r
+ * #IotLink_Container can be used to calculate the starting address of the\r
+ * link's container.\r
+ */\r
+typedef struct IotLink\r
+{\r
+ struct IotLink * pPrevious; /**< @brief Pointer to the previous element. */\r
+ struct IotLink * pNext; /**< @brief Pointer to the next element. */\r
+} IotLink_t;\r
+\r
+/**\r
+ * @ingroup linear_containers_datatypes_listqueue\r
+ * @brief Represents a doubly-linked list.\r
+ */\r
+typedef IotLink_t IotListDouble_t;\r
+\r
+/**\r
+ * @ingroup linear_containers_datatypes_listqueue\r
+ * @brief Represents a queue.\r
+ */\r
+typedef IotLink_t IotDeQueue_t;\r
+\r
+/**\r
+ * @constantspage{linear_containers,linear containers library}\r
+ *\r
+ * @section linear_containers_constants_initializers Linear Containers Initializers\r
+ * @brief Provides default values for initializing the linear containers data types.\r
+ *\r
+ * @snippet this define_linear_containers_initializers\r
+ *\r
+ * All user-facing data types of the linear containers library should be initialized\r
+ * using one of the following.\r
+ *\r
+ * @warning Failure to initialize a linear containers data type with the appropriate\r
+ * initializer may result in a runtime error!\r
+ * @note The initializers may change at any time in future versions, but their\r
+ * names will remain the same.\r
+ */\r
+/* @[define_linear_containers_initializers] */\r
+#define IOT_LINK_INITIALIZER { 0 } /**< @brief Initializer for an #IotLink_t. */\r
+#define IOT_LIST_DOUBLE_INITIALIZER IOT_LINK_INITIALIZER /**< @brief Initializer for an #IotListDouble_t. */\r
+#define IOT_DEQUEUE_INITIALIZER IOT_LINK_INITIALIZER /**< @brief Initializer for an #IotDeQueue_t. */\r
+/* @[define_linear_containers_initializers] */\r
+\r
+/**\r
+ * @def IotContainers_Assert( expression )\r
+ * @brief Assertion macro for the linear containers library.\r
+ *\r
+ * Set @ref IOT_CONTAINERS_ENABLE_ASSERTS to `1` to enable assertions in the linear\r
+ * containers library.\r
+ *\r
+ * @param[in] expression Expression to be evaluated.\r
+ */\r
+#if IOT_CONTAINERS_ENABLE_ASSERTS == 1\r
+ #ifndef IotContainers_Assert\r
+ #include <assert.h>\r
+ #define IotContainers_Assert( expression ) assert( expression )\r
+ #endif\r
+#else\r
+ #define IotContainers_Assert( expression )\r
+#endif\r
+\r
+/**\r
+ * @brief Calculates the starting address of a containing struct.\r
+ *\r
+ * @param[in] type Type of the containing struct.\r
+ * @param[in] pLink Pointer to a link member.\r
+ * @param[in] linkName Name of the #IotLink_t in the containing struct.\r
+ */\r
+#define IotLink_Container( type, pLink, linkName ) \\r
+ ( ( type * ) ( void * ) ( ( ( uint8_t * ) ( pLink ) ) - offsetof( type, linkName ) ) )\r
+\r
+/**\r
+ * @brief Iterates through all elements of a linear container.\r
+ *\r
+ * Container elements must not be freed or removed while iterating.\r
+ *\r
+ * @param[in] pStart The first element to iterate from.\r
+ * @param[out] pLink Pointer to a container element.\r
+ */\r
+#define IotContainers_ForEach( pStart, pLink ) \\r
+ for( ( pLink ) = ( pStart )->pNext; \\r
+ ( pLink ) != ( pStart ); \\r
+ ( pLink ) = ( pLink )->pNext )\r
+\r
+/**\r
+ * @functionspage{linear_containers,linear containers library}\r
+ * - @functionname{linear_containers_function_link_islinked}\r
+ * - @functionname{linear_containers_function_list_double_create}\r
+ * - @functionname{linear_containers_function_list_double_count}\r
+ * - @functionname{linear_containers_function_list_double_isempty}\r
+ * - @functionname{linear_containers_function_list_double_peekhead}\r
+ * - @functionname{linear_containers_function_list_double_peektail}\r
+ * - @functionname{linear_containers_function_list_double_inserthead}\r
+ * - @functionname{linear_containers_function_list_double_inserttail}\r
+ * - @functionname{linear_containers_function_list_double_insertbefore}\r
+ * - @functionname{linear_containers_function_list_double_insertafter}\r
+ * - @functionname{linear_containers_function_list_double_insertsorted}\r
+ * - @functionname{linear_containers_function_list_double_remove}\r
+ * - @functionname{linear_containers_function_list_double_removehead}\r
+ * - @functionname{linear_containers_function_list_double_removetail}\r
+ * - @functionname{linear_containers_function_list_double_removeall}\r
+ * - @functionname{linear_containers_function_list_double_findfirstmatch}\r
+ * - @functionname{linear_containers_function_list_double_removefirstmatch}\r
+ * - @functionname{linear_containers_function_list_double_removeallmatches}\r
+ * - @functionname{linear_containers_function_queue_create}\r
+ * - @functionname{linear_containers_function_queue_count}\r
+ * - @functionname{linear_containers_function_queue_isempty}\r
+ * - @functionname{linear_containers_function_queue_peekhead}\r
+ * - @functionname{linear_containers_function_queue_peektail}\r
+ * - @functionname{linear_containers_function_queue_enqueuehead}\r
+ * - @functionname{linear_containers_function_queue_dequeuehead}\r
+ * - @functionname{linear_containers_function_queue_enqueuetail}\r
+ * - @functionname{linear_containers_function_queue_dequeuetail}\r
+ * - @functionname{linear_containers_function_queue_remove}\r
+ * - @functionname{linear_containers_function_queue_removeall}\r
+ * - @functionname{linear_containers_function_queue_removeallmatches}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotLink_IsLinked,linear_containers,link_islinked}\r
+ * @functionpage{IotListDouble_Create,linear_containers,list_double_create}\r
+ * @functionpage{IotListDouble_Count,linear_containers,list_double_count}\r
+ * @functionpage{IotListDouble_IsEmpty,linear_containers,list_double_isempty}\r
+ * @functionpage{IotListDouble_PeekHead,linear_containers,list_double_peekhead}\r
+ * @functionpage{IotListDouble_PeekTail,linear_containers,list_double_peektail}\r
+ * @functionpage{IotListDouble_InsertHead,linear_containers,list_double_inserthead}\r
+ * @functionpage{IotListDouble_InsertTail,linear_containers,list_double_inserttail}\r
+ * @functionpage{IotListDouble_InsertBefore,linear_containers,list_double_insertbefore}\r
+ * @functionpage{IotListDouble_InsertAfter,linear_containers,list_double_insertafter}\r
+ * @functionpage{IotListDouble_InsertSorted,linear_containers,list_double_insertsorted}\r
+ * @functionpage{IotListDouble_Remove,linear_containers,list_double_remove}\r
+ * @functionpage{IotListDouble_RemoveHead,linear_containers,list_double_removehead}\r
+ * @functionpage{IotListDouble_RemoveTail,linear_containers,list_double_removetail}\r
+ * @functionpage{IotListDouble_RemoveAll,linear_containers,list_double_removeall}\r
+ * @functionpage{IotListDouble_FindFirstMatch,linear_containers,list_double_findfirstmatch}\r
+ * @functionpage{IotListDouble_RemoveFirstMatch,linear_containers,list_double_removefirstmatch}\r
+ * @functionpage{IotListDouble_RemoveAllMatches,linear_containers,list_double_removeallmatches}\r
+ * @functionpage{IotDeQueue_Create,linear_containers,queue_create}\r
+ * @functionpage{IotDeQueue_Count,linear_containers,queue_count}\r
+ * @functionpage{IotDeQueue_IsEmpty,linear_containers,queue_isempty}\r
+ * @functionpage{IotDeQueue_PeekHead,linear_containers,queue_peekhead}\r
+ * @functionpage{IotDeQueue_PeekTail,linear_containers,queue_peektail}\r
+ * @functionpage{IotDeQueue_EnqueueHead,linear_containers,queue_enqueuehead}\r
+ * @functionpage{IotDeQueue_DequeueHead,linear_containers,queue_dequeuehead}\r
+ * @functionpage{IotDeQueue_EnqueueTail,linear_containers,queue_enqueuetail}\r
+ * @functionpage{IotDeQueue_DequeueTail,linear_containers,queue_dequeuetail}\r
+ * @functionpage{IotDeQueue_Remove,linear_containers,queue_remove}\r
+ * @functionpage{IotDeQueue_RemoveAll,linear_containers,queue_removeall}\r
+ * @functionpage{IotDeQueue_RemoveAllMatches,linear_containers,queue_removeallmatches}\r
+ */\r
+\r
+/**\r
+ * @brief Check if an #IotLink_t is linked in a list or queue.\r
+ *\r
+ * @param[in] pLink The link to check.\r
+ *\r
+ * @return `true` if `pCurrent` is linked in a list or queue; `false` otherwise.\r
+ */\r
+/* @[declare_linear_containers_link_islinked] */\r
+static inline bool IotLink_IsLinked( const IotLink_t * const pLink )\r
+/* @[declare_linear_containers_link_islinked] */\r
+{\r
+ bool isLinked = false;\r
+\r
+ if( pLink != NULL )\r
+ {\r
+ isLinked = ( pLink->pNext != NULL ) && ( pLink->pPrevious != NULL );\r
+ }\r
+\r
+ return isLinked;\r
+}\r
+\r
+/**\r
+ * @brief Create a new doubly-linked list.\r
+ *\r
+ * This function initializes a new doubly-linked list. It must be called on an\r
+ * uninitialized #IotListDouble_t before calling any other doubly-linked list\r
+ * function. This function must not be called on an already-initialized\r
+ * #IotListDouble_t.\r
+ *\r
+ * This function will not fail. The function @ref linear_containers_function_list_double_removeall\r
+ * may be called to destroy a list.\r
+ *\r
+ * @param[in] pList Pointer to the memory that will hold the new doubly-linked list.\r
+ */\r
+/* @[declare_linear_containers_list_double_create] */\r
+static inline void IotListDouble_Create( IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_create] */\r
+{\r
+ /* This function must not be called with a NULL parameter. */\r
+ IotContainers_Assert( pList != NULL );\r
+\r
+ /* An empty list is a link pointing to itself. */\r
+ pList->pPrevious = pList;\r
+ pList->pNext = pList;\r
+}\r
+\r
+/**\r
+ * @brief Return the number of elements contained in an #IotListDouble_t.\r
+ *\r
+ * @param[in] pList The doubly-linked list with the elements to count.\r
+ *\r
+ * @return The number of elements in the doubly-linked list.\r
+ */\r
+/* @[declare_linear_containers_list_double_count] */\r
+static inline size_t IotListDouble_Count( const IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_count] */\r
+{\r
+ size_t count = 0;\r
+\r
+ if( pList != NULL )\r
+ {\r
+ /* Get the list head. */\r
+ const IotLink_t * pCurrent = pList->pNext;\r
+\r
+ /* Iterate through the list to count the elements. */\r
+ while( pCurrent != pList )\r
+ {\r
+ count++;\r
+ pCurrent = pCurrent->pNext;\r
+ }\r
+ }\r
+\r
+ return count;\r
+}\r
+\r
+/**\r
+ * @brief Check if a doubly-linked list is empty.\r
+ *\r
+ * @param[in] pList The doubly-linked list to check.\r
+ *\r
+ * @return `true` if the list is empty; `false` otherwise.\r
+ */\r
+/* @[declare_linear_containers_list_double_isempty] */\r
+static inline bool IotListDouble_IsEmpty( const IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_isempty] */\r
+{\r
+ /* An empty list is NULL link, or a link pointing to itself. */\r
+ return( ( pList == NULL ) || ( pList->pNext == pList ) );\r
+}\r
+\r
+/**\r
+ * @brief Return an #IotLink_t representing the first element in a doubly-linked list\r
+ * without removing it.\r
+ *\r
+ * @param[in] pList The list to peek.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the element at the head of the\r
+ * list; `NULL` if the list is empty. The macro #IotLink_Container may be used to\r
+ * determine the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_peekhead] */\r
+static inline IotLink_t * IotListDouble_PeekHead( const IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_peekhead] */\r
+{\r
+ IotLink_t * pHead = NULL;\r
+\r
+ if( pList != NULL )\r
+ {\r
+ if( IotListDouble_IsEmpty( pList ) == false )\r
+ {\r
+ pHead = pList->pNext;\r
+ }\r
+ }\r
+\r
+ return pHead;\r
+}\r
+\r
+/**\r
+ * @brief Return an #IotLink_t representing the last element in a doubly-linked\r
+ * list without removing it.\r
+ *\r
+ * @param[in] pList The list to peek.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the element at the tail of the\r
+ * list; `NULL` if the list is empty. The macro #IotLink_Container may be used to\r
+ * determine the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_peektail] */\r
+static inline IotLink_t * IotListDouble_PeekTail( const IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_peektail] */\r
+{\r
+ IotLink_t * pTail = NULL;\r
+\r
+ if( pList != NULL )\r
+ {\r
+ if( IotListDouble_IsEmpty( pList ) == false )\r
+ {\r
+ pTail = pList->pPrevious;\r
+ }\r
+ }\r
+\r
+ return pTail;\r
+}\r
+\r
+/**\r
+ * @brief Insert an element at the head of a doubly-linked list.\r
+ *\r
+ * @param[in] pList The doubly-linked list that will hold the new element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_list_double_inserthead] */\r
+static inline void IotListDouble_InsertHead( IotListDouble_t * const pList,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_list_double_inserthead] */\r
+{\r
+ /* This function must not be called with NULL parameters. */\r
+ IotContainers_Assert( pList != NULL );\r
+ IotContainers_Assert( pLink != NULL );\r
+\r
+ /* Save current list head. */\r
+ IotLink_t * pHead = pList->pNext;\r
+\r
+ /* Place new element before list head. */\r
+ pLink->pNext = pHead;\r
+ pLink->pPrevious = pList;\r
+\r
+ /* Assign new list head. */\r
+ pHead->pPrevious = pLink;\r
+ pList->pNext = pLink;\r
+}\r
+\r
+/**\r
+ * @brief Insert an element at the tail of a doubly-linked list.\r
+ *\r
+ * @param[in] pList The double-linked list that will hold the new element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_list_double_inserttail] */\r
+static inline void IotListDouble_InsertTail( IotListDouble_t * const pList,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_list_double_inserttail] */\r
+{\r
+ /* This function must not be called with NULL parameters. */\r
+ IotContainers_Assert( pList != NULL );\r
+ IotContainers_Assert( pLink != NULL );\r
+\r
+ /* Save current list tail. */\r
+ IotLink_t * pTail = pList->pPrevious;\r
+\r
+ pLink->pNext = pList;\r
+ pLink->pPrevious = pTail;\r
+\r
+ pList->pPrevious = pLink;\r
+ pTail->pNext = pLink;\r
+}\r
+\r
+/**\r
+ * @brief Insert an element before another element in a doubly-linked list.\r
+ *\r
+ * @param[in] pElement The new element will be placed before this element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_list_double_insertbefore] */\r
+static inline void IotListDouble_InsertBefore( IotLink_t * const pElement,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_list_double_insertbefore] */\r
+{\r
+ IotListDouble_InsertTail( pElement, pLink );\r
+}\r
+\r
+/**\r
+ * @brief Insert an element after another element in a doubly-linked list.\r
+ *\r
+ * @param[in] pElement The new element will be placed after this element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_list_double_insertafter] */\r
+static inline void IotListDouble_InsertAfter( IotLink_t * const pElement,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_list_double_insertafter] */\r
+{\r
+ IotListDouble_InsertHead( pElement, pLink );\r
+}\r
+\r
+/**\r
+ * @brief Insert an element in a sorted doubly-linked list.\r
+ *\r
+ * Places an element into a list by sorting it into order. The function\r
+ * `compare` is used to determine where to place the new element.\r
+ *\r
+ * @param[in] pList The list that will hold the new element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ * @param[in] compare Determines the order of the list. Returns a negative\r
+ * value if its first argument is less than its second argument; returns\r
+ * zero if its first argument is equal to its second argument; returns a\r
+ * positive value if its first argument is greater than its second argument.\r
+ * The parameters to this function are #IotLink_t, so the macro #IotLink_Container\r
+ * may be used to determine the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_insertsorted] */\r
+static inline void IotListDouble_InsertSorted( IotListDouble_t * const pList,\r
+ IotLink_t * const pLink,\r
+ int32_t ( *compare )( const IotLink_t * const, const IotLink_t * const ) )\r
+/* @[declare_linear_containers_list_double_insertsorted] */\r
+{\r
+ /* This function must not be called with NULL parameters. */\r
+ IotContainers_Assert( pList != NULL );\r
+ IotContainers_Assert( pLink != NULL );\r
+ IotContainers_Assert( compare != NULL );\r
+\r
+ /* Insert at head for empty list. */\r
+ if( IotListDouble_IsEmpty( pList ) == true )\r
+ {\r
+ IotListDouble_InsertHead( pList, pLink );\r
+ }\r
+ else\r
+ {\r
+ bool inserted = false;\r
+ IotLink_t * pCurrent = pList->pNext;\r
+\r
+ /* Iterate through the list to find the correct position. */\r
+ while( pCurrent != pList )\r
+ {\r
+ /* Comparing for '<' preserves the order of insertion. */\r
+ if( compare( pLink, pCurrent ) < 0 )\r
+ {\r
+ IotListDouble_InsertBefore( pCurrent, pLink );\r
+ inserted = true;\r
+\r
+ break;\r
+ }\r
+\r
+ pCurrent = pCurrent->pNext;\r
+ }\r
+\r
+ /* New element is greater than all elements in list. Insert at tail. */\r
+ if( inserted == false )\r
+ {\r
+ IotListDouble_InsertTail( pList, pLink );\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Remove a single element from a doubly-linked list.\r
+ *\r
+ * @param[in] pLink The element to remove.\r
+ */\r
+/* @[declare_linear_containers_list_double_remove] */\r
+static inline void IotListDouble_Remove( IotLink_t * const pLink )\r
+/* @[declare_linear_containers_list_double_remove] */\r
+{\r
+ /* This function must not be called with a NULL parameter. */\r
+ IotContainers_Assert( pLink != NULL );\r
+\r
+ /* This function must be called on a linked element. */\r
+ IotContainers_Assert( IotLink_IsLinked( pLink ) == true );\r
+\r
+ pLink->pPrevious->pNext = pLink->pNext;\r
+ pLink->pNext->pPrevious = pLink->pPrevious;\r
+ pLink->pPrevious = NULL;\r
+ pLink->pNext = NULL;\r
+}\r
+\r
+/**\r
+ * @brief Remove the element at the head of a doubly-linked list.\r
+ *\r
+ * @param[in] pList The doubly-linked list that holds the element to remove.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the removed list head; `NULL`\r
+ * if the list is empty. The macro #IotLink_Container may be used to determine\r
+ * the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_removehead] */\r
+static inline IotLink_t * IotListDouble_RemoveHead( IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_removehead] */\r
+{\r
+ IotLink_t * pHead = NULL;\r
+\r
+ if( IotListDouble_IsEmpty( pList ) == false )\r
+ {\r
+ pHead = pList->pNext;\r
+ IotListDouble_Remove( pHead );\r
+ }\r
+\r
+ return pHead;\r
+}\r
+\r
+/**\r
+ * @brief Remove the element at the tail of a doubly-linked list.\r
+ *\r
+ * @param[in] pList The doubly-linked list that holds the element to remove.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the removed list tail; `NULL`\r
+ * if the list is empty. The macro #IotLink_Container may be used to determine\r
+ * the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_removetail] */\r
+static inline IotLink_t * IotListDouble_RemoveTail( IotListDouble_t * const pList )\r
+/* @[declare_linear_containers_list_double_removetail] */\r
+{\r
+ IotLink_t * pTail = NULL;\r
+\r
+ if( IotListDouble_IsEmpty( pList ) == false )\r
+ {\r
+ pTail = pList->pPrevious;\r
+ IotListDouble_Remove( pTail );\r
+ }\r
+\r
+ return pTail;\r
+}\r
+\r
+/**\r
+ * @brief Remove all elements in a doubly-linked list.\r
+ *\r
+ * @param[in] pList The list to empty.\r
+ * @param[in] freeElement A function to free memory used by each removed list\r
+ * element. Optional; pass `NULL` to ignore.\r
+ * @param[in] linkOffset Offset in bytes of a link member in its container, used\r
+ * to calculate the pointer to pass to `freeElement`. This value should be calculated\r
+ * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL`\r
+ * or its value is `0`.\r
+ */\r
+/* @[declare_linear_containers_list_double_removeall] */\r
+static inline void IotListDouble_RemoveAll( IotListDouble_t * const pList,\r
+ void ( *freeElement )( void * ),\r
+ size_t linkOffset )\r
+/* @[declare_linear_containers_list_double_removeall] */\r
+{\r
+ /* This function must not be called with a NULL pList parameter. */\r
+ IotContainers_Assert( pList != NULL );\r
+\r
+ /* Get the list head. */\r
+ IotLink_t * pCurrent = pList->pNext;\r
+\r
+ /* Iterate through the list and remove all elements. */\r
+ while( pCurrent != pList )\r
+ {\r
+ /* Save a pointer to the next list element. */\r
+ IotLink_t * pNext = pCurrent->pNext;\r
+\r
+ /* Remove and free the current list element. */\r
+ IotListDouble_Remove( pCurrent );\r
+\r
+ if( freeElement != NULL )\r
+ {\r
+ freeElement( ( ( uint8_t * ) pCurrent ) - linkOffset );\r
+ }\r
+\r
+ /* Move the iterating pointer to the next list element. */\r
+ pCurrent = pNext;\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Search a doubly-linked list for the first matching element.\r
+ *\r
+ * If a match is found, the matching element is <b>not</b> removed from the list.\r
+ * See @ref linear_containers_function_list_double_removefirstmatch for the function\r
+ * that searches and removes.\r
+ *\r
+ * @param[in] pList The doubly-linked list to search.\r
+ * @param[in] pStartPoint An element in `pList`. Only elements between this one and\r
+ * the list tail are checked. Pass `NULL` to search from the beginning of the list.\r
+ * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to\r
+ * search using the address `pMatch`, i.e. `element == pMatch`.\r
+ * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared\r
+ * to this address to find a match. Otherwise, it is passed as the second argument\r
+ * to `isMatch`.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the first matched element; `NULL`\r
+ * if no match is found. The macro #IotLink_Container may be used to determine the\r
+ * address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_findfirstmatch] */\r
+static inline IotLink_t * IotListDouble_FindFirstMatch( const IotListDouble_t * const pList,\r
+ const IotLink_t * const pStartPoint,\r
+ bool ( *isMatch )( const IotLink_t * const, void * ),\r
+ void * pMatch )\r
+/* @[declare_linear_containers_list_double_findfirstmatch] */\r
+{\r
+ /* The const must be cast away to match this function's return value. Nevertheless,\r
+ * this function will respect the const-ness of pStartPoint. */\r
+ IotLink_t * pCurrent = ( IotLink_t * ) pStartPoint;\r
+\r
+ /* This function must not be called with a NULL pList parameter. */\r
+ IotContainers_Assert( pList != NULL );\r
+\r
+ /* Search starting from list head if no start point is given. */\r
+ if( pStartPoint == NULL )\r
+ {\r
+ pCurrent = pList->pNext;\r
+ }\r
+\r
+ /* Iterate through the list to search for matches. */\r
+ while( pCurrent != pList )\r
+ {\r
+ /* Call isMatch if provided. Otherwise, compare pointers. */\r
+ if( isMatch != NULL )\r
+ {\r
+ if( isMatch( pCurrent, pMatch ) == true )\r
+ {\r
+ return pCurrent;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if( pCurrent == pMatch )\r
+ {\r
+ return pCurrent;\r
+ }\r
+ }\r
+\r
+ pCurrent = pCurrent->pNext;\r
+ }\r
+\r
+ /* No match found, return NULL. */\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ * @brief Search a doubly-linked list for the first matching element and remove\r
+ * it.\r
+ *\r
+ * An #IotLink_t may be passed as `pList` to start searching after the head of a\r
+ * doubly-linked list.\r
+ *\r
+ * @param[in] pList The doubly-linked list to search.\r
+ * @param[in] pStartPoint An element in `pList`. Only elements between this one and\r
+ * the list tail are checked. Pass `NULL` to search from the beginning of the list.\r
+ * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to\r
+ * search using the address `pMatch`, i.e. `element == pMatch`.\r
+ * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared\r
+ * to this address to find a match. Otherwise, it is passed as the second argument\r
+ * to `isMatch`.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the matched and removed element;\r
+ * `NULL` if no match is found. The macro #IotLink_Container may be used to determine\r
+ * the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_list_double_removefirstmatch] */\r
+static inline IotLink_t * IotListDouble_RemoveFirstMatch( IotListDouble_t * const pList,\r
+ const IotLink_t * const pStartPoint,\r
+ bool ( *isMatch )( const IotLink_t *, void * ),\r
+ void * pMatch )\r
+/* @[declare_linear_containers_list_double_removefirstmatch] */\r
+{\r
+ IotLink_t * pMatchedElement = IotListDouble_FindFirstMatch( pList,\r
+ pStartPoint,\r
+ isMatch,\r
+ pMatch );\r
+\r
+ if( pMatchedElement != NULL )\r
+ {\r
+ IotListDouble_Remove( pMatchedElement );\r
+ }\r
+\r
+ return pMatchedElement;\r
+}\r
+\r
+/**\r
+ * @brief Remove all matching elements from a doubly-linked list.\r
+ *\r
+ * @param[in] pList The doubly-linked list to search.\r
+ * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to\r
+ * search using the address `pMatch`, i.e. `element == pMatch`.\r
+ * @param[in] pMatch If `isMatch` is `NULL`, each element in the list is compared\r
+ * to this address to find a match. Otherwise, it is passed as the second argument\r
+ * to `isMatch`.\r
+ * @param[in] freeElement A function to free memory used by each removed list\r
+ * element. Optional; pass `NULL` to ignore.\r
+ * @param[in] linkOffset Offset in bytes of a link member in its container, used\r
+ * to calculate the pointer to pass to `freeElement`. This value should be calculated\r
+ * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL`\r
+ * or its value is `0`.\r
+ */\r
+/* @[declare_linear_containers_list_double_removeallmatches] */\r
+static inline void IotListDouble_RemoveAllMatches( IotListDouble_t * const pList,\r
+ bool ( *isMatch )( const IotLink_t *, void * ),\r
+ void * pMatch,\r
+ void ( *freeElement )( void * ),\r
+ size_t linkOffset )\r
+/* @[declare_linear_containers_list_double_removeallmatches] */\r
+{\r
+ IotLink_t * pMatchedElement = NULL, * pNextElement = NULL;\r
+\r
+ /* Search the list for all matching elements. */\r
+ do\r
+ {\r
+ pMatchedElement = IotListDouble_FindFirstMatch( pList,\r
+ pMatchedElement,\r
+ isMatch,\r
+ pMatch );\r
+\r
+ if( pMatchedElement != NULL )\r
+ {\r
+ /* Save pointer to next element. */\r
+ pNextElement = pMatchedElement->pNext;\r
+\r
+ /* Match found; remove and free. */\r
+ IotListDouble_Remove( pMatchedElement );\r
+\r
+ if( freeElement != NULL )\r
+ {\r
+ freeElement( ( ( uint8_t * ) pMatchedElement ) - linkOffset );\r
+ }\r
+\r
+ /* Continue search from next element. */\r
+ pMatchedElement = pNextElement;\r
+ }\r
+ } while( pMatchedElement != NULL );\r
+}\r
+\r
+/**\r
+ * @brief Create a new queue.\r
+ *\r
+ * This function initializes a new double-ended queue. It must be called on an uninitialized\r
+ * #IotDeQueue_t before calling any other queue function. This function must not be\r
+ * called on an already-initialized #IotDeQueue_t.\r
+ *\r
+ * This function will not fail.\r
+ *\r
+ * @param[in] pQueue Pointer to the memory that will hold the new queue.\r
+ */\r
+/* @[declare_linear_containers_queue_create] */\r
+static inline void IotDeQueue_Create( IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_create] */\r
+{\r
+ IotListDouble_Create( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Return the number of elements contained in an #IotDeQueue_t.\r
+ *\r
+ * @param[in] pQueue The queue with the elements to count.\r
+ *\r
+ * @return The number of items elements in the queue.\r
+ */\r
+/* @[declare_linear_containers_queue_count] */\r
+static inline size_t IotDeQueue_Count( const IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_count] */\r
+{\r
+ return IotListDouble_Count( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Check if a queue is empty.\r
+ *\r
+ * @param[in] pQueue The queue to check.\r
+ *\r
+ * @return `true` if the queue is empty; `false` otherwise.\r
+ *\r
+ */\r
+/* @[declare_linear_containers_queue_isempty] */\r
+static inline bool IotDeQueue_IsEmpty( const IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_isempty] */\r
+{\r
+ return IotListDouble_IsEmpty( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Return an #IotLink_t representing the element at the front of the queue\r
+ * without removing it.\r
+ *\r
+ * @param[in] pQueue The queue to peek.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the element at the head of the\r
+ * queue; `NULL` if the queue is empty. The macro #IotLink_Container may be used\r
+ * to determine the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_queue_peekhead] */\r
+static inline IotLink_t * IotDeQueue_PeekHead( const IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_peekhead] */\r
+{\r
+ return IotListDouble_PeekHead( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Return an #IotLink_t representing the element at the back of the queue\r
+ * without removing it.\r
+ *\r
+ * @param[in] pQueue The queue to peek.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the element at the head of the\r
+ * queue; `NULL` if the queue is empty. The macro #IotLink_Container may be used\r
+ * to determine the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_queue_peektail] */\r
+static inline IotLink_t * IotDeQueue_PeekTail( const IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_peektail] */\r
+{\r
+ return IotListDouble_PeekTail( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Add an element at the head of the queue.\r
+ *\r
+ * @param[in] pQueue The queue that will hold the new element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_queue_enqueuehead] */\r
+static inline void IotDeQueue_EnqueueHead( IotDeQueue_t * const pQueue,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_queue_enqueuehead] */\r
+{\r
+ IotListDouble_InsertHead( pQueue, pLink );\r
+}\r
+\r
+/**\r
+ * @brief Remove an element at the head of the queue.\r
+ *\r
+ * @param[in] pQueue The queue that holds the element to remove.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the removed queue element; `NULL`\r
+ * if the queue is empty. The macro #IotLink_Container may be used to determine\r
+ * the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_queue_dequeuehead] */\r
+static inline IotLink_t * IotDeQueue_DequeueHead( IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_dequeuehead] */\r
+{\r
+ return IotListDouble_RemoveHead( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Add an element at the tail of the queue.\r
+ *\r
+ * @param[in] pQueue The queue that will hold the new element.\r
+ * @param[in] pLink Pointer to the new element's link member.\r
+ */\r
+/* @[declare_linear_containers_queue_enqueuetail] */\r
+static inline void IotDeQueue_EnqueueTail( IotDeQueue_t * const pQueue,\r
+ IotLink_t * const pLink )\r
+/* @[declare_linear_containers_queue_enqueuetail] */\r
+{\r
+ IotListDouble_InsertTail( pQueue, pLink );\r
+}\r
+\r
+/**\r
+ * @brief Remove an element at the tail of the queue.\r
+ *\r
+ * @param[in] pQueue The queue that holds the element to remove.\r
+ *\r
+ * @return Pointer to an #IotLink_t representing the removed queue element; `NULL`\r
+ * if the queue is empty. The macro #IotLink_Container may be used to determine\r
+ * the address of the link's container.\r
+ */\r
+/* @[declare_linear_containers_queue_dequeuetail] */\r
+static inline IotLink_t * IotDeQueue_DequeueTail( IotDeQueue_t * const pQueue )\r
+/* @[declare_linear_containers_queue_dequeuetail] */\r
+{\r
+ return IotListDouble_RemoveTail( pQueue );\r
+}\r
+\r
+/**\r
+ * @brief Remove a single element from a queue.\r
+ *\r
+ * @param[in] pLink The element to remove.\r
+ */\r
+/* @[declare_linear_containers_queue_remove] */\r
+static inline void IotDeQueue_Remove( IotLink_t * const pLink )\r
+/* @[declare_linear_containers_queue_remove] */\r
+{\r
+ IotListDouble_Remove( pLink );\r
+}\r
+\r
+/**\r
+ * @brief Remove all elements in a queue.\r
+ *\r
+ * @param[in] pQueue The queue to empty.\r
+ * @param[in] freeElement A function to free memory used by each removed queue\r
+ * element. Optional; pass `NULL` to ignore.\r
+ * @param[in] linkOffset Offset in bytes of a link member in its container, used\r
+ * to calculate the pointer to pass to `freeElement`. This value should be calculated\r
+ * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL`\r
+ * or its value is `0`.\r
+ */\r
+/* @[declare_linear_containers_queue_removeall] */\r
+static inline void IotDeQueue_RemoveAll( IotDeQueue_t * const pQueue,\r
+ void ( * freeElement )( void * ),\r
+ size_t linkOffset )\r
+/* @[declare_linear_containers_queue_removeall] */\r
+{\r
+ IotListDouble_RemoveAll( pQueue, freeElement, linkOffset );\r
+}\r
+\r
+/**\r
+ * @brief Remove all matching elements from a queue.\r
+ *\r
+ * @param[in] pQueue The queue to search.\r
+ * @param[in] isMatch Function to determine if an element matches. Pass `NULL` to\r
+ * search using the address `pMatch`, i.e. `element == pMatch`.\r
+ * @param[in] pMatch If `isMatch` is `NULL`, each element in the queue is compared\r
+ * to this address to find a match. Otherwise, it is passed as the second argument\r
+ * to `isMatch`.\r
+ * @param[in] freeElement A function to free memory used by each removed queue\r
+ * element. Optional; pass `NULL` to ignore.\r
+ * @param[in] linkOffset Offset in bytes of a link member in its container, used\r
+ * to calculate the pointer to pass to `freeElement`. This value should be calculated\r
+ * with the C `offsetof` macro. This parameter is ignored if `freeElement` is `NULL`\r
+ * or its value is `0`.\r
+ */\r
+/* @[declare_linear_containers_queue_removeallmatches] */\r
+static inline void IotDeQueue_RemoveAllMatches( IotDeQueue_t * const pQueue,\r
+ bool ( * isMatch )( const IotLink_t *, void * ),\r
+ void * pMatch,\r
+ void ( * freeElement )( void * ),\r
+ size_t linkOffset )\r
+/* @[declare_linear_containers_queue_removeallmatches] */\r
+{\r
+ IotListDouble_RemoveAllMatches( pQueue, isMatch, pMatch, freeElement, linkOffset );\r
+}\r
+\r
+#endif /* IOT_LINEAR_CONTAINERS_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_logging_setup.h\r
+ * @brief Defines the logging macro #IotLog.\r
+ */\r
+\r
+#ifndef IOT_LOGGING_SETUP_H_\r
+#define IOT_LOGGING_SETUP_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Logging include. Because it's included here, iot_logging.h never needs\r
+ * to be included in source. */\r
+#include "private/iot_logging.h"\r
+\r
+/**\r
+ * @functionpage{IotLog,logging,log}\r
+ * @functionpage{IotLog_PrintBuffer,logging,printbuffer}\r
+ */\r
+\r
+/**\r
+ * @def IotLog( messageLevel, pLogConfig, ... )\r
+ * @brief Logging function for a specific library. In most cases, this is the\r
+ * logging function to call.\r
+ *\r
+ * This function prints a single log message. It is available when @ref\r
+ * LIBRARY_LOG_LEVEL is not #IOT_LOG_NONE. Log messages automatically\r
+ * include the [log level](@ref logging_constants_levels), [library name]\r
+ * (@ref LIBRARY_LOG_NAME), and time. An optional @ref IotLogConfig_t may\r
+ * be passed to this function to hide information for a single log message.\r
+ *\r
+ * The logging library must be set up before this function may be called. See\r
+ * @ref logging_setup_use for more information.\r
+ *\r
+ * This logging function also has the following abbreviated forms that can be used\r
+ * when an #IotLogConfig_t isn't needed.\r
+ *\r
+ * Name | Equivalent to\r
+ * ---- | -------------\r
+ * #IotLogError | @code{c} IotLog( IOT_LOG_ERROR, NULL, ... ) @endcode\r
+ * #IotLogWarn | @code{c} IotLog( IOT_LOG_WARN, NULL, ... ) @endcode\r
+ * #IotLogInfo | @code{c} IotLog( IOT_LOG_INFO, NULL, ... ) @endcode\r
+ * #IotLogDebug | @code{c} IotLog( IOT_LOG_DEBUG, NULL, ... ) @endcode\r
+ *\r
+ * @param[in] messageLevel Log level of this message. Must be one of the\r
+ * @ref logging_constants_levels.\r
+ * @param[in] pLogConfig Pointer to an #IotLogConfig_t. Optional; pass `NULL`\r
+ * to ignore.\r
+ * @param[in] ... Message and format specification.\r
+ *\r
+ * @return No return value. On errors, it prints nothing.\r
+ *\r
+ * @note This function may be implemented as a macro.\r
+ * @see @ref logging_function_generic for the generic (not library-specific)\r
+ * logging function.\r
+ */\r
+\r
+/**\r
+ * @def IotLog_PrintBuffer( pHeader, pBuffer, bufferSize )\r
+ * @brief Log the contents of buffer as bytes. Only available when @ref\r
+ * LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG.\r
+ *\r
+ * This function prints the bytes located at a given memory address. It is\r
+ * intended for debugging only, and is therefore only available when @ref\r
+ * LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG.\r
+ *\r
+ * Log messages printed by this function <b>always</b> include the [log level]\r
+ * (@ref logging_constants_levels), [library name](@ref LIBRARY_LOG_NAME),\r
+ * and time. In addition, this function may print an optional header `pHeader`\r
+ * before it prints the contents of the buffer. This function does not have an\r
+ * #IotLogConfig_t parameter.\r
+ *\r
+ * The logging library must be set up before this function may be called. See\r
+ * @ref logging_setup_use for more information.\r
+ *\r
+ * @param[in] pHeader A message to log before the buffer. Optional; pass `NULL`\r
+ * to ignore.\r
+ * @param[in] pBuffer Pointer to start of buffer.\r
+ * @param[in] bufferSize Size of `pBuffer`.\r
+ *\r
+ * @return No return value. On errors, it prints nothing.\r
+ *\r
+ * @note This function may be implemented as a macro.\r
+ * @note To conserve memory, @ref logging_function_genericprintbuffer (the underlying\r
+ * implementation) only allocates enough memory for a single line of output. Therefore,\r
+ * in multithreaded systems, its output may appear "fragmented" if other threads are\r
+ * logging simultaneously.\r
+ * @see @ref logging_function_genericprintbuffer for the generic (not library-specific)\r
+ * buffer logging function.\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * const uint8_t pBuffer[] = { 0x00, 0x01, 0x02, 0x03 };\r
+ *\r
+ * IotLog_PrintBuffer( "This buffer contains:",\r
+ * pBuffer,\r
+ * 4 );\r
+ * @endcode\r
+ * The code above prints something like the following:\r
+ * @code{c}\r
+ * [DEBUG][LIB_NAME][2018-01-01 12:00:00] This buffer contains:\r
+ * 00 01 02 03\r
+ * @endcode\r
+ */\r
+\r
+/**\r
+ * @def IotLogError( ... )\r
+ * @brief Abbreviated logging macro for level #IOT_LOG_ERROR.\r
+ *\r
+ * Equivalent to:\r
+ * @code{c}\r
+ * IotLog( IOT_LOG_ERROR, NULL, ... )\r
+ * @endcode\r
+ */\r
+\r
+/**\r
+ * @def IotLogWarn( ... )\r
+ * @brief Abbreviated logging macro for level #IOT_LOG_WARN.\r
+ *\r
+ * Equivalent to:\r
+ * @code{c}\r
+ * IotLog( IOT_LOG_WARN, NULL, ... )\r
+ * @endcode\r
+ */\r
+\r
+/**\r
+ * @def IotLogInfo( ... )\r
+ * @brief Abbreviated logging macro for level #IOT_LOG_INFO.\r
+ *\r
+ * Equivalent to:\r
+ * @code{c}\r
+ * IotLog( IOT_LOG_INFO, NULL, ... )\r
+ * @endcode\r
+ */\r
+\r
+/**\r
+ * @def IotLogDebug( ... )\r
+ * @brief Abbreviated logging macro for level #IOT_LOG_DEBUG.\r
+ *\r
+ * Equivalent to:\r
+ * @code{c}\r
+ * IotLog( IOT_LOG_DEBUG, NULL, ... )\r
+ * @endcode\r
+ */\r
+\r
+/* Check that LIBRARY_LOG_LEVEL is defined and has a valid value. */\r
+#if !defined( LIBRARY_LOG_LEVEL ) || \\r
+ ( LIBRARY_LOG_LEVEL != IOT_LOG_NONE && \\r
+ LIBRARY_LOG_LEVEL != IOT_LOG_ERROR && \\r
+ LIBRARY_LOG_LEVEL != IOT_LOG_WARN && \\r
+ LIBRARY_LOG_LEVEL != IOT_LOG_INFO && \\r
+ LIBRARY_LOG_LEVEL != IOT_LOG_DEBUG )\r
+ #error "Please define LIBRARY_LOG_LEVEL as either IOT_LOG_NONE, IOT_LOG_ERROR, IOT_LOG_WARN, IOT_LOG_INFO, or IOT_LOG_DEBUG."\r
+/* Check that LIBRARY_LOG_NAME is defined and has a valid value. */\r
+#elif !defined( LIBRARY_LOG_NAME )\r
+ #error "Please define LIBRARY_LOG_NAME."\r
+#else\r
+ /* Define IotLog if the log level is greater than "none". */\r
+ #if LIBRARY_LOG_LEVEL > IOT_LOG_NONE\r
+ #define IotLog( messageLevel, pLogConfig, ... ) \\r
+ IotLog_Generic( LIBRARY_LOG_LEVEL, \\r
+ LIBRARY_LOG_NAME, \\r
+ messageLevel, \\r
+ pLogConfig, \\r
+ __VA_ARGS__ )\r
+\r
+ /* Define the abbreviated logging macros. */\r
+ #define IotLogError( ... ) IotLog( IOT_LOG_ERROR, NULL, __VA_ARGS__ )\r
+ #define IotLogWarn( ... ) IotLog( IOT_LOG_WARN, NULL, __VA_ARGS__ )\r
+ #define IotLogInfo( ... ) IotLog( IOT_LOG_INFO, NULL, __VA_ARGS__ )\r
+ #define IotLogDebug( ... ) IotLog( IOT_LOG_DEBUG, NULL, __VA_ARGS__ )\r
+\r
+ /* If log level is DEBUG, enable the function to print buffers. */\r
+ #if LIBRARY_LOG_LEVEL >= IOT_LOG_DEBUG\r
+ #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize ) \\r
+ IotLog_GenericPrintBuffer( LIBRARY_LOG_NAME, \\r
+ pHeader, \\r
+ pBuffer, \\r
+ bufferSize )\r
+ #else\r
+ #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize )\r
+ #endif\r
+ /* Remove references to IotLog from the source code if logging is disabled. */\r
+ #else\r
+ /* @[declare_logging_log] */\r
+ #define IotLog( messageLevel, pLogConfig, ... )\r
+ /* @[declare_logging_log] */\r
+ /* @[declare_logging_printbuffer] */\r
+ #define IotLog_PrintBuffer( pHeader, pBuffer, bufferSize )\r
+ /* @[declare_logging_printbuffer] */\r
+ #define IotLogError( ... )\r
+ #define IotLogWarn( ... )\r
+ #define IotLogInfo( ... )\r
+ #define IotLogDebug( ... )\r
+ #endif\r
+#endif\r
+\r
+#endif /* ifndef IOT_LOGGING_SETUP_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_taskpool.h\r
+ * @brief User-facing functions of the task pool library.\r
+ */\r
+\r
+#ifndef IOT_TASKPOOL_H_\r
+#define IOT_TASKPOOL_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+#include <stddef.h>\r
+\r
+/* Task pool types. */\r
+#include "types/iot_taskpool_types.h"\r
+\r
+/*------------------------- Task Pool library functions --------------------------*/\r
+\r
+/**\r
+ * @functionspage{taskpool,task pool library}\r
+ * - @functionname{taskpool_function_createsystemtaskpool}\r
+ * - @functionname{taskpool_function_getsystemtaskpool}\r
+ * - @functionname{taskpool_function_create}\r
+ * - @functionname{taskpool_function_destroy}\r
+ * - @functionname{taskpool_function_setmaxthreads}\r
+ * - @functionname{taskpool_function_createjob}\r
+ * - @functionname{taskpool_function_createrecyclablejob}\r
+ * - @functionname{taskpool_function_destroyrecyclablejob}\r
+ * - @functionname{taskpool_function_recyclejob}\r
+ * - @functionname{taskpool_function_schedule}\r
+ * - @functionname{taskpool_function_scheduledeferred}\r
+ * - @functionname{taskpool_function_getstatus}\r
+ * - @functionname{taskpool_function_trycancel}\r
+ * - @functionname{taskpool_function_getjobstoragefromhandle}\r
+ * - @functionname{taskpool_function_strerror}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotTaskPool_CreateSystemTaskPool,taskpool,createsystemtaskpool}\r
+ * @functionpage{IotTaskPool_GetSystemTaskPool,taskpool,getsystemtaskpool}\r
+ * @functionpage{IotTaskPool_Create,taskpool,create}\r
+ * @functionpage{IotTaskPool_Destroy,taskpool,destroy}\r
+ * @functionpage{IotTaskPool_SetMaxThreads,taskpool,setmaxthreads}\r
+ * @functionpage{IotTaskPool_CreateJob,taskpool,createjob}\r
+ * @functionpage{IotTaskPool_CreateRecyclableJob,taskpool,createrecyclablejob}\r
+ * @functionpage{IotTaskPool_DestroyRecyclableJob,taskpool,destroyrecyclablejob}\r
+ * @functionpage{IotTaskPool_RecycleJob,taskpool,recyclejob}\r
+ * @functionpage{IotTaskPool_Schedule,taskpool,schedule}\r
+ * @functionpage{IotTaskPool_ScheduleDeferred,taskpool,scheduledeferred}\r
+ * @functionpage{IotTaskPool_GetStatus,taskpool,getstatus}\r
+ * @functionpage{IotTaskPool_TryCancel,taskpool,trycancel}\r
+ * @functionpage{IotTaskPool_GetJobStorageFromHandle,taskpool,getjobstoragefromhandle}\r
+ * @functionpage{IotTaskPool_strerror,taskpool,strerror}\r
+ */\r
+\r
+/**\r
+ * @brief Creates the one single instance of the system task pool.\r
+ *\r
+ * This function should be called once by the application to initialize the one single instance of the system task pool.\r
+ * An application should initialize the system task pool early in the boot sequence, before initializing any other library\r
+ * and before posting any jobs. Early initialization it typically easy to accomplish by creating the system task pool\r
+ * before starting the scheduler.\r
+ *\r
+ * This function does not allocate memory to hold the task pool data structures and state, but it\r
+ * may allocate memory to hold the dependent entities and data structures, e.g. the threads of the task\r
+ * pool. The system task pool handle is recoverable for later use by calling @ref IotTaskPool_GetSystemTaskPool or\r
+ * the shortcut @ref IOT_SYSTEM_TASKPOOL.\r
+ *\r
+ * @param[in] pInfo A pointer to the task pool initialization data.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_NO_MEMORY\r
+ *\r
+ * @warning This function should be called only once. Calling this function more that once will result in\r
+ * undefined behavior.\r
+ *\r
+ */\r
+/* @[declare_taskpool_createsystemtaskpool] */\r
+IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo );\r
+/* @[declare_taskpool_createsystemtaskpool] */\r
+\r
+/**\r
+ * @brief Retrieves the one and only instance of a system task pool\r
+ *\r
+ * This function retrieves the system task pool created with @ref IotTaskPool_CreateSystemTaskPool, and it is functionally\r
+ * equivalent to using the shortcut @ref IOT_SYSTEM_TASKPOOL.\r
+ *\r
+ * @return The system task pool handle.\r
+ *\r
+ * @warning This function should be called after creating the system task pool with @ref IotTaskPool_CreateSystemTaskPool.\r
+ * Calling this function before creating the system task pool may return a pointer to an uninitialized task pool, NULL, or otherwise\r
+ * fail with undefined behaviour.\r
+ *\r
+ */\r
+/* @[declare_taskpool_getsystemtaskpool] */\r
+IotTaskPool_t IotTaskPool_GetSystemTaskPool( void );\r
+/* @[declare_taskpool_getsystemtaskpool] */\r
+\r
+/**\r
+ * @brief Creates one instance of a task pool.\r
+ *\r
+ * This function should be called by the user to initialize one instance of a task\r
+ * pool. The task pool instance will be created around the storage pointed to by the `pTaskPool`\r
+ * parameter. This function will create the minimum number of threads requested by the user\r
+ * through an instance of the #IotTaskPoolInfo_t type specified with the `pInfo` parameter.\r
+ * This function does not allocate memory to hold the task pool data structures and state, but it\r
+ * may allocates memory to hold the dependent data structures, e.g. the threads of the task\r
+ * pool.\r
+ *\r
+ * @param[in] pInfo A pointer to the task pool initialization data.\r
+ * @param[out] pTaskPool A pointer to the task pool handle to be used after initialization.\r
+ * The pointer `pTaskPool` will hold a valid handle only if (@ref IotTaskPool_Create)\r
+ * completes successfully.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_NO_MEMORY\r
+ *\r
+ */\r
+/* @[declare_taskpool_create] */\r
+IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo,\r
+ IotTaskPool_t * const pTaskPool );\r
+/* @[declare_taskpool_create] */\r
+\r
+/**\r
+ * @brief Destroys a task pool instance and collects all memory associated with a task pool and its\r
+ * satellite data structures.\r
+ *\r
+ * This function should be called to destroy one instance of a task pool previously created with a call\r
+ * to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool.\r
+ * Calling this fuction release all underlying resources. After calling this function, any job scheduled but not yet executed\r
+ * will be cancelled and destroyed.\r
+ * The `taskPool` instance will no longer be valid after this function returns.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create or\r
+ * @ref IotTaskPool_CreateSystemTaskPool. The `taskPool` instance will no longer be valid after this function returns.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ *\r
+ */\r
+/* @[declare_taskpool_destroy] */\r
+IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPool );\r
+/* @[declare_taskpool_destroy] */\r
+\r
+/**\r
+ * @brief Sets the maximum number of threads for one instance of a task pool.\r
+ *\r
+ * This function sets the maximum number of threads for the task pool\r
+ * pointed to by `taskPool`.\r
+ *\r
+ * If the number of currently active threads in the task pool is greater than `maxThreads`, this\r
+ * function causes the task pool to shrink the number of active threads.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool that must have been previously initialized with\r
+ * a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool.\r
+ * @param[in] maxThreads The maximum number of threads for the task pool.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ */\r
+/* @[declare_taskpool_setmaxthreads] */\r
+IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPool,\r
+ uint32_t maxThreads );\r
+/* @[declare_taskpool_setmaxthreads] */\r
+\r
+/**\r
+ * @brief Creates a job for the task pool around a user-provided storage.\r
+ *\r
+ * This function may allocate memory to hold the state for a job.\r
+ *\r
+ * @param[in] userCallback A user-specified callback for the job.\r
+ * @param[in] pUserContext A user-specified context for the callback.\r
+ * @param[in] pJobStorage The storage for the job data structure.\r
+ * @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this\r
+ * function returns successfully. This handle can be used to inspect the job status with\r
+ * @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc....\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ *\r
+ *\r
+ */\r
+/* @[declare_taskpool_createjob] */\r
+IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ IotTaskPoolJobStorage_t * const pJobStorage,\r
+ IotTaskPoolJob_t * const pJob );\r
+/* @[declare_taskpool_createjob] */\r
+\r
+/**\r
+ * brief Creates a job for the task pool by allocating the job dynamically.\r
+ *\r
+ * A recyclable job does not need to be allocated twice, but it can rather be reused through\r
+ * subsequent calls to @ref IotTaskPool_CreateRecyclableJob.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool for which to create a recyclable job.\r
+ * @param[in] userCallback A user-specified callback for the job.\r
+ * @param[in] pUserContext A user-specified context for the callback.\r
+ * @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this\r
+ * function returns successfully. This handle can be used to inspect the job status with\r
+ * @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc....\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_NO_MEMORY\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ * @note This function will not allocate memory.\r
+ *\r
+ * @warning A recyclable job should be recycled with a call to @ref IotTaskPool_RecycleJob rather than destroyed.\r
+ *\r
+ */\r
+/* @[declare_taskpool_createrecyclablejob] */\r
+IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPool,\r
+ IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ IotTaskPoolJob_t * const pJob );\r
+/* @[declare_taskpool_createrecyclablejob] */\r
+\r
+/**\r
+ * @brief This function un-initializes a job.\r
+ *\r
+ * This function will destroy a job created with @ref IotTaskPool_CreateRecyclableJob.\r
+ * A job should not be destroyed twice. A job that was previously scheduled but has not completed yet should not be destroyed,\r
+ * but rather the application should attempt to cancel it first by calling @ref IotTaskPool_TryCancel.\r
+ * An attempt to destroy a job that was scheduled but not yet executed or canceled, may result in a\r
+ * @ref IOT_TASKPOOL_ILLEGAL_OPERATION error.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool.\r
+ * @param[in] job A handle to a job that was create with a call to @ref IotTaskPool_CreateJob.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_ILLEGAL_OPERATION\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ * @warning The task pool will try and prevent destroying jobs that are currently queued for execution, but does\r
+ * not enforce strict ordering of operations. It is up to the user to make sure @ref IotTaskPool_DestroyRecyclableJob is not called\r
+ * our of order.\r
+ *\r
+ * @warning Calling this function on job that was not previously created with @ref IotTaskPool_CreateRecyclableJob\r
+ * will result in a @ref IOT_TASKPOOL_ILLEGAL_OPERATION error.\r
+ *\r
+ */\r
+/* @[declare_taskpool_destroyrecyclablejob] */\r
+IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job );\r
+/* @[declare_taskpool_destroyrecyclablejob] */\r
+\r
+/**\r
+ * @brief Recycles a job into the task pool job cache.\r
+ *\r
+ * This function will try and recycle the job into the task pool cache. If the cache is full,\r
+ * the job memory is destroyed as if the user called @ref IotTaskPool_DestroyRecyclableJob. The job should be recycled into\r
+ * the task pool instance from where it was allocated.\r
+ * Failure to do so will yield undefined results. A job should not be recycled twice. A job\r
+ * that was previously scheduled but not completed or canceled cannot be safely recycled. An attempt to do so will result\r
+ * in an @ref IOT_TASKPOOL_ILLEGAL_OPERATION error.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create.\r
+ * @param[out] job A pointer to a job that was create with a call to @ref IotTaskPool_CreateJob.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_ILLEGAL_OPERATION\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ * @warning The `taskPool` used in this function should be the same\r
+ * used to create the job pointed to by `job`, or the results will be undefined.\r
+ *\r
+ * @warning Attempting to call this function on a statically allocated job will result in @ref IOT_TASKPOOL_ILLEGAL_OPERATION\r
+ * error.\r
+ *\r
+ * @warning This function should be used to recycle a job in the task pool cache when after the job executed.\r
+ * Failing to call either this function or @ref IotTaskPool_DestroyRecyclableJob will result is a memory leak. Statically\r
+ * allocated jobs do not need to be recycled or destroyed.\r
+ *\r
+ */\r
+/* @[declare_taskpool_recyclejob] */\r
+IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job );\r
+/* @[declare_taskpool_recyclejob] */\r
+\r
+/**\r
+ * @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob\r
+ * against the task pool pointed to by `taskPool`.\r
+ *\r
+ * See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool\r
+ * library.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool that must have been previously initialized with.\r
+ * a call to @ref IotTaskPool_Create.\r
+ * @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob.\r
+ * @param[in] flags Flags to be passed by the user, e.g. to identify the job as high priority by specifying #IOT_TASKPOOL_JOB_HIGH_PRIORITY.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_ILLEGAL_OPERATION\r
+ * - #IOT_TASKPOOL_NO_MEMORY\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ *\r
+ * @note This function will not allocate memory, so it is guaranteed to succeed if the paramters are correct and the task pool\r
+ * was correctly initialized, and not yet destroyed.\r
+ *\r
+ * @warning The `taskPool` used in this function should be the same used to create the job pointed to by `job`, or the\r
+ * results will be undefined.\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ * // An example of a user context to pass to a callback through a task pool thread.\r
+ * typedef struct JobUserContext\r
+ * {\r
+ * uint32_t counter;\r
+ * } JobUserContext_t;\r
+ *\r
+ * // An example of a user callback to invoke through a task pool thread.\r
+ * static void ExecutionCb( IotTaskPool_t taskPool, IotTaskPoolJob_t job, void * context )\r
+ * {\r
+ * ( void )taskPool;\r
+ * ( void )job;\r
+ *\r
+ * JobUserContext_t * pUserContext = ( JobUserContext_t * )context;\r
+ *\r
+ * pUserContext->counter++;\r
+ * }\r
+ *\r
+ * void TaskPoolExample( )\r
+ * {\r
+ * JobUserContext_t userContext = { 0 };\r
+ * IotTaskPoolJob_t job;\r
+ * IotTaskPool_t taskPool;\r
+ *\r
+ * // Configure the task pool to hold at least two threads and three at the maximum.\r
+ * // Provide proper stack size and priority per the application needs.\r
+ *\r
+ * const IotTaskPoolInfo_t tpInfo = { .minThreads = 2, .maxThreads = 3, .stackSize = 512, .priority = 0 };\r
+ *\r
+ * // Create a task pool.\r
+ * IotTaskPool_Create( &tpInfo, &taskPool );\r
+ *\r
+ * // Statically allocate one job, schedule it.\r
+ * IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job );\r
+ *\r
+ * IotTaskPoolError_t errorSchedule = IotTaskPool_Schedule( taskPool, &job, 0 );\r
+ *\r
+ * switch ( errorSchedule )\r
+ * {\r
+ * case IOT_TASKPOOL_SUCCESS:\r
+ * break;\r
+ * case IOT_TASKPOOL_BAD_PARAMETER: // Invalid parameters, such as a NULL handle, can trigger this error.\r
+ * case IOT_TASKPOOL_ILLEGAL_OPERATION: // Scheduling a job that was previously scheduled or destroyed could trigger this error.\r
+ * case IOT_TASKPOOL_NO_MEMORY: // Scheduling a with flag #IOT_TASKPOOL_JOB_HIGH_PRIORITY could trigger this error.\r
+ * case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS: // Scheduling a job after trying to destroy the task pool could trigger this error.\r
+ * // ASSERT\r
+ * break;\r
+ * default:\r
+ * // ASSERT\r
+ * }\r
+ *\r
+ * //\r
+ * // ... Perform other operations ...\r
+ * //\r
+ *\r
+ * IotTaskPool_Destroy( taskPool );\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_taskpool_schedule] */\r
+IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job,\r
+ uint32_t flags );\r
+/* @[declare_taskpool_schedule] */\r
+\r
+/**\r
+ * @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool\r
+ * pointed to by `taskPool` to be executed after a user-defined time interval.\r
+ *\r
+ * See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool\r
+ * library.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool that must have been previously initialized with.\r
+ * a call to @ref IotTaskPool_Create.\r
+ * @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob.\r
+ * @param[in] timeMs The time in milliseconds to wait before scheduling the job.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_ILLEGAL_OPERATION\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ *\r
+ * @note This function will not allocate memory.\r
+ *\r
+ * @warning The `taskPool` used in this function should be the same\r
+ * used to create the job pointed to by `job`, or the results will be undefined.\r
+ *\r
+ */\r
+/* @[declare_taskpool_scheduledeferred] */\r
+IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job,\r
+ uint32_t timeMs );\r
+/* @[declare_taskpool_scheduledeferred] */\r
+\r
+/**\r
+ * @brief This function retrieves the current status of a job.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool that must have been previously initialized with\r
+ * a call to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool.\r
+ * @param[in] job The job to cancel.\r
+ * @param[out] pStatus The status of the job at the time of cancellation.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ *\r
+ * @warning This function is not thread safe and the job status returned in `pStatus` may be invalid by the time\r
+ * the calling thread has a chance to inspect it.\r
+ */\r
+/* @[declare_taskpool_getstatus] */\r
+IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job,\r
+ IotTaskPoolJobStatus_t * const pStatus );\r
+/* @[declare_taskpool_getstatus] */\r
+\r
+/**\r
+ * @brief This function tries to cancel a job that was previously scheduled with @ref IotTaskPool_Schedule.\r
+ *\r
+ * A job can be canceled only if it is not yet executing, i.e. if its status is\r
+ * @ref IOT_TASKPOOL_STATUS_READY or @ref IOT_TASKPOOL_STATUS_SCHEDULED. Calling\r
+ * @ref IotTaskPool_TryCancel on a job whose status is @ref IOT_TASKPOOL_STATUS_COMPLETED,\r
+ * or #IOT_TASKPOOL_STATUS_CANCELED will yield a #IOT_TASKPOOL_CANCEL_FAILED return result.\r
+ *\r
+ * @param[in] taskPool A handle to the task pool that must have been previously initialized with\r
+ * a call to @ref IotTaskPool_Create.\r
+ * @param[in] job The job to cancel.\r
+ * @param[out] pStatus The status of the job at the time of cancellation.\r
+ *\r
+ * @return One of the following:\r
+ * - #IOT_TASKPOOL_SUCCESS\r
+ * - #IOT_TASKPOOL_BAD_PARAMETER\r
+ * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
+ * - #IOT_TASKPOOL_CANCEL_FAILED\r
+ *\r
+ * @warning The `taskPool` used in this function should be the same\r
+ * used to create the job pointed to by `job`, or the results will be undefined.\r
+ *\r
+ */\r
+/* @[declare_taskpool_trycancel] */\r
+IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPool,\r
+ IotTaskPoolJob_t job,\r
+ IotTaskPoolJobStatus_t * const pStatus );\r
+/* @[declare_taskpool_trycancel] */\r
+\r
+/**\r
+ * @brief Returns a pointer to the job storage from an instance of a job handle\r
+ * of type @ref IotTaskPoolJob_t. This function is guaranteed to succeed for a\r
+ * valid job handle.\r
+ *\r
+ * @param[in] job The job handle.\r
+ *\r
+ * @return A pointer to the storage associated with the job handle `job`.\r
+ *\r
+ * @warning If the `job` handle used is invalid, the results will be undefined.\r
+ */\r
+/* @[declare_taskpool_getjobstoragefromhandle] */\r
+IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t job );\r
+/* @[declare_taskpool_getjobstoragefromhandle] */\r
+\r
+/**\r
+ * @brief Returns a string that describes an @ref IotTaskPoolError_t.\r
+ *\r
+ * Like the POSIX's `strerror`, this function returns a string describing a\r
+ * return code. In this case, the return code is a task pool library error code,\r
+ * `status`.\r
+ *\r
+ * The string returned by this function <b>MUST</b> be treated as read-only: any\r
+ * attempt to modify its contents may result in a crash. Therefore, this function\r
+ * is limited to usage in logging.\r
+ *\r
+ * @param[in] status The status to describe.\r
+ *\r
+ * @return A read-only string that describes `status`.\r
+ *\r
+ * @warning The string returned by this function must never be modified.\r
+ */\r
+/* @[declare_taskpool_strerror] */\r
+const char * IotTaskPool_strerror( IotTaskPoolError_t status );\r
+/* @[declare_taskpool_strerror] */\r
+\r
+/**\r
+ * @brief The maximum number of task pools to be created when using\r
+ * a memory pool.\r
+ */\r
+#ifndef IOT_TASKPOOLS\r
+#define IOT_TASKPOOLS ( 4 )\r
+#endif\r
+\r
+/**\r
+ * @brief The maximum number of jobs to cache.\r
+ */\r
+#ifndef IOT_TASKPOOL_JOBS_RECYCLE_LIMIT\r
+ #define IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ( 8UL )\r
+#endif\r
+\r
+/**\r
+ * @brief The maximum timeout in milliseconds to wait for a job to be scheduled before waking up a worker thread.\r
+ * A worker thread that wakes up as a result of a timeout may exit to allow the task pool to fold back to its\r
+ * minimum number of threads.\r
+ */\r
+#ifndef IOT_TASKPOOL_JOB_WAIT_TIMEOUT_MS\r
+ #define IOT_TASKPOOL_JOB_WAIT_TIMEOUT_MS ( 60 * 1000UL )\r
+#endif\r
+\r
+#endif /* ifndef IOT_TASKPOOL_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_error.h\r
+ * @brief Provides macros for error checking and function cleanup.\r
+ *\r
+ * The macros in this file are generic. They may be customized by each library\r
+ * by setting the library prefix.\r
+ */\r
+\r
+#ifndef IOT_ERROR_H_\r
+#define IOT_ERROR_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/**\r
+ * @brief Declare the status variable and an initial value.\r
+ *\r
+ * This macro should be at the beginning of any functions that use cleanup sections.\r
+ *\r
+ * @param[in] statusType The type of the status variable for this function.\r
+ * @param[in] initialValue The initial value to assign to the status variable.\r
+ */\r
+#define IOT_FUNCTION_ENTRY( statusType, initialValue ) statusType status = initialValue\r
+\r
+/**\r
+ * @brief Declares the label that begins a cleanup section.\r
+ *\r
+ * This macro should be placed at the end of a function and followed by\r
+ * #IOT_FUNCTION_CLEANUP_END.\r
+ */\r
+#define IOT_FUNCTION_CLEANUP_BEGIN() iotCleanup:\r
+\r
+/**\r
+ * @brief Declares the end of a cleanup section.\r
+ *\r
+ * This macro should be placed at the end of a function and preceded by\r
+ * #IOT_FUNCTION_CLEANUP_BEGIN.\r
+ */\r
+#define IOT_FUNCTION_CLEANUP_END() return status\r
+\r
+/**\r
+ * @brief Declares an empty cleanup section.\r
+ *\r
+ * This macro should be placed at the end of a function to exit on error if no\r
+ * cleanup is required.\r
+ */\r
+#define IOT_FUNCTION_EXIT_NO_CLEANUP() IOT_FUNCTION_CLEANUP_BEGIN(); IOT_FUNCTION_CLEANUP_END()\r
+\r
+/**\r
+ * @brief Jump to the cleanup section.\r
+ */\r
+#define IOT_GOTO_CLEANUP() goto iotCleanup\r
+\r
+/**\r
+ * @brief Assign a value to the status variable and jump to the cleanup section.\r
+ *\r
+ * @param[in] statusValue The value to assign to the status variable.\r
+ */\r
+#define IOT_SET_AND_GOTO_CLEANUP( statusValue ) { status = ( statusValue ); IOT_GOTO_CLEANUP(); }\r
+\r
+/**\r
+ * @brief Jump to the cleanup section if a condition is `false`.\r
+ *\r
+ * This macro may be used in place of `assert` to exit a function is a condition\r
+ * is `false`.\r
+ *\r
+ * @param[in] condition The condition to check.\r
+ */\r
+#define IOT_GOTO_CLEANUP_IF_FALSE( condition ) { if( ( condition ) == false ) { IOT_GOTO_CLEANUP(); } }\r
+\r
+/**\r
+ * @brief Assign a value to the status variable and jump to the cleanup section\r
+ * if a condition is `false`.\r
+ *\r
+ * @param[in] statusValue The value to assign to the status variable.\r
+ * @param[in] condition The condition to check.\r
+ */\r
+#define IOT_SET_AND_GOTO_CLEANUP_IF_FALSE( statusValue, condition ) \\r
+ if( ( condition ) == false ) \\r
+ IOT_SET_AND_GOTO_CLEANUP( statusValue )\r
+\r
+/**\r
+ * @brief Check a condition; if `false`, assign the "Bad parameter" status value\r
+ * and jump to the cleanup section.\r
+ *\r
+ * @param[in] libraryPrefix The library prefix of the status variable.\r
+ * @param[in] condition The condition to check.\r
+ */\r
+#define IOT_VALIDATE_PARAMETER( libraryPrefix, condition ) \\r
+ IOT_SET_AND_GOTO_CLEANUP_IF_FALSE( libraryPrefix ## _BAD_PARAMETER, condition )\r
+\r
+#endif /* ifndef IOT_ERROR_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_logging.h\r
+ * @brief Generic logging function header file.\r
+ *\r
+ * Declares the generic logging function and the log levels. This file never\r
+ * needs to be included in source code. The header iot_logging_setup.h should\r
+ * be included instead.\r
+ *\r
+ * @see iot_logging_setup.h\r
+ */\r
+\r
+#ifndef IOT_LOGGING_H_\r
+#define IOT_LOGGING_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * @constantspage{logging,logging library}\r
+ *\r
+ * @section logging_constants_levels Log levels\r
+ * @brief Log levels for the libraries in this SDK.\r
+ *\r
+ * Each library should specify a log level by setting @ref LIBRARY_LOG_LEVEL.\r
+ * All log messages with a level at or below the specified level will be printed\r
+ * for that library.\r
+ *\r
+ * Currently, there are 4 log levels. In the order of lowest to highest, they are:\r
+ * - #IOT_LOG_NONE <br>\r
+ * @copybrief IOT_LOG_NONE\r
+ * - #IOT_LOG_ERROR <br>\r
+ * @copybrief IOT_LOG_ERROR\r
+ * - #IOT_LOG_WARN <br>\r
+ * @copybrief IOT_LOG_WARN\r
+ * - #IOT_LOG_INFO <br>\r
+ * @copybrief IOT_LOG_INFO\r
+ * - #IOT_LOG_DEBUG <br>\r
+ * @copybrief IOT_LOG_DEBUG\r
+ */\r
+\r
+/**\r
+ * @brief No log messages.\r
+ *\r
+ * Log messages with this level will be silently discarded. When @ref\r
+ * LIBRARY_LOG_LEVEL is #IOT_LOG_NONE, logging is disabled and no [logging functions]\r
+ * (@ref logging_functions) can be called.\r
+ */\r
+#define IOT_LOG_NONE 0\r
+\r
+/**\r
+ * @brief Only critical, unrecoverable errors.\r
+ *\r
+ * Log messages with this level will be printed when a library encounters an\r
+ * error from which it cannot easily recover.\r
+ */\r
+#define IOT_LOG_ERROR 1\r
+\r
+/**\r
+ * @brief Message about an abnormal but recoverable event.\r
+ *\r
+ * Log messages with this level will be printed when a library encounters an\r
+ * abnormal event that may be indicative of an error. Libraries should continue\r
+ * execution after logging a warning.\r
+ */\r
+#define IOT_LOG_WARN 2\r
+\r
+/**\r
+ * @brief A helpful, informational message.\r
+ *\r
+ * Log messages with this level may indicate the normal status of a library\r
+ * function. They should be used to track how far a program has executed.\r
+ */\r
+#define IOT_LOG_INFO 3\r
+\r
+/**\r
+ * @brief Detailed and excessive debug information.\r
+ *\r
+ * Log messages with this level are intended for developers. They may contain\r
+ * excessive information such as internal variables, buffers, or other specific\r
+ * information.\r
+ */\r
+#define IOT_LOG_DEBUG 4\r
+\r
+/**\r
+ * @paramstructs{logging,logging}\r
+ */\r
+\r
+/**\r
+ * @ingroup logging_datatypes_paramstructs\r
+ * @brief Log message configuration struct.\r
+ *\r
+ * @paramfor @ref logging_function_log, @ref logging_function_generic\r
+ *\r
+ * By default, log messages print the library name, log level, and a timestring.\r
+ * This struct can be passed to @ref logging_function_generic to disable one of\r
+ * the above components in the log message.\r
+ *\r
+ * <b>Example:</b>\r
+ *\r
+ * @code{c}\r
+ * IotLog_Generic( IOT_LOG_DEBUG, "SAMPLE", IOT_LOG_DEBUG, NULL, "Hello world!" );\r
+ * @endcode\r
+ * The code above prints the following message:\r
+ * @code\r
+ * [DEBUG][SAMPLE][2018-01-01 12:00:00] Hello world!\r
+ * @endcode\r
+ *\r
+ * The timestring can be disabled as follows:\r
+ * @code\r
+ * IotLogConfig_t logConfig = { .hideLogLevel = false, .hideLibraryName = false, .hideTimestring = true};\r
+ * IotLog_Generic( IOT_LOG_DEBUG, "SAMPLE", IOT_LOG_DEBUG, &logConfig, "Hello world!" );\r
+ * @endcode\r
+ * The resulting log message will be:\r
+ * @code\r
+ * [DEBUG][SAMPLE] Hello world!\r
+ * @endcode\r
+ */\r
+typedef struct IotLogConfig\r
+{\r
+ bool hideLogLevel; /**< @brief Don't print the log level string for this message. */\r
+ bool hideLibraryName; /**< @brief Don't print the library name for this message. */\r
+ bool hideTimestring; /**< @brief Don't print the timestring for this message. */\r
+} IotLogConfig_t;\r
+\r
+/**\r
+ * @functionspage{logging,logging library}\r
+ *\r
+ * - @functionname{logging_function_log}\r
+ * - @functionname{logging_function_printbuffer}\r
+ * - @functionname{logging_function_generic}\r
+ * - @functionname{logging_function_genericprintbuffer}\r
+ */\r
+\r
+/**\r
+ * @functionpage{IotLog_Generic,logging,generic}\r
+ * @functionpage{IotLog_PrintBuffer,logging,genericprintbuffer}\r
+ */\r
+\r
+/**\r
+ * @brief Generic logging function that prints a single message.\r
+ *\r
+ * This function is the generic logging function shared across all libraries.\r
+ * The library-specific logging function @ref logging_function_log is implemented\r
+ * using this function. Like @ref logging_function_log, this function is only\r
+ * available when @ref LIBRARY_LOG_LEVEL is #IOT_LOG_NONE.\r
+ *\r
+ * In most cases, the library-specific logging function @ref logging_function_log\r
+ * should be called instead of this function.\r
+ *\r
+ * @param[in] libraryLogSetting The log level setting of the library, used to\r
+ * determine if the log message should be printed. Must be one of the @ref\r
+ * logging_constants_levels.\r
+ * @param[in] pLibraryName The library name to print. See @ref LIBRARY_LOG_NAME.\r
+ * @param[in] messageLevel The log level of the this message. See @ref LIBRARY_LOG_LEVEL.\r
+ * @param[in] pLogConfig Pointer to a #IotLogConfig_t. Optional; pass `NULL` to ignore.\r
+ * @param[in] pFormat Format string for the log message.\r
+ * @param[in] ... Arguments for format specification.\r
+ *\r
+ * @return No return value. On errors, it prints nothing.\r
+ */\r
+/* @[declare_logging_generic] */\r
+void IotLog_Generic( int libraryLogSetting,\r
+ const char * const pLibraryName,\r
+ int messageLevel,\r
+ const IotLogConfig_t * const pLogConfig,\r
+ const char * const pFormat,\r
+ ... );\r
+/* @[declare_logging_generic] */\r
+\r
+/**\r
+ * @brief Generic function to log the contents of a buffer as bytes.\r
+ *\r
+ * This function is the generic buffer logging function shared across all libraries.\r
+ * The library-specific buffer logging function @ref logging_function_printbuffer is\r
+ * implemented using this function. Like @ref logging_function_printbuffer, this\r
+ * function is only available when @ref LIBRARY_LOG_LEVEL is #IOT_LOG_DEBUG.\r
+ *\r
+ * In most cases, the library-specific buffer logging function @ref\r
+ * logging_function_printbuffer should be called instead of this function.\r
+ *\r
+ * @param[in] pLibraryName The library name to print with the log. See @ref LIBRARY_LOG_NAME.\r
+ * @param[in] pHeader A message to print before printing the buffer.\r
+ * @param[in] pBuffer The buffer to print.\r
+ * @param[in] bufferSize The number of bytes in `pBuffer` to print.\r
+ *\r
+ * @return No return value. On errors, it prints nothing.\r
+ *\r
+ * @note To conserve memory, this function only allocates enough memory for a\r
+ * single line of output. Therefore, in multithreaded systems, its output may\r
+ * appear "fragmented" if other threads are logging simultaneously.\r
+ */\r
+/* @[declare_logging_genericprintbuffer] */\r
+void IotLog_GenericPrintBuffer( const char * const pLibraryName,\r
+ const char * const pHeader,\r
+ const uint8_t * const pBuffer,\r
+ size_t bufferSize );\r
+/* @[declare_logging_genericprintbuffer] */\r
+\r
+#endif /* ifndef IOT_LOGGING_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_static_memory.h\r
+ * @brief Common functions for managing static buffers. Only used when\r
+ * @ref IOT_STATIC_MEMORY_ONLY is `1`.\r
+ */\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* The functions in this file should only exist in static memory only mode, hence\r
+ * the check for IOT_STATIC_MEMORY_ONLY in the double inclusion guard. */\r
+#if !defined( IOT_STATIC_MEMORY_H_ ) && ( IOT_STATIC_MEMORY_ONLY == 1 )\r
+#define IOT_STATIC_MEMORY_H_\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * @functionspage{static_memory,static memory component}\r
+ * - @functionname{static_memory_function_init}\r
+ * - @functionname{static_memory_function_cleanup}\r
+ * - @functionname{static_memory_function_findfree}\r
+ * - @functionname{static_memory_function_returninuse}\r
+ * - @functionname{static_memory_function_messagebuffersize}\r
+ * - @functionname{static_memory_function_mallocmessagebuffer}\r
+ * - @functionname{static_memory_function_freemessagebuffer}\r
+ */\r
+\r
+/*----------------------- Initialization and cleanup ------------------------*/\r
+\r
+/**\r
+ * @functionpage{IotStaticMemory_Init,static_memory,init}\r
+ * @functionpage{IotStaticMemory_Cleanup,static_memory,cleanup}\r
+ */\r
+\r
+/**\r
+ * @brief One-time initialization function for static memory.\r
+ *\r
+ * This function performs internal setup of static memory. <b>It must be called\r
+ * once (and only once) before calling any other static memory function.</b>\r
+ * Calling this function more than once without first calling\r
+ * @ref static_memory_function_cleanup may result in a crash.\r
+ *\r
+ * @return `true` if initialization succeeded; `false` otherwise.\r
+ *\r
+ * @attention This function is called by `IotSdk_Init` and does not need to be\r
+ * called by itself.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ *\r
+ * @see static_memory_function_cleanup\r
+ */\r
+/* @[declare_static_memory_init] */\r
+bool IotStaticMemory_Init( void );\r
+/* @[declare_static_memory_init] */\r
+\r
+/**\r
+ * @brief One-time deinitialization function for static memory.\r
+ *\r
+ * This function frees resources taken in @ref static_memory_function_init.\r
+ * It should be called after to clean up static memory. After this function\r
+ * returns, @ref static_memory_function_init must be called again before\r
+ * calling any other static memory function.\r
+ *\r
+ * @attention This function is called by `IotSdk_Cleanup` and does not need\r
+ * to be called by itself.\r
+ *\r
+ * @warning No thread-safety guarantees are provided for this function.\r
+ *\r
+ * @see static_memory_function_init\r
+ */\r
+/* @[declare_static_memory_cleanup] */\r
+void IotStaticMemory_Cleanup( void );\r
+/* @[declare_static_memory_cleanup] */\r
+\r
+/*------------------------- Buffer allocation and free ----------------------*/\r
+\r
+/**\r
+ * @functionpage{IotStaticMemory_FindFree,static_memory,findfree}\r
+ * @functionpage{IotStaticMemory_ReturnInUse,static_memory,returninuse}\r
+ */\r
+\r
+/**\r
+ * @brief Find a free buffer using the "in-use" flags.\r
+ *\r
+ * If a free buffer is found, this function marks the buffer in-use. This function\r
+ * is common to the static memory implementation.\r
+ *\r
+ * @param[in] pInUse The "in-use" flags to search.\r
+ * @param[in] limit How many flags to check, i.e. the size of `pInUse`.\r
+ *\r
+ * @return The index of a free buffer; `-1` if no free buffers are available.\r
+ *\r
+ * <b>Example</b>:\r
+ * @code{c}\r
+ * // To use this function, first declare two arrays. One provides the statically-allocated\r
+ * // objects, the other provides flags to determine which objects are in-use.\r
+ * #define NUMBER_OF_OBJECTS ...\r
+ * #define OBJECT_SIZE ...\r
+ * static bool _pInUseObjects[ NUMBER_OF_OBJECTS ] = { 0 };\r
+ * static uint8_t _pObjects[ NUMBER_OF_OBJECTS ][ OBJECT_SIZE ] = { { 0 } }; // Placeholder for objects.\r
+ *\r
+ * // The function to statically allocate objects. Must have the same signature\r
+ * // as malloc().\r
+ * void * Iot_MallocObject( size_t size )\r
+ * {\r
+ * int32_t freeIndex = -1;\r
+ * void * pNewObject = NULL;\r
+ *\r
+ * // Check that sizes match. \r
+ * if( size != OBJECT_SIZE )\r
+ * {\r
+ * // Get the index of a free object.\r
+ * freeIndex = IotStaticMemory_FindFree( _pInUseMessageBuffers,\r
+ * IOT_MESSAGE_BUFFERS );\r
+ *\r
+ * if( freeIndex != -1 )\r
+ * {\r
+ * pNewBuffer = &( _pMessageBuffers[ freeIndex ][ 0 ] );\r
+ * }\r
+ * }\r
+ *\r
+ * return pNewBuffer;\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_static_memory_findfree] */\r
+int32_t IotStaticMemory_FindFree( bool * pInUse,\r
+ size_t limit );\r
+/* @[declare_static_memory_findfree] */\r
+\r
+/**\r
+ * @brief Return an "in-use" buffer.\r
+ *\r
+ * This function is common to the static memory implementation.\r
+ *\r
+ * @param[in] ptr Pointer to the buffer to return.\r
+ * @param[in] pPool The pool of buffers that the in-use buffer was allocated from.\r
+ * @param[in] pInUse The "in-use" flags for pPool.\r
+ * @param[in] limit How many buffers (and flags) to check while searching for ptr.\r
+ * @param[in] elementSize The size of a single element in pPool.\r
+ *\r
+ * <b>Example</b>:\r
+ * @code{c}\r
+ * // To use this function, first declare two arrays. One provides the statically-allocated\r
+ * // objects, the other provides flags to determine which objects are in-use.\r
+ * #define NUMBER_OF_OBJECTS ...\r
+ * #define OBJECT_SIZE ...\r
+ * static bool _pInUseObjects[ NUMBER_OF_OBJECTS ] = { 0 };\r
+ * static uint8_t _pObjects[ NUMBER_OF_OBJECTS ][ OBJECT_SIZE ] = { { 0 } }; // Placeholder for objects.\r
+ *\r
+ * // The function to free statically-allocated objects. Must have the same signature\r
+ * // as free().\r
+ * void Iot_FreeObject( void * ptr )\r
+ * {\r
+ * IotStaticMemory_ReturnInUse( ptr,\r
+ * _pObjects,\r
+ * _pInUseObjects,\r
+ * NUMBER_OF_OBJECTS,\r
+ * OBJECT_SIZE );\r
+ * }\r
+ * @endcode\r
+ */\r
+/* @[declare_static_memory_returninuse] */\r
+void IotStaticMemory_ReturnInUse( void * ptr,\r
+ void * pPool,\r
+ bool * pInUse,\r
+ size_t limit,\r
+ size_t elementSize );\r
+/* @[declare_static_memory_returninuse] */\r
+\r
+/*------------------------ Message buffer management ------------------------*/\r
+\r
+/**\r
+ * @functionpage{Iot_MessageBufferSize,static_memory,messagebuffersize}\r
+ * @functionpage{Iot_MallocMessageBuffer,static_memory,mallocmessagebuffer}\r
+ * @functionpage{Iot_FreeMessageBuffer,static_memory,freemessagebuffer}\r
+ */\r
+\r
+/**\r
+ * @brief Get the fixed size of a message buffer.\r
+ *\r
+ * The size of the message buffers are known at compile time, but it is a [constant]\r
+ * (@ref IOT_MESSAGE_BUFFER_SIZE) that may not be visible to all source files.\r
+ * This function allows other source files to know the size of a message buffer.\r
+ *\r
+ * @return The size, in bytes, of a single message buffer.\r
+ */\r
+/* @[declare_static_memory_messagebuffersize] */\r
+size_t Iot_MessageBufferSize( void );\r
+/* @[declare_static_memory_messagebuffersize] */\r
+\r
+/**\r
+ * @brief Get an empty message buffer.\r
+ *\r
+ * This function is the analog of [malloc]\r
+ * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html)\r
+ * for message buffers.\r
+ *\r
+ * @param[in] size Requested size for a message buffer.\r
+ *\r
+ * @return Pointer to the start of a message buffer. If the `size` argument is larger\r
+ * than the [fixed size of a message buffer](@ref IOT_MESSAGE_BUFFER_SIZE)\r
+ * or no message buffers are available, `NULL` is returned.\r
+ */\r
+/* @[declare_static_memory_mallocmessagebuffer] */\r
+void * Iot_MallocMessageBuffer( size_t size );\r
+/* @[declare_static_memory_mallocmessagebuffer] */\r
+\r
+/**\r
+ * @brief Free an in-use message buffer.\r
+ *\r
+ * This function is the analog of [free]\r
+ * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html)\r
+ * for message buffers.\r
+ *\r
+ * @param[in] ptr Pointer to the message buffer to free.\r
+ */\r
+/* @[declare_static_memory_freemessagebuffer] */\r
+void Iot_FreeMessageBuffer( void * ptr );\r
+/* @[declare_static_memory_freemessagebuffer] */\r
+ \r
+#endif /* if !defined( IOT_STATIC_MEMORY_H_ ) && ( IOT_STATIC_MEMORY_ONLY == 1 ) */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_taskpool_internal.h\r
+ * @brief Internal header of task pool library. This header should not be included in\r
+ * typical application code.\r
+ */\r
+\r
+#ifndef IOT_TASKPOOL_INTERNAL_H_\r
+#define IOT_TASKPOOL_INTERNAL_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Task pool include. */\r
+#include "private/iot_error.h"\r
+#include "iot_taskpool.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "semphr.h"\r
+#include "timers.h"\r
+\r
+/* Establish a few convenience macros to handle errors in a standard way. */\r
+\r
+/**\r
+ * @brief Every public API return an enumeration value with an undelying value of 0 in case of success.\r
+ */\r
+#define TASKPOOL_SUCCEEDED( x ) ( ( x ) == IOT_TASKPOOL_SUCCESS )\r
+\r
+/**\r
+ * @brief Every public API returns an enumeration value with an undelying value different than 0 in case of success.\r
+ */\r
+#define TASKPOOL_FAILED( x ) ( ( x ) != IOT_TASKPOOL_SUCCESS )\r
+\r
+/**\r
+ * @brief Jump to the cleanup area.\r
+ */\r
+#define TASKPOOL_GOTO_CLEANUP() IOT_GOTO_CLEANUP()\r
+\r
+/**\r
+ * @brief Declare the storage for the error status variable.\r
+ */\r
+#define TASKPOOL_FUNCTION_ENTRY( result ) IOT_FUNCTION_ENTRY( IotTaskPoolError_t, result )\r
+\r
+/**\r
+ * @brief Check error and leave in case of failure.\r
+ */\r
+#define TASKPOOL_ON_ERROR_GOTO_CLEANUP( expr ) \\r
+ { if( TASKPOOL_FAILED( status = ( expr ) ) ) { IOT_GOTO_CLEANUP(); } \\r
+ }\r
+\r
+/**\r
+ * @brief Exit if an argument is NULL.\r
+ */\r
+#define TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ptr ) IOT_VALIDATE_PARAMETER( IOT_TASKPOOL, ( ptr != NULL ) )\r
+\r
+/**\r
+ * @brief Exit if an argument is NULL.\r
+ */\r
+#define TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( expr ) IOT_VALIDATE_PARAMETER( IOT_TASKPOOL, ( ( expr ) == false ) )\r
+\r
+/**\r
+ * @brief Set error and leave.\r
+ */\r
+#define TASKPOOL_SET_AND_GOTO_CLEANUP( expr ) IOT_SET_AND_GOTO_CLEANUP( expr )\r
+\r
+/**\r
+ * @brief Initialize error and declare start of cleanup area.\r
+ */\r
+#define TASKPOOL_FUNCTION_CLEANUP() IOT_FUNCTION_CLEANUP_BEGIN()\r
+\r
+/**\r
+ * @brief Initialize error and declare end of cleanup area.\r
+ */\r
+#define TASKPOOL_FUNCTION_CLEANUP_END() IOT_FUNCTION_CLEANUP_END()\r
+\r
+/**\r
+ * @brief Create an empty cleanup area.\r
+ */\r
+#define TASKPOOL_NO_FUNCTION_CLEANUP() IOT_FUNCTION_EXIT_NO_CLEANUP()\r
+\r
+/**\r
+ * @brief Does not create a cleanup area.\r
+ */\r
+#define TASKPOOL_NO_FUNCTION_CLEANUP_NOLABEL() return status\r
+\r
+/**\r
+ * @def IotTaskPool_Assert( expression )\r
+ * @brief Assertion macro for the Task pool library.\r
+ *\r
+ * Set @ref IOT_TASKPOOL_ENABLE_ASSERTS to `1` to enable assertions in the Task pool\r
+ * library.\r
+ *\r
+ * @param[in] expression Expression to be evaluated.\r
+ */\r
+#if IOT_TASKPOOL_ENABLE_ASSERTS == 1\r
+ #ifndef IotTaskPool_Assert\r
+ #include <assert.h>\r
+ #define IotTaskPool_Assert( expression ) assert( expression )\r
+ #endif\r
+#else\r
+ #define IotTaskPool_Assert( expression )\r
+#endif\r
+\r
+/* Configure logs for TASKPOOL functions. */\r
+#ifdef IOT_LOG_LEVEL_TASKPOOL\r
+ #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_TASKPOOL\r
+#else\r
+ #ifdef IOT_LOG_LEVEL_GLOBAL\r
+ #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL\r
+ #else\r
+ #define LIBRARY_LOG_LEVEL IOT_LOG_NONE\r
+ #endif\r
+#endif\r
+\r
+#define LIBRARY_LOG_NAME ( "TASKPOOL" )\r
+#include "iot_logging_setup.h"\r
+\r
+/*\r
+ * Provide default values for undefined memory allocation functions based on\r
+ * the usage of dynamic memory allocation.\r
+ */\r
+#if IOT_STATIC_MEMORY_ONLY == 1\r
+ #include "private/iot_static_memory.h"\r
+\r
+/**\r
+ * @brief Allocate an #_taskPool_t. This function should have the\r
+ * same signature as [malloc].\r
+ */\r
+ void * IotTaskPool_MallocTaskPool( size_t size );\r
+\r
+/**\r
+ * @brief Free an #_taskPool_t. This function should have the\r
+ * same signature as [malloc].\r
+ */\r
+ void IotTaskPool_FreeTaskPool( void * ptr );\r
+\r
+/**\r
+ * @brief Allocate an #IotTaskPoolJob_t. This function should have the\r
+ * same signature as [malloc].\r
+ */\r
+ void * IotTaskPool_MallocJob( size_t size );\r
+\r
+/**\r
+ * @brief Free an #IotTaskPoolJob_t. This function should have the same\r
+ * same signature as [malloc].\r
+ * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).\r
+ */\r
+ void IotTaskPool_FreeJob( void * ptr );\r
+\r
+/**\r
+ * @brief Allocate an #_taskPoolTimerEvent_t. This function should have the\r
+ * same signature as [malloc].\r
+ */\r
+ void * IotTaskPool_MallocTimerEvent( size_t size );\r
+\r
+/**\r
+ * @brief Free an #_taskPoolTimerEvent_t. This function should have the\r
+ * same signature as[ free ].\r
+ */\r
+ void IotTaskPool_FreeTimerEvent( void * ptr );\r
+\r
+#else /* if IOT_STATIC_MEMORY_ONLY == 1 */\r
+ #include <stdlib.h>\r
+\r
+ #ifndef IotTaskPool_MallocTaskPool\r
+ #define IotTaskPool_MallocTaskPool malloc\r
+ #endif\r
+\r
+ #ifndef IotTaskPool_FreeTaskPool\r
+ #define IotTaskPool_FreeTaskPool free\r
+ #endif\r
+\r
+ #ifndef IotTaskPool_MallocJob\r
+ #define IotTaskPool_MallocJob malloc\r
+ #endif\r
+\r
+ #ifndef IotTaskPool_FreeJob\r
+ #define IotTaskPool_FreeJob free\r
+ #endif\r
+\r
+ #ifndef IotTaskPool_MallocTimerEvent\r
+ #define IotTaskPool_MallocTimerEvent malloc\r
+ #endif\r
+\r
+ #ifndef IotTaskPool_FreeTimerEvent\r
+ #define IotTaskPool_FreeTimerEvent free\r
+ #endif\r
+\r
+#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+/**\r
+ * @cond DOXYGEN_IGNORE\r
+ * Doxygen should ignore this section.\r
+ *\r
+ * A macros to manage task pool memory allocation.\r
+ */\r
+#define IOT_TASK_POOL_INTERNAL_STATIC ( ( uint32_t ) 0x00000001 ) /* Flag to mark a job as user-allocated. */\r
+/** @endcond */\r
+\r
+/**\r
+ * @brief Task pool jobs cache.\r
+ *\r
+ * @warning This is a system-level data type that should not be modified or used directly in any application.\r
+ * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.\r
+ *\r
+ */\r
+typedef struct _taskPoolCache\r
+{\r
+ IotListDouble_t freeList; /**< @brief A list ot hold cached jobs. */\r
+\r
+ uint32_t freeCount; /**< @brief A counter to track the number of jobs in the cache. */\r
+} _taskPoolCache_t;\r
+\r
+/**\r
+ * @brief The task pool data structure keeps track of the internal state and the signals for the dispatcher threads.\r
+ * The task pool is a thread safe data structure.\r
+ *\r
+ * @warning This is a system-level data type that should not be modified or used directly in any application.\r
+ * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.\r
+ *\r
+ */\r
+typedef struct _taskPool\r
+{\r
+ IotDeQueue_t dispatchQueue; /**< @brief The queue for the jobs waiting to be executed. */\r
+ IotListDouble_t timerEventsList; /**< @brief The timeouts queue for all deferred jobs waiting to be executed. */\r
+ _taskPoolCache_t jobsCache; /**< @brief A cache to re-use jobs in order to limit memory allocations. */\r
+ uint32_t activeThreads; /**< @brief The number of threads in the task pool at any given time. */\r
+ int32_t priority; /**< @brief The priority for all task pool threads. */\r
+ SemaphoreHandle_t dispatchSignal; /**< @brief The synchronization object on which threads are waiting for incoming jobs. */\r
+ StaticSemaphore_t dispatchSignalBuffer; /**< @brief The semaphore buffer. */\r
+ SemaphoreHandle_t startStopSignal; /**< @brief The synchronization object for threads to signal start and stop condition. */\r
+ StaticSemaphore_t startStopSignalBuffer; /**< @brief The semaphore buffer. */\r
+ TimerHandle_t timer; /**< @brief The timer for deferred jobs. */\r
+ StaticTimer_t timerBuffer; /**< @brief The timer buffer. */\r
+ bool running; /**< @brief A flag to track whether the task pool is operational or should shut down. */\r
+} _taskPool_t;\r
+\r
+/**\r
+ * @brief The job data structure keeps track of the user callback and context, as well as the status of the job.\r
+ *\r
+ * @warning This is a system-level data type that should not be modified or used directly in any application.\r
+ * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.\r
+ *\r
+ */\r
+typedef struct _taskPoolJob\r
+{\r
+ IotLink_t link; /**< @brief The link to insert the job in the dispatch queue. */\r
+ IotTaskPoolRoutine_t userCallback; /**< @brief The user provided callback. */\r
+ void * pUserContext; /**< @brief The user provided context. */\r
+ uint32_t flags; /**< @brief Internal flags. */\r
+ IotTaskPoolJobStatus_t status; /**< @brief The status for the job. */\r
+} _taskPoolJob_t;\r
+\r
+/**\r
+ * @brief Represents an operation that is subject to a timer.\r
+ *\r
+ * These events are queued per MQTT connection. They are sorted by their\r
+ * expiration time.\r
+ */\r
+typedef struct _taskPoolTimerEvent\r
+{\r
+ IotLink_t link; /**< @brief List link member. */\r
+ TickType_t expirationTime; /**< @brief When this event should be processed. */\r
+ IotTaskPoolJob_t job; /**< @brief The task pool job associated with this event. */\r
+} _taskPoolTimerEvent_t;\r
+\r
+#endif /* ifndef IOT_TASKPOOL_INTERNAL_H_ */
\ No newline at end of file
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_taskpool_types.h\r
+ * @brief Types of the task pool.\r
+ */\r
+\r
+#ifndef IOT_TASKPOOL_TYPES_H_\r
+#define IOT_TASKPOOL_TYPES_H_\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stdint.h>\r
+\r
+/* Platform types includes. */\r
+#include "types/iot_platform_types.h"\r
+\r
+/* Linear containers (lists and queues) include. */\r
+#include "iot_linear_containers.h"\r
+\r
+/*-------------------------- Task pool enumerated types --------------------------*/\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_enums\r
+ * @brief Return codes of [task pool functions](@ref taskpool_functions).\r
+ */\r
+typedef enum IotTaskPoolError\r
+{\r
+ /**\r
+ * @brief Task pool operation completed successfully.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_createsystemtaskpool\r
+ * - @ref taskpool_function_create\r
+ * - @ref taskpool_function_destroy\r
+ * - @ref taskpool_function_setmaxthreads\r
+ * - @ref taskpool_function_createjob\r
+ * - @ref taskpool_function_createrecyclablejob\r
+ * - @ref taskpool_function_destroyrecyclablejob\r
+ * - @ref taskpool_function_recyclejob\r
+ * - @ref taskpool_function_schedule\r
+ * - @ref taskpool_function_scheduledeferred\r
+ * - @ref taskpool_function_getstatus\r
+ * - @ref taskpool_function_trycancel\r
+ *\r
+ */\r
+ IOT_TASKPOOL_SUCCESS = 0,\r
+\r
+ /**\r
+ * @brief Task pool operation failed because at laest one parameter is invalid.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_createsystemtaskpool\r
+ * - @ref taskpool_function_create\r
+ * - @ref taskpool_function_destroy\r
+ * - @ref taskpool_function_setmaxthreads\r
+ * - @ref taskpool_function_createjob\r
+ * - @ref taskpool_function_createrecyclablejob\r
+ * - @ref taskpool_function_destroyrecyclablejob\r
+ * - @ref taskpool_function_recyclejob\r
+ * - @ref taskpool_function_schedule\r
+ * - @ref taskpool_function_scheduledeferred\r
+ * - @ref taskpool_function_getstatus\r
+ * - @ref taskpool_function_trycancel\r
+ *\r
+ */\r
+ IOT_TASKPOOL_BAD_PARAMETER,\r
+\r
+ /**\r
+ * @brief Task pool operation failed because it is illegal.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_createjob\r
+ * - @ref taskpool_function_createrecyclablejob\r
+ * - @ref taskpool_function_destroyrecyclablejob\r
+ * - @ref taskpool_function_recyclejob\r
+ * - @ref taskpool_function_schedule\r
+ * - @ref taskpool_function_scheduledeferred\r
+ * - @ref taskpool_function_trycancel\r
+ *\r
+ */\r
+ IOT_TASKPOOL_ILLEGAL_OPERATION,\r
+\r
+ /**\r
+ * @brief Task pool operation failed because allocating memory failed.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_createsystemtaskpool\r
+ * - @ref taskpool_function_create\r
+ * - @ref taskpool_function_setmaxthreads\r
+ * - @ref taskpool_function_createrecyclablejob\r
+ * - @ref taskpool_function_scheduledeferred\r
+ * - @ref taskpool_function_getstatus\r
+ *\r
+ */\r
+ IOT_TASKPOOL_NO_MEMORY,\r
+\r
+ /**\r
+ * @brief Task pool operation failed because of an invalid parameter.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_setmaxthreads\r
+ * - @ref taskpool_function_createrecyclablejob\r
+ * - @ref taskpool_function_destroyrecyclablejob\r
+ * - @ref taskpool_function_recyclejob\r
+ * - @ref taskpool_function_schedule\r
+ * - @ref taskpool_function_scheduledeferred\r
+ * - @ref taskpool_function_getstatus\r
+ * - @ref taskpool_function_trycancel\r
+ *\r
+ */\r
+ IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS,\r
+\r
+ /**\r
+ * @brief Task pool cancellation failed.\r
+ *\r
+ * Functions that may return this value:\r
+ * - @ref taskpool_function_trycancel\r
+ *\r
+ */\r
+ IOT_TASKPOOL_CANCEL_FAILED,\r
+} IotTaskPoolError_t;\r
+\r
+/**\r
+ * @enums{taskpool,Task pool library}\r
+ */\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_enums\r
+ * @brief Status codes of [task pool Job](@ref IotTaskPoolJob_t).\r
+ *\r
+ */\r
+typedef enum IotTaskPoolJobStatus\r
+{\r
+ /**\r
+ * @brief Job is ready to be scheduled.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_READY = 0,\r
+\r
+ /**\r
+ * @brief Job has been queued for execution.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_SCHEDULED,\r
+\r
+ /**\r
+ * @brief Job has been scheduled for deferred execution.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_DEFERRED,\r
+\r
+ /**\r
+ * @brief Job is executing.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_COMPLETED,\r
+\r
+ /**\r
+ * @brief Job has been canceled before executing.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_CANCELED,\r
+\r
+ /**\r
+ * @brief Job status is undefined.\r
+ *\r
+ */\r
+ IOT_TASKPOOL_STATUS_UNDEFINED,\r
+} IotTaskPoolJobStatus_t;\r
+\r
+/*------------------------- Task pool types and handles --------------------------*/\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_handles\r
+ * @brief Opaque handle of a Task Pool instance.\r
+ *\r
+ * This type identifies a Task Pool instance, which is valid after a successful call\r
+ * to @ref taskpool_function_createsystemtaskpool or @ref taskpool_function_create. A\r
+ * variable of this type is passed as the first\r
+ * argument to [Task Pool library functions](@ref taskpool_functions) to identify which\r
+ * task pool that function acts on.\r
+ *\r
+ * A call to @ref taskpool_function_destroy makes a task pool handle invalid. Once\r
+ * @ref taskpool_function_destroy returns, the task handle should no longer\r
+ * be used.\r
+ *\r
+ * @initializer{IotTaskPool_t,IOT_TASKPOOL_INITIALIZER}\r
+ */\r
+typedef struct _taskPool * IotTaskPool_t;\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_structs\r
+ * @brief The job storage data structure provides the storage for a statically allocated Task Pool Job instance.\r
+ *\r
+ * @warning This is a system-level data type that should not be modified or used directly in any application.\r
+ * @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.\r
+ *\r
+ */\r
+typedef struct IotTaskPoolJobStorage\r
+{\r
+ IotLink_t link; /**< @brief Placeholder. */\r
+ void * dummy2; /**< @brief Placeholder. */\r
+ void * dummy3; /**< @brief Placeholder. */\r
+ uint32_t dummy4; /**< @brief Placeholder. */\r
+ IotTaskPoolJobStatus_t status; /**< @brief Placeholder. */\r
+} IotTaskPoolJobStorage_t;\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_handles\r
+ * @brief Opaque handle of a Task Pool Job.\r
+ * \r
+ * This type identifies a Task Pool Job instance, which is valid after a successful call\r
+ * to @ref taskpool_function_createjob or @ref taskpool_function_createrecyclablejob.\r
+ *\r
+ * A call to @ref taskpool_function_recyclejob or @ref taskpool_function_destroyrecyclablejob makes a \r
+ * task pool job handle invalid. Once @ref taskpool_function_recyclejob or \r
+ * @ref taskpool_function_destroyrecyclablejob returns, the task job handle should no longer be used.\r
+ *\r
+ * @initializer{IotTaskPoolJob_t,IOT_TASKPOOL_JOB_INITIALIZER}\r
+ *\r
+ */\r
+typedef struct _taskPoolJob * IotTaskPoolJob_t;\r
+\r
+/*------------------------- Task pool parameter structs --------------------------*/\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_functionpointers\r
+ * @brief Callback type for a user callback.\r
+ *\r
+ * This type identifies the user callback signature to execute a task pool job. This callback will be invoked\r
+ * by the task pool threads with the `pUserContext` parameter, as specified by the user when\r
+ * calling @ref IotTaskPool_Schedule.\r
+ *\r
+ */\r
+typedef void ( * IotTaskPoolRoutine_t )( IotTaskPool_t pTaskPool,\r
+ IotTaskPoolJob_t pJob,\r
+ void * pUserContext );\r
+\r
+/**\r
+ * @ingroup taskpool_datatypes_paramstructs\r
+ * @brief Initialization information to create one task pool instance.\r
+ *\r
+ * @paramfor @ref taskpool_function_createsystemtaskpool @ref taskpool_function_create.\r
+ *\r
+ * Passed as an argument to @ref taskpool_function_create.\r
+ *\r
+ * @initializer{IotTaskPoolInfo_t,IOT_TASKPOOL_INFO_INITIALIZER}\r
+ */\r
+typedef struct IotTaskPoolInfo\r
+{\r
+ /**\r
+ * @brief Specifies the operating parameters for a task pool.\r
+ *\r
+ * @attention #IotTaskPoolInfo_t.minThreads <b>MUST</b> be at least 1.\r
+ * #IotTaskPoolInfo_t.maxThreads <b>MUST</b> be greater or equal to #IotTaskPoolInfo_t.minThreads.\r
+ * If the minimum number of threads is same as the maximum, then the task pool will not try and grow the\r
+ * number of worker threads at run time.\r
+ */\r
+\r
+ uint32_t minThreads; /**< @brief Minimum number of threads in a task pool. These threads will be created when the task pool is first created with @ref taskpool_function_create. */\r
+ uint32_t maxThreads; /**< @brief Maximum number of threads in a task pool. A task pool may try and grow the number of active threads up to #IotTaskPoolInfo_t.maxThreads. */\r
+ uint32_t stackSize; /**< @brief Stack size for every task pool thread. The stack size for each thread is fixed after the task pool is created and cannot be changed. */\r
+ int32_t priority; /**< @brief priority for every task pool thread. The priority for each thread is fixed after the task pool is created and cannot be changed. */\r
+} IotTaskPoolInfo_t;\r
+\r
+/*------------------------- TASKPOOL defined constants --------------------------*/\r
+\r
+/**\r
+ * @constantspage{taskpool,task pool library}\r
+ *\r
+ * @section taskpool_constants_initializers Task pool Initializers\r
+ * @brief Provides default values for initializing the data types of the task pool library.\r
+ *\r
+ * @snippet this define_taskpool_initializers\r
+ *\r
+ * All user-facing data types of the task pool library can be initialized using\r
+ * one of the following.\r
+ *\r
+ * @warning Failure to initialize a task pool data type with the appropriate initializer\r
+ * may result in a runtime error!\r
+ * @note The initializers may change at any time in future versions, but their\r
+ * names will remain the same.\r
+ *\r
+ * <b>Example</b>\r
+ * @code{c}\r
+ *\r
+ * IotTaskPool_t * pTaskPool;\r
+ *\r
+ * const IotTaskPoolInfo_t tpInfo = IOT_TASKPOOL_INFO_INITIALIZER_LARGE;\r
+ *\r
+ * IotTaskPoolError_t error = IotTaskPool_Create( &tpInfo, &pTaskPool );\r
+ *\r
+ * // Use the task pool\r
+ * // ...\r
+ *\r
+ * @endcode\r
+ *\r
+ */\r
+/* @[define_taskpool_initializers] */\r
+/** @brief Initializer for a small #IotTaskPoolInfo_t. */\r
+#define IOT_TASKPOOL_INFO_INITIALIZER_SMALL { .minThreads = 1, .maxThreads = 1, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } \r
+/** @brief Initializer for a medium #IotTaskPoolInfo_t. */\r
+#define IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM { .minThreads = 1, .maxThreads = 2, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } \r
+/** @brief Initializer for a large #IotTaskPoolInfo_t. */\r
+#define IOT_TASKPOOL_INFO_INITIALIZER_LARGE { .minThreads = 2, .maxThreads = 3, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } \r
+/** @brief Initializer for a very large #IotTaskPoolInfo_t. */\r
+#define IOT_TASKPOOL_INFO_INITIALIZER_XLARGE { .minThreads = 2, .maxThreads = 4, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY } \r
+/** @brief Initializer for a typical #IotTaskPoolInfo_t. */\r
+#define IOT_TASKPOOL_INFO_INITIALIZER IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM\r
+/** @brief Initializer for a #IotTaskPool_t. */\r
+#define IOT_TASKPOOL_INITIALIZER NULL \r
+/** @brief Initializer for a #IotTaskPoolJobStorage_t. */\r
+#define IOT_TASKPOOL_JOB_STORAGE_INITIALIZER { { NULL, NULL }, NULL, NULL, 0, IOT_TASKPOOL_STATUS_UNDEFINED } \r
+/** @brief Initializer for a #IotTaskPoolJob_t. */\r
+#define IOT_TASKPOOL_JOB_INITIALIZER NULL \r
+/* @[define_taskpool_initializers] */\r
+\r
+/**\r
+ * @brief Flag for scheduling a job to execute immediately, even if the maximum number of threads in the\r
+ * task pool was reached already.\r
+ *\r
+ * @warning This flag may cause the task pool to create a worker to serve the job immediately, and\r
+ * therefore using this flag may incur in additional memory usage and potentially fail scheduling the job.\r
+ */\r
+#define IOT_TASKPOOL_JOB_HIGH_PRIORITY ( ( uint32_t ) 0x00000001 )\r
+\r
+/**\r
+ * @brief Allows the use of the handle to the system task pool.\r
+ *\r
+ * @warning The task pool handle is not valid unless @ref IotTaskPool_CreateSystemTaskPool is\r
+ * called before the handle is used.\r
+ */\r
+#define IOT_SYSTEM_TASKPOOL ( IotTaskPool_GetSystemTaskPool() )\r
+\r
+#endif /* ifndef IOT_TASKPOOL_TYPES_H_ */\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+/**\r
+ * @file iot_taskpool.c\r
+ * @brief Implements the task pool functions in iot_taskpool.h\r
+ */\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+\r
+/* Platform layer includes. */\r
+#include "platform/iot_threads.h"\r
+#include "platform/iot_clock.h"\r
+\r
+/* Task pool internal include. */\r
+#include "private/iot_taskpool_internal.h"\r
+\r
+/**\r
+ * @brief Enter a critical section by disabling interrupts.\r
+ *\r
+ */\r
+#define TASKPOOL_ENTER_CRITICAL() taskENTER_CRITICAL()\r
+\r
+/**\r
+ * @brief Enter a critical section by disabling interrupts.\r
+ *\r
+ */\r
+#define TASKPOOL_ENTER_CRITICAL_FROM_ISR() taskENTER_CRITICAL_FROM_ISR()\r
+\r
+/**\r
+ * @brief Exit a critical section by re-enabling interrupts.\r
+ *\r
+ */\r
+#define TASKPOOL_EXIT_CRITICAL() taskEXIT_CRITICAL()\r
+\r
+/**\r
+ * @brief Exit a critical section by re-enabling interrupts.\r
+ *\r
+ */\r
+#define TASKPOOL_EXIT_CRITICAL_FROM_ISR( x ) taskEXIT_CRITICAL_FROM_ISR( x )\r
+\r
+/**\r
+ * @brief Maximum semaphore value for wait operations.\r
+ */\r
+#define TASKPOOL_MAX_SEM_VALUE 0xFFFF\r
+\r
+/**\r
+ * @brief Reschedule delay in milliseconds for deferred jobs.\r
+ */\r
+#define TASKPOOL_JOB_RESCHEDULE_DELAY_MS ( 10ULL )\r
+\r
+/* ---------------------------------------------------------------------------------- */\r
+\r
+/**\r
+ * Doxygen should ignore this section.\r
+ *\r
+ * @brief The system task pool handle for all libraries to use.\r
+ * User application can use the system task pool as well knowing that the usage will be shared with\r
+ * the system libraries as well. The system task pool needs to be initialized before any library is used or\r
+ * before any code that posts jobs to the task pool runs.\r
+ */\r
+_taskPool_t _IotSystemTaskPool = { .dispatchQueue = IOT_DEQUEUE_INITIALIZER };\r
+\r
+/* -------------- Convenience functions to create/recycle/destroy jobs -------------- */\r
+\r
+/**\r
+ * @brief Initializes one instance of a Task pool cache.\r
+ *\r
+ * @param[in] pCache The pre-allocated instance of the cache to initialize.\r
+ */\r
+static void _initJobsCache( _taskPoolCache_t * const pCache );\r
+\r
+/**\r
+ * @brief Initialize a job.\r
+ *\r
+ * @param[in] pJob The job to initialize.\r
+ * @param[in] userCallback The user callback for the job.\r
+ * @param[in] pUserContext The context tp be passed to the callback.\r
+ * @param[in] isStatic A flag to indicate whether the job is statically or synamically allocated.\r
+ */\r
+static void _initializeJob( _taskPoolJob_t * const pJob,\r
+ IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ bool isStatic );\r
+\r
+/**\r
+ * @brief Extracts and initializes one instance of a job from the cache or, if there is none available, it allocates and initialized a new one.\r
+ *\r
+ * @param[in] pCache The instance of the cache to extract the job from.\r
+ */\r
+static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache );\r
+\r
+/**\r
+ * Recycles one instance of a job into the cache or, if the cache is full, it destroys it.\r
+ *\r
+ * @param[in] pCache The instance of the cache to recycle the job into.\r
+ * @param[in] pJob The job to recycle.\r
+ *\r
+ */\r
+static void _recycleJob( _taskPoolCache_t * const pCache,\r
+ _taskPoolJob_t * const pJob );\r
+\r
+/**\r
+ * Destroys one instance of a job.\r
+ *\r
+ * @param[in] pJob The job to destroy.\r
+ *\r
+ */\r
+static void _destroyJob( _taskPoolJob_t * const pJob );\r
+\r
+/* -------------- The worker thread procedure for a task pool thread -------------- */\r
+\r
+/**\r
+ * The procedure for a task pool worker thread.\r
+ *\r
+ * @param[in] pUserContext The user context.\r
+ *\r
+ */\r
+static void _taskPoolWorker( void * pUserContext );\r
+\r
+/* -------------- Convenience functions to handle timer events -------------- */\r
+\r
+/**\r
+ * Comparer for the time list.\r
+ *\r
+ * param[in] pTimerEventLink1 The link to the first timer event.\r
+ * param[in] pTimerEventLink1 The link to the first timer event.\r
+ */\r
+static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1,\r
+ const IotLink_t * const pTimerEventLink2 );\r
+\r
+/**\r
+ * Reschedules the timer for handling deferred jobs to the next timeout.\r
+ *\r
+ * param[in] timer The timer to reschedule.\r
+ * param[in] pFirstTimerEvent The timer event that carries the timeout and job inforamtion.\r
+ */\r
+static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,\r
+ _taskPoolTimerEvent_t * const pFirstTimerEvent );\r
+\r
+/**\r
+ * The task pool timer procedure for scheduling deferred jobs.\r
+ *\r
+ * param[in] timer The timer to handle.\r
+ */\r
+static void _timerThread( TimerHandle_t xTimer );\r
+\r
+/* -------------- Convenience functions to create/initialize/destroy the task pool -------------- */\r
+\r
+/**\r
+ * Parameter validation for a task pool initialization.\r
+ *\r
+ * @param[in] pInfo The initialization information for the task pool.\r
+ *\r
+ */\r
+static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo );\r
+\r
+/**\r
+ * Initializes a pre-allocated instance of a task pool.\r
+ *\r
+ * @param[in] pInfo The initialization information for the task pool.\r
+ * @param[in] pTaskPool The pre-allocated instance of the task pool to initialize.\r
+ *\r
+ */\r
+static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo,\r
+ _taskPool_t * const pTaskPool );\r
+\r
+/**\r
+ * Initializes a pre-allocated instance of a task pool.\r
+ *\r
+ * @param[in] pInfo The initialization information for the task pool.\r
+ * @param[out] pTaskPool A pointer to the task pool data structure to initialize.\r
+ *\r
+ */\r
+static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo,\r
+ _taskPool_t * const pTaskPool );\r
+\r
+/**\r
+ * Destroys one instance of a task pool.\r
+ *\r
+ * @param[in] pTaskPool The task pool to destroy.\r
+ *\r
+ */\r
+static void _destroyTaskPool( _taskPool_t * const pTaskPool );\r
+\r
+/**\r
+ * Check for the exit condition.\r
+ *\r
+ * @param[in] pTaskPool The task pool to destroy.\r
+ *\r
+ */\r
+static bool _IsShutdownStarted( const _taskPool_t * const pTaskPool );\r
+\r
+/**\r
+ * Set the exit condition.\r
+ *\r
+ * @param[in] pTaskPool The task pool to destroy.\r
+ * @param[in] threads The number of threads active in the task pool at shutdown time.\r
+ *\r
+ */\r
+static void _signalShutdown( _taskPool_t * const pTaskPool,\r
+ uint32_t threads );\r
+\r
+/**\r
+ * Places a job in the dispatch queue.\r
+ *\r
+ * @param[in] pTaskPool The task pool to scheduel the job with.\r
+ * @param[in] pJob The job to schedule.\r
+ * @param[in] flags The job flags.\r
+ *\r
+ */\r
+static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
+ _taskPoolJob_t * const pJob,\r
+ uint32_t flags );\r
+\r
+/**\r
+ * Matches a deferred job in the timer queue with its timer event wrapper.\r
+ *\r
+ * @param[in] pLink A pointer to the timer event link in the timer queue.\r
+ * @param[in] pMatch A pointer to the job to match.\r
+ *\r
+ */\r
+static bool _matchJobByPointer( const IotLink_t * const pLink,\r
+ void * pMatch );\r
+\r
+/**\r
+ * Tries to cancel a job.\r
+ *\r
+ * @param[in] pTaskPool The task pool to cancel an operation against.\r
+ * @param[in] pJob The job to cancel.\r
+ * @param[out] pStatus The status of the job at the time of cancellation.\r
+ *\r
+ */\r
+static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,\r
+ _taskPoolJob_t * const pJob,\r
+ IotTaskPoolJobStatus_t * const pStatus );\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+IotTaskPool_t IotTaskPool_GetSystemTaskPool( void )\r
+{\r
+ return &_IotSystemTaskPool;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );\r
+\r
+ /* Create the system task pool pool. */\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, &_IotSystemTaskPool ) );\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo,\r
+ IotTaskPool_t * const pTaskPool )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTempTaskPool = NULL;\r
+\r
+ /* Verify that the task pool storage is valid. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );\r
+\r
+ /* Allocate the memory for the task pool */\r
+ pTempTaskPool = ( _taskPool_t * ) IotTaskPool_MallocTaskPool( sizeof( _taskPool_t ) );\r
+\r
+ if( pTempTaskPool == NULL )\r
+ {\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ memset( pTempTaskPool, 0x00, sizeof( _taskPool_t ) );\r
+\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, pTempTaskPool ) );\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP();\r
+\r
+ if( TASKPOOL_FAILED( status ) )\r
+ {\r
+ if( pTempTaskPool != NULL )\r
+ {\r
+ IotTaskPool_FreeTaskPool( pTempTaskPool );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *pTaskPool = pTempTaskPool;\r
+ }\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP_END();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ uint32_t count;\r
+ bool completeShutdown = true;\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Track how many threads the task pool owns. */\r
+ uint32_t activeThreads;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
+\r
+ /* Destroying the task pool should be safe, and therefore we will grab the task pool lock.\r
+ * No worker thread or application thread should access any data structure\r
+ * in the task pool while the task pool is being destroyed. */\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ IotLink_t * pItemLink;\r
+\r
+ /* Record how many active threads in the task pool. */\r
+ activeThreads = pTaskPool->activeThreads;\r
+\r
+ /* Destroying a Task pool happens in six (6) stages: First, (1) we clear the job queue and (2) the timer queue.\r
+ * Then (3) we clear the jobs cache. We will then (4) wait for all worker threads to signal exit,\r
+ * before (5) setting the exit condition and wake up all active worker threads. Finally (6) destroying\r
+ * all task pool data structures and release the associated memory.\r
+ */\r
+\r
+ /* (1) Clear the job queue. */\r
+ do\r
+ {\r
+ pItemLink = NULL;\r
+\r
+ pItemLink = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
+\r
+ if( pItemLink != NULL )\r
+ {\r
+ _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );\r
+\r
+ _destroyJob( pJob );\r
+ }\r
+ } while( pItemLink );\r
+\r
+ /* (2) Clear the timer queue. */\r
+ {\r
+ _taskPoolTimerEvent_t * pTimerEvent;\r
+\r
+ /* A deferred job may have fired already. Since deferred jobs will go through the same mutex\r
+ * the shutdown sequence is holding at this stage, there is no risk for race conditions. Yet, we\r
+ * need to let the deferred job to destroy the task pool. */\r
+\r
+ pItemLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
+\r
+ if( pItemLink != NULL )\r
+ {\r
+ TickType_t now = xTaskGetTickCount();\r
+\r
+ pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );\r
+\r
+ if( pTimerEvent->expirationTime <= now )\r
+ {\r
+ IotLogDebug( "Shutdown will be deferred to the timer thread" );\r
+\r
+ /* Timer may have fired already! Let the timer thread destroy\r
+ * complete the taskpool destruction sequence. */\r
+ completeShutdown = false;\r
+ }\r
+\r
+ /* Remove all timers from the timeout list. */\r
+ for( ; ; )\r
+ {\r
+ pItemLink = IotListDouble_RemoveHead( &pTaskPool->timerEventsList );\r
+\r
+ if( pItemLink == NULL )\r
+ {\r
+ break;\r
+ }\r
+\r
+ pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );\r
+\r
+ _destroyJob( pTimerEvent->job );\r
+\r
+ IotTaskPool_FreeTimerEvent( pTimerEvent );\r
+ }\r
+ }\r
+ }\r
+\r
+ /* (3) Clear the job cache. */\r
+ do\r
+ {\r
+ pItemLink = NULL;\r
+\r
+ pItemLink = IotListDouble_RemoveHead( &pTaskPool->jobsCache.freeList );\r
+\r
+ if( pItemLink != NULL )\r
+ {\r
+ _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );\r
+\r
+ _destroyJob( pJob );\r
+ }\r
+ } while( pItemLink );\r
+\r
+ /* (4) Set the exit condition. */\r
+ _signalShutdown( pTaskPool, activeThreads );\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ /* (5) Wait for all active threads to reach the end of their life-span. */\r
+ for( count = 0; count < activeThreads; ++count )\r
+ {\r
+ xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );\r
+ }\r
+\r
+ IotTaskPool_Assert( uxSemaphoreGetCount( pTaskPool->startStopSignal ) == 0 );\r
+ IotTaskPool_Assert( pTaskPool->activeThreads == 0 );\r
+\r
+ /* (6) Destroy all signaling objects. */\r
+ if( completeShutdown == true )\r
+ {\r
+ _destroyTaskPool( pTaskPool );\r
+\r
+ /* Do not free the system task pool which is statically allocated. */\r
+ if( pTaskPool != &_IotSystemTaskPool )\r
+ {\r
+ IotTaskPool_FreeTaskPool( pTaskPool );\r
+ }\r
+ }\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPoolHandle,\r
+ uint32_t maxThreads )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
+ TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( maxThreads < 1UL );\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ IotTaskPoolJobStorage_t * const pJobStorage,\r
+ IotTaskPoolJob_t * const ppJob )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobStorage );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
+\r
+ /* Build a job around the user-provided storage. */\r
+ _initializeJob( ( _taskPoolJob_t * ) pJobStorage, userCallback, pUserContext, true );\r
+\r
+ *ppJob = ( IotTaskPoolJob_t ) pJobStorage;\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ IotTaskPoolJob_t * const ppJob )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPoolJob_t * pTempJob = NULL;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ /* Bail out early if this task pool is shutting down. */\r
+ pTempJob = _fetchOrAllocateJob( &pTaskPool->jobsCache );\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ if( pTempJob == NULL )\r
+ {\r
+ IotLogInfo( "Failed to allocate a job." );\r
+\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ _initializeJob( pTempJob, userCallback, pUserContext, false );\r
+\r
+ *ppJob = pTempJob;\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t pJobHandle )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPoolJob_t * pJob = ( _taskPoolJob_t * ) pJobHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobHandle );\r
+\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
+\r
+ _destroyJob( pJob );\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t pJob )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
+\r
+ _recycleJob( &pTaskPool->jobsCache, pJob );\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t pJob,\r
+ uint32_t flags )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
+ TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( ( flags != 0UL ) && ( flags != IOT_TASKPOOL_JOB_HIGH_PRIORITY ) );\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ _scheduleInternal( pTaskPool, pJob, flags );\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t job,\r
+ uint32_t timeMs )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
+\r
+ if( timeMs == 0UL )\r
+ {\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IotTaskPool_Schedule( pTaskPool, job, 0 ) );\r
+ }\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ _taskPoolTimerEvent_t * pTimerEvent = IotTaskPool_MallocTimerEvent( sizeof( _taskPoolTimerEvent_t ) );\r
+\r
+ if( pTimerEvent == NULL )\r
+ {\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ IotLink_t * pTimerEventLink;\r
+\r
+ TickType_t now = xTaskGetTickCount();\r
+\r
+ pTimerEvent->link.pNext = NULL;\r
+ pTimerEvent->link.pPrevious = NULL;\r
+ pTimerEvent->expirationTime = now + pdMS_TO_TICKS( timeMs );\r
+ pTimerEvent->job = job;\r
+\r
+ /* Append the timer event to the timer list. */\r
+ IotListDouble_InsertSorted( &pTaskPool->timerEventsList, &pTimerEvent->link, _timerEventCompare );\r
+\r
+ /* Update the job status to 'scheduled'. */\r
+ job->status = IOT_TASKPOOL_STATUS_DEFERRED;\r
+\r
+ /* Peek the first event in the timer event list. There must be at least one,\r
+ * since we just inserted it. */\r
+ pTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
+ IotTaskPool_Assert( pTimerEventLink != NULL );\r
+\r
+ /* If the event we inserted is at the front of the queue, then\r
+ * we need to reschedule the underlying timer. */\r
+ if( pTimerEventLink == &pTimerEvent->link )\r
+ {\r
+ pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link );\r
+\r
+ _rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );\r
+ }\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t job,\r
+ IotTaskPoolJobStatus_t * const pStatus )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );\r
+ *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ *pStatus = job->status;\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,\r
+ IotTaskPoolJob_t job,\r
+ IotTaskPoolJobStatus_t * const pStatus )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+\r
+ /* Parameter checking. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
+\r
+ if( pStatus != NULL )\r
+ {\r
+ *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
+ }\r
+\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ status = _tryCancelInternal( pTaskPool, job, pStatus );\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t pJob )\r
+{\r
+ return ( IotTaskPoolJobStorage_t * ) pJob;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+const char * IotTaskPool_strerror( IotTaskPoolError_t status )\r
+{\r
+ const char * pMessage = NULL;\r
+\r
+ switch( status )\r
+ {\r
+ case IOT_TASKPOOL_SUCCESS:\r
+ pMessage = "SUCCESS";\r
+ break;\r
+\r
+ case IOT_TASKPOOL_BAD_PARAMETER:\r
+ pMessage = "BAD PARAMETER";\r
+ break;\r
+\r
+ case IOT_TASKPOOL_ILLEGAL_OPERATION:\r
+ pMessage = "ILLEGAL OPERATION";\r
+ break;\r
+\r
+ case IOT_TASKPOOL_NO_MEMORY:\r
+ pMessage = "NO MEMORY";\r
+ break;\r
+\r
+ case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS:\r
+ pMessage = "SHUTDOWN IN PROGRESS";\r
+ break;\r
+\r
+ case IOT_TASKPOOL_CANCEL_FAILED:\r
+ pMessage = "CANCEL FAILED";\r
+ break;\r
+\r
+ default:\r
+ pMessage = "INVALID STATUS";\r
+ break;\r
+ }\r
+\r
+ return pMessage;\r
+}\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+/* ---------------------------------------------------------------------------------------------- */\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Check input values for consistency. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pInfo );\r
+ TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads > pInfo->maxThreads );\r
+ TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads < 1UL );\r
+ TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->maxThreads < 1UL );\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo,\r
+ _taskPool_t * const pTaskPool )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ bool semStartStopInit = false;\r
+ bool semDispatchInit = false;\r
+\r
+ /* Initialize a job data structures that require no de-initialization.\r
+ * All other data structures carry a value of 'NULL' before initailization.\r
+ */\r
+ IotDeQueue_Create( &pTaskPool->dispatchQueue );\r
+ IotListDouble_Create( &pTaskPool->timerEventsList );\r
+\r
+ _initJobsCache( &pTaskPool->jobsCache );\r
+\r
+ /* Initialize the semaphore to ensure all threads have started. */\r
+ pTaskPool->startStopSignal = xSemaphoreCreateCountingStatic( pInfo->minThreads, 0, &pTaskPool->startStopSignalBuffer );\r
+\r
+ if( pTaskPool->startStopSignal != NULL )\r
+ {\r
+ semStartStopInit = true;\r
+\r
+ /* Initialize the semaphore for waiting for incoming work. */\r
+ pTaskPool->dispatchSignal = xSemaphoreCreateCountingStatic( TASKPOOL_MAX_SEM_VALUE, 0, &pTaskPool->dispatchSignalBuffer );\r
+\r
+ if( pTaskPool->dispatchSignal != NULL )\r
+ {\r
+ semDispatchInit = true;\r
+ }\r
+ else\r
+ {\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP();\r
+\r
+ if( TASKPOOL_FAILED( status ) )\r
+ {\r
+ if( semStartStopInit )\r
+ {\r
+ vSemaphoreDelete( &pTaskPool->startStopSignal );\r
+ }\r
+\r
+ if( semDispatchInit )\r
+ {\r
+ vSemaphoreDelete( &pTaskPool->dispatchSignal );\r
+ }\r
+ }\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP_END();\r
+}\r
+\r
+static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo,\r
+ _taskPool_t * const pTaskPool )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ uint32_t count;\r
+ uint32_t threadsCreated = 0;\r
+\r
+ /* Check input values for consistency. */\r
+ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
+\r
+ /* Zero out all data structures. */\r
+ memset( ( void * ) pTaskPool, 0x00, sizeof( _taskPool_t ) );\r
+\r
+ /* Initialize all internal data structure prior to creating all threads. */\r
+ TASKPOOL_ON_ERROR_GOTO_CLEANUP( _initTaskPoolControlStructures( pInfo, pTaskPool ) );\r
+\r
+ /* Create the timer mutex for a new connection. */\r
+ pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerThread );\r
+\r
+ if( pTaskPool->timer == NULL )\r
+ {\r
+ IotLogError( "Failed to create timer for task pool." );\r
+\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ /* The task pool will initialize the minimum number of threads reqeusted by the user upon start. */\r
+ /* When a thread is created, it will signal a semaphore to signify that it is about to wait on incoming */\r
+ /* jobs. A thread can be woken up for exit or for new jobs only at that point in time. */\r
+ /* The exit condition is setting the maximum number of threads to 0. */\r
+\r
+ /* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */\r
+ for( ; threadsCreated < pInfo->minThreads; )\r
+ {\r
+ TaskHandle_t task = NULL;\r
+\r
+ BaseType_t res = xTaskCreate( _taskPoolWorker,\r
+ NULL,\r
+ pInfo->stackSize,\r
+ pTaskPool,\r
+ pInfo->priority,\r
+ &task );\r
+\r
+ /* Create one thread. */\r
+ if( res == pdFALSE )\r
+ {\r
+ IotLogError( "Could not create worker thread! Exiting..." );\r
+\r
+ /* If creating one thread fails, set error condition and exit the loop. */\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
+ }\r
+\r
+ /* Upon successful thread creation, increase the number of active threads. */\r
+ pTaskPool->activeThreads++;\r
+ IotTaskPool_Assert( task != NULL );\r
+\r
+ ++threadsCreated;\r
+ }\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP();\r
+\r
+ /* Wait for threads to be ready to wait on the condition, so that threads are actually able to receive messages. */\r
+ for( count = 0; count < threadsCreated; ++count )\r
+ {\r
+ xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );\r
+ }\r
+\r
+ /* In case of failure, wait on the created threads to exit. */\r
+ if( TASKPOOL_FAILED( status ) )\r
+ {\r
+ /* Set the exit condition for the newly created threads. */\r
+ _signalShutdown( pTaskPool, threadsCreated );\r
+\r
+ /* Signal all threads to exit. */\r
+ for( count = 0; count < threadsCreated; ++count )\r
+ {\r
+ xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );\r
+ }\r
+\r
+ _destroyTaskPool( pTaskPool );\r
+ }\r
+\r
+ pTaskPool->running = true;\r
+\r
+ TASKPOOL_FUNCTION_CLEANUP_END();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _destroyTaskPool( _taskPool_t * const pTaskPool )\r
+{\r
+ if( pTaskPool->timer != NULL )\r
+ {\r
+ xTimerDelete( pTaskPool->timer, 0 );\r
+ }\r
+\r
+ if( pTaskPool->dispatchSignal != NULL )\r
+ {\r
+ vSemaphoreDelete( pTaskPool->dispatchSignal );\r
+ }\r
+\r
+ if( pTaskPool->startStopSignal != NULL )\r
+ {\r
+ vSemaphoreDelete( pTaskPool->startStopSignal );\r
+ }\r
+}\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+static void _taskPoolWorker( void * pUserContext )\r
+{\r
+ IotTaskPool_Assert( pUserContext != NULL );\r
+\r
+ IotTaskPoolRoutine_t userCallback = NULL;\r
+ bool running = true;\r
+\r
+ /* Extract pTaskPool pointer from context. */\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) pUserContext;\r
+\r
+ /* Signal that this worker completed initialization and it is ready to receive notifications. */\r
+ ( void ) xSemaphoreGive( pTaskPool->startStopSignal );\r
+\r
+ /* OUTER LOOP: it controls the lifetiem of the worker thread: exit condition for a worker thread\r
+ * is setting maxThreads to zero. A worker thread is running until the maximum number of allowed\r
+ * threads is not zero and the active threads are less than the maximum number of allowed threads.\r
+ */\r
+ do\r
+ {\r
+ IotLink_t * pFirst = NULL;\r
+ _taskPoolJob_t * pJob = NULL;\r
+\r
+ /* Wait on incoming notifications... */\r
+ xSemaphoreTake( pTaskPool->dispatchSignal, portMAX_DELAY );\r
+\r
+ /* Acquire the lock to check the exit condition, and release the lock if the exit condition is verified,\r
+ * or before waiting for incoming notifications.\r
+ */\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ /* If the exit condition is verified, update the number of active threads and exit the loop. */\r
+ if( _IsShutdownStarted( pTaskPool ) )\r
+ {\r
+ IotLogDebug( "Worker thread exiting because exit condition was set." );\r
+\r
+ /* Decrease the number of active threads. */\r
+ pTaskPool->activeThreads--;\r
+\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ /* Signal that this worker is exiting. */\r
+ xSemaphoreGive( pTaskPool->startStopSignal );\r
+\r
+ /* On shutdown, abandon the OUTER LOOP immediately. */\r
+ break;\r
+ }\r
+\r
+ /* Dequeue the first job in FIFO order. */\r
+ pFirst = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
+\r
+ /* If there is indeed a job, then update status under lock, and release the lock before processing the job. */\r
+ if( pFirst != NULL )\r
+ {\r
+ /* Extract the job from its link. */\r
+ pJob = IotLink_Container( _taskPoolJob_t, pFirst, link );\r
+\r
+ /* Update status to 'executing'. */\r
+ pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;\r
+ userCallback = pJob->userCallback;\r
+ }\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ /* INNER LOOP: it controls the execution of jobs: the exit condition is the lack of a job to execute. */\r
+ while( pJob != NULL )\r
+ {\r
+ /* Process the job by invoking the associated callback with the user context.\r
+ * This task pool thread will not be available until the user callback returns.\r
+ */\r
+ {\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
+ IotTaskPool_Assert( userCallback != NULL );\r
+\r
+ userCallback( pTaskPool, pJob, pJob->pUserContext );\r
+\r
+ /* This job is finished, clear its pointer. */\r
+ pJob = NULL;\r
+ userCallback = NULL;\r
+\r
+ /* If this thread exceeded the quota, then let it terminate. */\r
+ if( running == false )\r
+ {\r
+ /* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Acquire the lock before updating the job status. */\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ /* Try and dequeue the next job in the dispatch queue. */\r
+ IotLink_t * pItem = NULL;\r
+\r
+ /* Dequeue the next job from the dispatch queue. */\r
+ pItem = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
+\r
+ /* If there is no job left in the dispatch queue, update the worker status and leave. */\r
+ if( pItem == NULL )\r
+ {\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ /* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ pJob = IotLink_Container( _taskPoolJob_t, pItem, link );\r
+\r
+ userCallback = pJob->userCallback;\r
+ }\r
+\r
+ pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+ }\r
+ } while( running == true );\r
+\r
+ vTaskDelete( NULL );\r
+}\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+static void _initJobsCache( _taskPoolCache_t * const pCache )\r
+{\r
+ IotDeQueue_Create( &pCache->freeList );\r
+\r
+ pCache->freeCount = 0;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _initializeJob( _taskPoolJob_t * const pJob,\r
+ IotTaskPoolRoutine_t userCallback,\r
+ void * pUserContext,\r
+ bool isStatic )\r
+{\r
+ pJob->link.pNext = NULL;\r
+ pJob->link.pPrevious = NULL;\r
+ pJob->userCallback = userCallback;\r
+ pJob->pUserContext = pUserContext;\r
+\r
+ if( isStatic )\r
+ {\r
+ pJob->flags = IOT_TASK_POOL_INTERNAL_STATIC;\r
+ pJob->status = IOT_TASKPOOL_STATUS_READY;\r
+ }\r
+ else\r
+ {\r
+ pJob->status = IOT_TASKPOOL_STATUS_READY;\r
+ }\r
+}\r
+\r
+static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache )\r
+{\r
+ _taskPoolJob_t * pJob = NULL;\r
+ IotLink_t * pLink = IotListDouble_RemoveHead( &( pCache->freeList ) );\r
+\r
+ if( pLink != NULL )\r
+ {\r
+ pJob = IotLink_Container( _taskPoolJob_t, pLink, link );\r
+ }\r
+\r
+ /* If there is no available job in the cache, then allocate one. */\r
+ if( pJob == NULL )\r
+ {\r
+ pJob = ( _taskPoolJob_t * ) IotTaskPool_MallocJob( sizeof( _taskPoolJob_t ) );\r
+\r
+ if( pJob != NULL )\r
+ {\r
+ memset( pJob, 0x00, sizeof( _taskPoolJob_t ) );\r
+ }\r
+ else\r
+ {\r
+ /* Log alocation failure for troubleshooting purposes. */\r
+ IotLogInfo( "Failed to allocate job." );\r
+ }\r
+ }\r
+ /* If there was a job in the cache, then make sure we keep the counters up-to-date. */\r
+ else\r
+ {\r
+ IotTaskPool_Assert( pCache->freeCount > 0 );\r
+\r
+ pCache->freeCount--;\r
+ }\r
+\r
+ return pJob;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _recycleJob( _taskPoolCache_t * const pCache,\r
+ _taskPoolJob_t * const pJob )\r
+{\r
+ /* We should never try and recycling a job that is linked into some queue. */\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
+\r
+ /* We will recycle the job if there is space in the cache. */\r
+ if( pCache->freeCount < IOT_TASKPOOL_JOBS_RECYCLE_LIMIT )\r
+ {\r
+ /* Destroy user data, for added safety&security. */\r
+ pJob->userCallback = NULL;\r
+ pJob->pUserContext = NULL;\r
+\r
+ /* Reset the status for added debuggability. */\r
+ pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED;\r
+\r
+ IotListDouble_InsertTail( &pCache->freeList, &pJob->link );\r
+\r
+ pCache->freeCount++;\r
+\r
+ IotTaskPool_Assert( pCache->freeCount >= 1 );\r
+ }\r
+ else\r
+ {\r
+ _destroyJob( pJob );\r
+ }\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _destroyJob( _taskPoolJob_t * const pJob )\r
+{\r
+ /* Destroy user data, for added safety & security. */\r
+ pJob->userCallback = NULL;\r
+ pJob->pUserContext = NULL;\r
+\r
+ /* Reset the status for added debuggability. */\r
+ pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED;\r
+\r
+ /* Only dispose of dynamically allocated jobs. */\r
+ if( ( pJob->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == 0UL )\r
+ {\r
+ IotTaskPool_FreeJob( pJob );\r
+ }\r
+}\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+static bool _IsShutdownStarted( const _taskPool_t * const pTaskPool )\r
+{\r
+ return( pTaskPool->running == false );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _signalShutdown( _taskPool_t * const pTaskPool,\r
+ uint32_t threads )\r
+{\r
+ uint32_t count;\r
+\r
+ /* Set the exit condition. */\r
+ pTaskPool->running = false;\r
+\r
+ /* Broadcast to all active threads to wake-up. Active threads do check the exit condition right after wakein up. */\r
+ for( count = 0; count < threads; ++count )\r
+ {\r
+ ( void ) xSemaphoreGive( pTaskPool->dispatchSignal );\r
+ }\r
+}\r
+\r
+/* ---------------------------------------------------------------------------------------------- */\r
+\r
+static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
+ _taskPoolJob_t * const pJob,\r
+ uint32_t flags )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Update the job status to 'scheduled'. */\r
+ pJob->status = IOT_TASKPOOL_STATUS_SCHEDULED;\r
+\r
+ BaseType_t higherPriorityTaskWoken;\r
+\r
+ /* Append the job to the dispatch queue. */\r
+ IotDeQueue_EnqueueTail( &pTaskPool->dispatchQueue, &pJob->link );\r
+\r
+ /* Signal a worker to pick up the job. */\r
+ ( void ) xSemaphoreGiveFromISR( pTaskPool->dispatchSignal, &higherPriorityTaskWoken );\r
+\r
+ portYIELD_FROM_ISR( higherPriorityTaskWoken );\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP_NOLABEL();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static bool _matchJobByPointer( const IotLink_t * const pLink,\r
+ void * pMatch )\r
+{\r
+ const _taskPoolJob_t * const pJob = ( _taskPoolJob_t * ) pMatch;\r
+\r
+ const _taskPoolTimerEvent_t * const pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link );\r
+\r
+ if( pJob == pTimerEvent->job )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,\r
+ _taskPoolJob_t * const pJob,\r
+ IotTaskPoolJobStatus_t * const pStatus )\r
+{\r
+ TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
+\r
+ bool cancelable = false;\r
+\r
+ /* We can only cancel jobs that are either 'ready' (waiting to be scheduled). 'deferred', or 'scheduled'. */\r
+\r
+ IotTaskPoolJobStatus_t currentStatus = pJob->status;\r
+\r
+ switch( currentStatus )\r
+ {\r
+ case IOT_TASKPOOL_STATUS_READY:\r
+ case IOT_TASKPOOL_STATUS_DEFERRED:\r
+ case IOT_TASKPOOL_STATUS_SCHEDULED:\r
+ case IOT_TASKPOOL_STATUS_CANCELED:\r
+ cancelable = true;\r
+ break;\r
+\r
+ case IOT_TASKPOOL_STATUS_COMPLETED:\r
+ /* Log mesggesong purposes. */\r
+ IotLogWarn( "Attempt to cancel a job that is already executing, or canceled." );\r
+ break;\r
+\r
+ default:\r
+ /* Log mesggesong purposes. */\r
+ IotLogError( "Attempt to cancel a job with an undefined state." );\r
+ break;\r
+ }\r
+\r
+ /* Update the returned status to the current status of the job. */\r
+ if( pStatus != NULL )\r
+ {\r
+ *pStatus = currentStatus;\r
+ }\r
+\r
+ if( cancelable == false )\r
+ {\r
+ TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_CANCEL_FAILED );\r
+ }\r
+ else\r
+ {\r
+ /* Update the status of the job. */\r
+ pJob->status = IOT_TASKPOOL_STATUS_CANCELED;\r
+\r
+ /* If the job is cancelable and its current status is 'scheduled' then unlink it from the dispatch\r
+ * queue and signal any waiting threads. */\r
+ if( currentStatus == IOT_TASKPOOL_STATUS_SCHEDULED )\r
+ {\r
+ /* A scheduled work items must be in the dispatch queue. */\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) );\r
+\r
+ IotDeQueue_Remove( &pJob->link );\r
+ }\r
+\r
+ /* If the job current status is 'deferred' then the job has to be pending\r
+ * in the timeouts queue. */\r
+ else if( currentStatus == IOT_TASKPOOL_STATUS_DEFERRED )\r
+ {\r
+ /* Find the timer event associated with the current job. There MUST be one, hence assert if not. */\r
+ IotLink_t * pTimerEventLink = IotListDouble_FindFirstMatch( &pTaskPool->timerEventsList, NULL, _matchJobByPointer, pJob );\r
+ IotTaskPool_Assert( pTimerEventLink != NULL );\r
+\r
+ if( pTimerEventLink != NULL )\r
+ {\r
+ bool shouldReschedule = false;\r
+\r
+ /* If the job being cancelled was at the head of the timeouts queue, then we need to reschedule the timer\r
+ * with the next job timeout */\r
+ IotLink_t * pHeadLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
+\r
+ if( pHeadLink == pTimerEventLink )\r
+ {\r
+ shouldReschedule = true;\r
+ }\r
+\r
+ /* Remove the timer event associated with the canceled job and free the associated memory. */\r
+ IotListDouble_Remove( pTimerEventLink );\r
+ IotTaskPool_FreeTimerEvent( IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link ) );\r
+\r
+ if( shouldReschedule )\r
+ {\r
+ IotLink_t * pNextTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
+\r
+ if( pNextTimerEventLink != NULL )\r
+ {\r
+ _rescheduleDeferredJobsTimer( pTaskPool->timer, IotLink_Container( _taskPoolTimerEvent_t, pNextTimerEventLink, link ) );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* A cancelable job status should be either 'scheduled' or 'deferrred'. */\r
+ IotTaskPool_Assert( ( currentStatus == IOT_TASKPOOL_STATUS_READY ) || ( currentStatus == IOT_TASKPOOL_STATUS_CANCELED ) );\r
+ }\r
+ }\r
+\r
+ TASKPOOL_NO_FUNCTION_CLEANUP();\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1,\r
+ const IotLink_t * const pTimerEventLink2 )\r
+{\r
+ const _taskPoolTimerEvent_t * const pTimerEvent1 = IotLink_Container( _taskPoolTimerEvent_t,\r
+ pTimerEventLink1,\r
+ link );\r
+ const _taskPoolTimerEvent_t * const pTimerEvent2 = IotLink_Container( _taskPoolTimerEvent_t,\r
+ pTimerEventLink2,\r
+ link );\r
+\r
+ if( pTimerEvent1->expirationTime < pTimerEvent2->expirationTime )\r
+ {\r
+ return -1;\r
+ }\r
+\r
+ if( pTimerEvent1->expirationTime > pTimerEvent2->expirationTime )\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,\r
+ _taskPoolTimerEvent_t * const pFirstTimerEvent )\r
+{\r
+ uint64_t delta = 0;\r
+ TickType_t now = xTaskGetTickCount();\r
+\r
+ if( pFirstTimerEvent->expirationTime > now )\r
+ {\r
+ delta = pFirstTimerEvent->expirationTime - now;\r
+ }\r
+\r
+ if( delta < TASKPOOL_JOB_RESCHEDULE_DELAY_MS )\r
+ {\r
+ delta = TASKPOOL_JOB_RESCHEDULE_DELAY_MS; /* The job will be late... */\r
+ }\r
+\r
+ IotTaskPool_Assert( delta > 0 );\r
+\r
+ if( xTimerChangePeriod( timer, ( uint32_t ) delta, portMAX_DELAY ) == pdFAIL )\r
+ {\r
+ IotLogWarn( "Failed to re-arm timer for task pool" );\r
+ }\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void _timerThread( TimerHandle_t xTimer )\r
+{\r
+ _taskPool_t * pTaskPool = pvTimerGetTimerID( xTimer );\r
+\r
+ IotTaskPool_Assert( pTaskPool );\r
+\r
+ _taskPoolTimerEvent_t * pTimerEvent = NULL;\r
+\r
+ IotLogDebug( "Timer thread started for task pool %p.", pTaskPool );\r
+\r
+ /* Attempt to lock the timer mutex. Return immediately if the mutex cannot be locked.\r
+ * If this mutex cannot be locked it means that another thread is manipulating the\r
+ * timeouts list, and will reset the timer to fire again, although it will be late.\r
+ */\r
+ TASKPOOL_ENTER_CRITICAL();\r
+ {\r
+ /* Check again for shutdown and bail out early in case. */\r
+ if( _IsShutdownStarted( pTaskPool ) )\r
+ {\r
+ TASKPOOL_EXIT_CRITICAL();\r
+\r
+ /* Complete the shutdown sequence. */\r
+ _destroyTaskPool( pTaskPool );\r
+\r
+ return;\r
+ }\r
+\r
+ /* Dispatch all deferred job whose timer expired, then reset the timer for the next\r
+ * job down the line. */\r
+ for( ; ; )\r
+ {\r
+ /* Peek the first event in the timer event list. */\r
+ IotLink_t * pLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
+\r
+ /* Check if the timer misfired for any reason. */\r
+ if( pLink != NULL )\r
+ {\r
+ /* Record the current time. */\r
+ TickType_t now = xTaskGetTickCount();\r
+\r
+ /* Extract the job from its envelope. */\r
+ pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link );\r
+\r
+ /* Check if the first event should be processed now. */\r
+ if( pTimerEvent->expirationTime <= now )\r
+ {\r
+ /* Remove the timer event for immediate processing. */\r
+ IotListDouble_Remove( &( pTimerEvent->link ) );\r
+ }\r
+ else\r
+ {\r
+ /* The first element in the timer queue shouldn't be processed yet.\r
+ * Arm the timer for when it should be processed and leave altogether. */\r
+ _rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );\r
+\r
+ break;\r
+ }\r
+ }\r
+ /* If there are no timer events to process, terminate this thread. */\r
+ else\r
+ {\r
+ IotLogDebug( "No further timer events to process. Exiting timer thread." );\r
+\r
+ break;\r
+ }\r
+\r
+ IotLogDebug( "Scheduling job from timer event." );\r
+\r
+ /* Queue the job associated with the received timer event. */\r
+ ( void ) _scheduleInternal( pTaskPool, pTimerEvent->job, 0 );\r
+\r
+ /* Free the timer event. */\r
+ IotTaskPool_FreeTimerEvent( pTimerEvent );\r
+ }\r
+ }\r
+ TASKPOOL_EXIT_CRITICAL();\r
+}\r
--- /dev/null
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_taskpool_static_memory.c\r
+ * @brief Implementation of task pool static memory functions.\r
+ */\r
+\r
+/* The config header is always included first. */\r
+#include "iot_config.h"\r
+\r
+/* This file should only be compiled if dynamic memory allocation is forbidden. */\r
+#if IOT_STATIC_MEMORY_ONLY == 1\r
+\r
+/* Standard includes. */\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <string.h>\r
+\r
+/* Static memory include. */\r
+#include "private/iot_static_memory.h"\r
+\r
+/* Task pool internal include. */\r
+#include "private/iot_taskpool_internal.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Validate static memory configuration settings. */\r
+#if IOT_TASKPOOL_JOBS_RECYCLE_LIMIT <= 0\r
+ #error "IOT_TASKPOOL_JOBS_RECYCLE_LIMIT cannot be 0 or negative."\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Static memory buffers and flags, allocated and zeroed at compile-time.\r
+ */\r
+static bool _pInUseTaskPools[ IOT_TASKPOOLS ] = { 0 }; /**< @brief Task pools in-use flags. */\r
+static _taskPool_t _pTaskPools[ IOT_TASKPOOLS ] = { { .dispatchQueue = IOT_DEQUEUE_INITIALIZER } }; /**< @brief Task pools. */\r
+\r
+static bool _pInUseTaskPoolJobs[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { 0 }; /**< @brief Task pool jobs in-use flags. */\r
+static _taskPoolJob_t _pTaskPoolJobs[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { { .link = IOT_LINK_INITIALIZER } }; /**< @brief Task pool jobs. */\r
+\r
+static bool _pInUseTaskPoolTimerEvents[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { 0 }; /**< @brief Task pool timer event in-use flags. */\r
+static _taskPoolTimerEvent_t _pTaskPoolTimerEvents[ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT ] = { { .link = { 0 } } }; /**< @brief Task pool timer events. */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void * IotTaskPool_MallocTaskPool( size_t size )\r
+{\r
+ int freeIndex = -1;\r
+ void * pNewTaskPool = NULL;\r
+\r
+ /* Check size argument. */\r
+ if( size == sizeof( _taskPool_t ) )\r
+ {\r
+ /* Find a free task pool job. */\r
+ freeIndex = IotStaticMemory_FindFree( _pInUseTaskPools, IOT_TASKPOOLS );\r
+\r
+ if( freeIndex != -1 )\r
+ {\r
+ pNewTaskPool = &( _pTaskPools[ freeIndex ] );\r
+ }\r
+ }\r
+\r
+ return pNewTaskPool;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void IotTaskPool_FreeTaskPool( void * ptr )\r
+{\r
+ /* Return the in-use task pool job. */\r
+ IotStaticMemory_ReturnInUse( ptr,\r
+ _pTaskPools,\r
+ _pInUseTaskPools,\r
+ IOT_TASKPOOLS,\r
+ sizeof( _taskPool_t ) );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void * IotTaskPool_MallocJob( size_t size )\r
+{\r
+ int32_t freeIndex = -1;\r
+ void * pNewJob = NULL;\r
+\r
+ /* Check size argument. */\r
+ if( size == sizeof( _taskPoolJob_t ) )\r
+ {\r
+ /* Find a free task pool job. */\r
+ freeIndex = IotStaticMemory_FindFree( _pInUseTaskPoolJobs,\r
+ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT );\r
+\r
+ if( freeIndex != -1 )\r
+ {\r
+ pNewJob = &( _pTaskPoolJobs[ freeIndex ] );\r
+ }\r
+ }\r
+\r
+ return pNewJob;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void IotTaskPool_FreeJob( void * ptr )\r
+{\r
+ /* Return the in-use task pool job. */\r
+ IotStaticMemory_ReturnInUse( ptr,\r
+ _pTaskPoolJobs,\r
+ _pInUseTaskPoolJobs,\r
+ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT,\r
+ sizeof( _taskPoolJob_t ) );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void * IotTaskPool_MallocTimerEvent( size_t size )\r
+{\r
+ int32_t freeIndex = -1;\r
+ void * pNewTimerEvent = NULL;\r
+\r
+ /* Check size argument. */\r
+ if( size == sizeof( _taskPoolTimerEvent_t ) )\r
+ {\r
+ /* Find a free task pool timer event. */\r
+ freeIndex = IotStaticMemory_FindFree( _pInUseTaskPoolTimerEvents,\r
+ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT );\r
+\r
+ if( freeIndex != -1 )\r
+ {\r
+ pNewTimerEvent = &( _pTaskPoolTimerEvents[ freeIndex ] );\r
+ }\r
+ }\r
+\r
+ return pNewTimerEvent;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void IotTaskPool_FreeTimerEvent( void * ptr )\r
+{\r
+ /* Return the in-use task pool timer event. */\r
+ IotStaticMemory_ReturnInUse( ptr,\r
+ _pTaskPoolTimerEvents,\r
+ _pInUseTaskPoolTimerEvents,\r
+ IOT_TASKPOOL_JOBS_RECYCLE_LIMIT,\r
+ sizeof( _taskPoolTimerEvent_t ) );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif\r