1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   Timer                                                               */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "tx_api.h"
28 #include "tx_initialize.h"
29 #include "tx_thread.h"
30 #include "tx_timer.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _txe_timer_create                                   PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    William E. Lamie, Microsoft Corporation                             */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function checks for errors in the create application timer     */
46 /*    function call.                                                      */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    timer_ptr                         Pointer to timer control block    */
51 /*    name_ptr                          Pointer to timer name             */
52 /*    expiration_function               Application expiration function   */
53 /*    initial_ticks                     Initial expiration ticks          */
54 /*    reschedule_ticks                  Reschedule ticks                  */
55 /*    auto_activate                     Automatic activation flag         */
56 /*    timer_control_block_size          Size of timer control block       */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    TX_TIMER_ERROR                    Invalid timer control block       */
61 /*    TX_TICK_ERROR                     Invalid initial expiration count  */
62 /*    TX_ACTIVATE_ERROR                 Invalid timer activation option   */
63 /*    TX_CALLER_ERROR                   Invalid caller of this function   */
64 /*    status                            Actual completion status          */
65 /*                                                                        */
66 /*  CALLS                                                                 */
67 /*                                                                        */
68 /*    _tx_thread_system_preempt_check   Check for preemption              */
69 /*    _tx_timer_create                  Actual timer create function      */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    Application Code                                                    */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
80 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*                                                                        */
83 /**************************************************************************/
_txe_timer_create(TX_TIMER * timer_ptr,CHAR * name_ptr,VOID (* expiration_function)(ULONG id),ULONG expiration_input,ULONG initial_ticks,ULONG reschedule_ticks,UINT auto_activate,UINT timer_control_block_size)84 UINT  _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
85             VOID (*expiration_function)(ULONG id), ULONG expiration_input,
86             ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size)
87 {
88 
89 TX_INTERRUPT_SAVE_AREA
90 
91 UINT            status;
92 ULONG           i;
93 TX_TIMER        *next_timer;
94 #ifndef TX_TIMER_PROCESS_IN_ISR
95 TX_THREAD       *thread_ptr;
96 #endif
97 
98 
99     /* Default status to success.  */
100     status =  TX_SUCCESS;
101 
102     /* Check for a NULL timer pointer.  */
103     if (timer_ptr == TX_NULL)
104     {
105 
106         /* Timer pointer is invalid, return appropriate error code.  */
107         status =  TX_TIMER_ERROR;
108     }
109 
110     /* Now check for invalid control block size.  */
111     else if (timer_control_block_size != (sizeof(TX_TIMER)))
112     {
113 
114         /* Timer pointer is invalid, return appropriate error code.  */
115         status =  TX_TIMER_ERROR;
116     }
117     else
118     {
119 
120         /* Disable interrupts.  */
121         TX_DISABLE
122 
123         /* Increment the preempt disable flag.  */
124         _tx_thread_preempt_disable++;
125 
126         /* Restore interrupts.  */
127         TX_RESTORE
128 
129         /* Next see if it is already in the created list.  */
130         next_timer =  _tx_timer_created_ptr;
131         for (i = ((ULONG) 0); i < _tx_timer_created_count; i++)
132         {
133 
134             /* Determine if this timer matches the current timer in the list.  */
135             if (timer_ptr == next_timer)
136             {
137 
138                 break;
139             }
140             else
141             {
142 
143                 /* Move to next timer.  */
144                 next_timer =  next_timer -> tx_timer_created_next;
145             }
146         }
147 
148         /* Disable interrupts.  */
149         TX_DISABLE
150 
151         /* Decrement the preempt disable flag.  */
152         _tx_thread_preempt_disable--;
153 
154         /* Restore interrupts.  */
155         TX_RESTORE
156 
157         /* Check for preemption.  */
158         _tx_thread_system_preempt_check();
159 
160         /* At this point, check to see if there is a duplicate timer.  */
161         if (timer_ptr == next_timer)
162         {
163 
164             /* Timer is already created, return appropriate error code.  */
165             status =  TX_TIMER_ERROR;
166         }
167 
168         /* Check for an illegal initial tick value.  */
169         else if (initial_ticks == ((ULONG) 0))
170         {
171 
172             /* Invalid initial tick value, return appropriate error code.  */
173             status =  TX_TICK_ERROR;
174         }
175         else
176         {
177 
178             /* Check for an illegal activation.  */
179             if (auto_activate != TX_AUTO_ACTIVATE)
180             {
181 
182                 /* And activation is not the other value.  */
183                 if (auto_activate != TX_NO_ACTIVATE)
184                 {
185 
186                     /* Invalid activation selected, return appropriate error code.  */
187                     status =  TX_ACTIVATE_ERROR;
188                 }
189             }
190         }
191     }
192 
193     /* Determine if everything is okay.  */
194     if (status == TX_SUCCESS)
195     {
196 
197 #ifndef TX_TIMER_PROCESS_IN_ISR
198 
199         /* Pickup thread pointer.  */
200         TX_THREAD_GET_CURRENT(thread_ptr)
201 
202         /* Check for invalid caller of this function.  First check for a calling thread.  */
203         if (thread_ptr == &_tx_timer_thread)
204         {
205 
206             /* Invalid caller of this function, return appropriate error code.  */
207             status =  TX_CALLER_ERROR;
208         }
209 #endif
210 
211         /* Check for interrupt call.  */
212         if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
213         {
214 
215             /* Now, make sure the call is from an interrupt and not initialization.  */
216             if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
217             {
218 
219                 /* Invalid caller of this function, return appropriate error code.  */
220                 status =  TX_CALLER_ERROR;
221             }
222         }
223     }
224 
225 
226     /* Determine if everything is okay.  */
227     if (status == TX_SUCCESS)
228     {
229 
230         /* Call actual application timer create function.  */
231         status =  _tx_timer_create(timer_ptr, name_ptr, expiration_function, expiration_input,
232                                                     initial_ticks, reschedule_ticks, auto_activate);
233     }
234 
235     /* Return completion status.  */
236     return(status);
237 }
238 
239