1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** ThreadX Component                                                     */
17 /**                                                                       */
18 /**   Thread                                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define TX_SOURCE_CODE
24 
25 #ifndef TX_NO_TIMER
26 
27 /* Include necessary system files.  */
28 
29 #include "tx_api.h"
30 #include "tx_timer.h"
31 #include "tx_thread.h"
32 #include "tx_trace.h"
33 
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _tx_thread_time_slice                               PORTABLE C      */
40 /*                                                           6.1          */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    William E. Lamie, Microsoft Corporation                             */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    This function moves the currently executing thread to the end of    */
48 /*    the threads ready at the same priority level as a result of a       */
49 /*    time-slice interrupt.  If no other thread of the same priority is   */
50 /*    ready, this function simply returns.                                */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    None                                                                */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    _tx_timer_interrupt                   Timer interrupt handling      */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
73 /*  09-30-2020     Scott Larson             Modified comment(s), and      */
74 /*                                            opt out of function when    */
75 /*                                            TX_NO_TIMER is defined,     */
76 /*                                            resulting in version 6.1    */
77 /*                                                                        */
78 /**************************************************************************/
_tx_thread_time_slice(VOID)79 VOID  _tx_thread_time_slice(VOID)
80 {
81 
82 TX_INTERRUPT_SAVE_AREA
83 
84 TX_THREAD       *thread_ptr;
85 #ifdef TX_ENABLE_STACK_CHECKING
86 TX_THREAD       *next_thread_ptr;
87 #endif
88 #ifdef TX_ENABLE_EVENT_TRACE
89 ULONG           system_state;
90 UINT            preempt_disable;
91 #endif
92 
93     /* Pickup thread pointer.  */
94     TX_THREAD_GET_CURRENT(thread_ptr)
95 
96 #ifdef TX_ENABLE_STACK_CHECKING
97 
98     /* Check this thread's stack.  */
99     TX_THREAD_STACK_CHECK(thread_ptr)
100 
101     /* Set the next thread pointer to NULL.  */
102     next_thread_ptr =  TX_NULL;
103 #endif
104 
105     /* Lockout interrupts while the time-slice is evaluated.  */
106     TX_DISABLE
107 
108     /* Clear the expired time-slice flag.  */
109     _tx_timer_expired_time_slice =  TX_FALSE;
110 
111     /* Make sure the thread pointer is valid.  */
112     if (thread_ptr != TX_NULL)
113     {
114 
115         /* Make sure the thread is still active, i.e. not suspended.  */
116         if (thread_ptr -> tx_thread_state == TX_READY)
117         {
118 
119             /* Setup a fresh time-slice for the thread.  */
120             thread_ptr -> tx_thread_time_slice =  thread_ptr -> tx_thread_new_time_slice;
121 
122             /* Reset the actual time-slice variable.  */
123             _tx_timer_time_slice =  thread_ptr -> tx_thread_time_slice;
124 
125             /* Determine if there is another thread at the same priority and preemption-threshold
126                is not set.  Preemption-threshold overrides time-slicing.  */
127             if (thread_ptr -> tx_thread_ready_next != thread_ptr)
128             {
129 
130                 /* Check to see if preemption-threshold is not being used.  */
131                 if (thread_ptr -> tx_thread_priority == thread_ptr -> tx_thread_preempt_threshold)
132                 {
133 
134                     /* Preemption-threshold is not being used by this thread.  */
135 
136                     /* There is another thread at this priority, make it the highest at
137                        this priority level.  */
138                     _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr -> tx_thread_ready_next;
139 
140                     /* Designate the highest priority thread as the one to execute.  Don't use this
141                        thread's priority as an index just in case a higher priority thread is now
142                        ready!  */
143                     _tx_thread_execute_ptr =  _tx_thread_priority_list[_tx_thread_highest_priority];
144 
145 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
146 
147                     /* Increment the thread's time-slice counter.  */
148                     thread_ptr -> tx_thread_performance_time_slice_count++;
149 
150                     /* Increment the total number of thread time-slice operations.  */
151                     _tx_thread_performance_time_slice_count++;
152 #endif
153 
154 
155 #ifdef TX_ENABLE_STACK_CHECKING
156 
157                     /* Pickup the next execute pointer.  */
158                     next_thread_ptr =  _tx_thread_execute_ptr;
159 #endif
160                 }
161             }
162         }
163     }
164 
165 #ifdef TX_ENABLE_EVENT_TRACE
166 
167     /* Pickup the volatile information.  */
168     system_state =  TX_THREAD_GET_SYSTEM_STATE();
169     preempt_disable =  _tx_thread_preempt_disable;
170 
171     /* Insert this event into the trace buffer.  */
172     TX_TRACE_IN_LINE_INSERT(TX_TRACE_TIME_SLICE, _tx_thread_execute_ptr, system_state, preempt_disable, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_INTERNAL_EVENTS)
173 #endif
174 
175     /* Restore previous interrupt posture.  */
176     TX_RESTORE
177 
178 #ifdef TX_ENABLE_STACK_CHECKING
179 
180     /* Determine if there is a next thread pointer to perform stack checking on.  */
181     if (next_thread_ptr != TX_NULL)
182     {
183 
184         /* Yes, check this thread's stack.  */
185         TX_THREAD_STACK_CHECK(next_thread_ptr)
186     }
187 #endif
188 }
189 
190 #endif
191