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 #ifndef TX_NO_TIMER
25 
26 /* Include necessary system files.  */
27 
28 #include "tx_api.h"
29 #include "tx_timer.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _tx_timer_system_activate                           PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    William E. Lamie, Microsoft Corporation                             */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function places the specified internal timer in the proper     */
45 /*    place in the timer expiration list.  If the timer is already active */
46 /*    this function does nothing.                                         */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    timer_ptr                         Pointer to timer control block    */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    TX_SUCCESS                        Always returns success            */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    _tx_thread_system_suspend         Thread suspend function           */
63 /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
64 /*    _tx_timer_thread_entry            Timer thread processing           */
65 /*    _tx_timer_activate                Application timer activate        */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
72 /*  09-30-2020     Scott Larson             Modified comment(s), and      */
73 /*                                            opt out of function when    */
74 /*                                            TX_NO_TIMER is defined,     */
75 /*                                            resulting in version 6.1    */
76 /*                                                                        */
77 /**************************************************************************/
_tx_timer_system_activate(TX_TIMER_INTERNAL * timer_ptr)78 VOID  _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr)
79 {
80 
81 TX_TIMER_INTERNAL           **timer_list;
82 TX_TIMER_INTERNAL           *next_timer;
83 TX_TIMER_INTERNAL           *previous_timer;
84 ULONG                       delta;
85 ULONG                       remaining_ticks;
86 ULONG                       expiration_time;
87 
88 
89     /* Pickup the remaining ticks.  */
90     remaining_ticks =  timer_ptr -> tx_timer_internal_remaining_ticks;
91 
92     /* Determine if there is a timer to activate.  */
93     if (remaining_ticks != ((ULONG) 0))
94     {
95 
96         /* Determine if the timer is set to wait forever.  */
97         if (remaining_ticks != TX_WAIT_FOREVER)
98         {
99 
100             /* Valid timer activate request.  */
101 
102             /* Determine if the timer still needs activation.  */
103             if (timer_ptr -> tx_timer_internal_list_head == TX_NULL)
104             {
105 
106                 /* Activate the timer.  */
107 
108                 /* Calculate the amount of time remaining for the timer.  */
109                 if (remaining_ticks > TX_TIMER_ENTRIES)
110                 {
111 
112                     /* Set expiration time to the maximum number of entries.  */
113                     expiration_time =  TX_TIMER_ENTRIES - ((ULONG) 1);
114                 }
115                 else
116                 {
117 
118                     /* Timer value fits in the timer entries.  */
119 
120                     /* Set the expiration time.  */
121                     expiration_time =  (remaining_ticks - ((ULONG) 1));
122                 }
123 
124                 /* At this point, we are ready to put the timer on one of
125                    the timer lists.  */
126 
127                 /* Calculate the proper place for the timer.  */
128                 timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, expiration_time);
129                 if (TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(timer_list) >= TX_TIMER_INDIRECT_TO_VOID_POINTER_CONVERT(_tx_timer_list_end))
130                 {
131 
132                     /* Wrap from the beginning of the list.  */
133                     delta =  TX_TIMER_POINTER_DIF(timer_list, _tx_timer_list_end);
134                     timer_list =  TX_TIMER_POINTER_ADD(_tx_timer_list_start, delta);
135                 }
136 
137                 /* Now put the timer on this list.  */
138                 if ((*timer_list) == TX_NULL)
139                 {
140 
141                     /* This list is NULL, just put the new timer on it.  */
142 
143                     /* Setup the links in this timer.  */
144                     timer_ptr -> tx_timer_internal_active_next =      timer_ptr;
145                     timer_ptr -> tx_timer_internal_active_previous =  timer_ptr;
146 
147                     /* Setup the list head pointer.  */
148                     *timer_list =  timer_ptr;
149                 }
150                 else
151                 {
152 
153                     /* This list is not NULL, add current timer to the end. */
154                     next_timer =                                        *timer_list;
155                     previous_timer =                                    next_timer -> tx_timer_internal_active_previous;
156                     previous_timer -> tx_timer_internal_active_next =   timer_ptr;
157                     next_timer -> tx_timer_internal_active_previous =   timer_ptr;
158                     timer_ptr -> tx_timer_internal_active_next =        next_timer;
159                     timer_ptr -> tx_timer_internal_active_previous =    previous_timer;
160                 }
161 
162                 /* Setup list head pointer.  */
163                 timer_ptr -> tx_timer_internal_list_head =  timer_list;
164             }
165         }
166     }
167 }
168 
169 #endif
170