1 /***********************************************************************************************//** 2 * \file cy_worker_thread.h 3 * 4 * \brief 5 * Defines the interface for the worker thread utility. Provides prototypes for 6 * functions that allow creating/deleting worker threads and queueing work to 7 * a worker thread. 8 *************************************************************************************************** 9 * \copyright 10 * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or 11 * an affiliate of Cypress Semiconductor Corporation 12 * 13 * SPDX-License-Identifier: Apache-2.0 14 * 15 * Licensed under the Apache License, Version 2.0 (the "License"); 16 * you may not use this file except in compliance with the License. 17 * You may obtain a copy of the License at 18 * 19 * http://www.apache.org/licenses/LICENSE-2.0 20 * 21 * Unless required by applicable law or agreed to in writing, software 22 * distributed under the License is distributed on an "AS IS" BASIS, 23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 * See the License for the specific language governing permissions and 25 * limitations under the License. 26 **************************************************************************************************/ 27 28 #pragma once 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #include <stdint.h> 35 36 #include "cy_result.h" 37 #include "cyabs_rtos.h" 38 39 /** 40 * \addtogroup group_worker_thread_util Worker Thread Utility 41 * \{ 42 * Worker thread utility that allows functions to be run a different thread context. 43 * This utility can be used to delegate work that is not timing critical. For example, 44 * scheduling work in interrupt handlers to keep handler execution times low or if some 45 * work needs to be done at a different priority. 46 */ 47 48 /**< Default worker thread name */ 49 #define CY_WORKER_THREAD_DEFAULT_NAME "CYWorker" 50 /** Default number of work items in the queue */ 51 #define CY_WORKER_DEFAULT_ENTRIES (16) 52 53 /** Additional work cannot be enqueued because the worker thread has been terminated. 54 * This can occur if \ref cy_worker_thread_create was not called or \ref cy_worker_thread_delete was 55 * called before calling \ref cy_worker_thread_enqueue 56 */ 57 #define CY_WORKER_THREAD_ERR_THREAD_INVALID \ 58 CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 32) 59 60 /** Worker thread function call prototype */ 61 typedef void (cy_worker_thread_func_t)(void* arg); 62 63 /** Thread state enumeration */ 64 typedef enum 65 { 66 CY_WORKER_THREAD_INVALID, /**< Worker Thread is in invalid state */ 67 CY_WORKER_THREAD_VALID, /**< Worker Thread is in valid state */ 68 CY_WORKER_THREAD_ENQUEUING, /**< Worker Thread is adding to the queue */ 69 CY_WORKER_THREAD_TERMINATING, /**< Worker Thread is starting to terminate */ 70 CY_WORKER_THREAD_JOIN_COMPLETE /**< Worker Thread join is complete */ 71 } cy_worker_thread_state_t; 72 73 /** Worker Thread Parameters. */ 74 typedef struct 75 { 76 cy_thread_priority_t priority; /**< Requested thread priority. */ 77 uint32_t stack_size; /**< Size of stack for new thread. 78 Note that this must be atleast CY_RTOS_MIN_STACK_SIZE */ 79 uint8_t* stack; /**< Pointer to stack. If this is NULL a stack of 80 size \ref stack_size will be allocated. */ 81 const char* name; /**< Thread name. If set to NULL, 82 \ref CY_WORKER_THREAD_DEFAULT_NAME will be used. */ 83 uint32_t num_entries; /**< Maximum number of enteries the worker thread can queue. 84 If set to 0, \ref CY_WORKER_DEFAULT_ENTRIES 85 will be used. */ 86 } cy_worker_thread_params_t; 87 88 /** Worker Thread Information. */ 89 typedef struct 90 { 91 cy_queue_t event_queue; /**< Event Queue for this thread */ 92 uint32_t enqueue_count; /**< Number of conccurent enqueue requests */ 93 cy_thread_t thread; /**< Thread object */ 94 cy_worker_thread_state_t state; /**< State of the worker thread */ 95 } cy_worker_thread_info_t; 96 97 /** Create worker thread to handle running callbacks in a separate thread. 98 * 99 * @note Calling this function twice on the same thread object ( \ref cy_worker_thread_info_t) 100 * without 101 * calling \ref cy_worker_thread_delete will cause memory leakage. 102 * 103 * @param[out] new_worker pointer to cy_worker_thread_info_t structure to be filled when created. 104 * @param[in] params pointer to requested parameters for starting worker thread. 105 * 106 * @return The status of the worker thread creation request. 107 */ 108 cy_rslt_t cy_worker_thread_create(cy_worker_thread_info_t* new_worker, 109 const cy_worker_thread_params_t* params); 110 111 /** Delete worker thread. 112 * 113 * @note This function will wait for the thread to complete all pending work in the 114 * queue and exit before returning. 115 * 116 * @param[in] old_worker pointer to cy_worker_thread_info_t structure to be deleted. 117 * 118 * @return The status of the deletion of the worker thread. 119 */ 120 cy_rslt_t cy_worker_thread_delete(cy_worker_thread_info_t* old_worker); 121 122 /** Queue work on a worker thread. 123 * 124 * Call the given function in the worker thread context. 125 * 126 * @note If the thread priority is below that of the current thread, you must yield to allow 127 * the worker thread to run. This can be done by calling \ref cy_rtos_delay_milliseconds or 128 * by waiting on an RTOS object in all higher priority threads. 129 * 130 * @param[in] worker_info pointer to worker_thread used to run function 131 * @param[in] work_func function to run 132 * @param[in] arg opaque arg to be used in function call 133 * 134 * @return The status of the queueing of work. 135 */ 136 cy_rslt_t cy_worker_thread_enqueue(cy_worker_thread_info_t* worker_info, 137 cy_worker_thread_func_t* work_func, void* arg); 138 139 /** @} */ 140 141 #ifdef __cplusplus 142 } 143 #endif 144 145 /** \} group_abstraction_resource */ 146