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