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 /** Thread */
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_trace.h"
29 #include "tx_thread.h"
30 #ifndef TX_NO_TIMER
31 #include "tx_timer.h"
32 #endif
33
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _tx_thread_relinquish 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 list of threads ready at the same priority. If no other threads */
49 /* of the same or higher priority are ready, this function simply */
50 /* returns. */
51 /* */
52 /* INPUT */
53 /* */
54 /* None */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* None */
59 /* */
60 /* CALLS */
61 /* */
62 /* _tx_thread_system_return Return to the system */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
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 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_tx_thread_relinquish(VOID)77 VOID _tx_thread_relinquish(VOID)
78 {
79
80 TX_INTERRUPT_SAVE_AREA
81
82 UINT priority;
83 TX_THREAD *thread_ptr;
84
85
86 /* Pickup thread pointer. */
87 TX_THREAD_GET_CURRENT(thread_ptr)
88
89 #ifdef TX_ENABLE_STACK_CHECKING
90
91 /* Check this thread's stack. */
92 TX_THREAD_STACK_CHECK(thread_ptr)
93 #endif
94
95 /* Disable interrupts. */
96 TX_DISABLE
97
98 #ifndef TX_NO_TIMER
99
100 /* Reset time slice for current thread. */
101 _tx_timer_time_slice = thread_ptr -> tx_thread_new_time_slice;
102 #endif
103
104 /* Pickup the thread's priority. */
105 priority = thread_ptr -> tx_thread_priority;
106
107 /* Determine if there is another thread at the same priority. */
108 if (thread_ptr -> tx_thread_ready_next != thread_ptr)
109 {
110
111 /* Yes, there is another thread at this priority, make it the highest at
112 this priority level. */
113 _tx_thread_priority_list[priority] = thread_ptr -> tx_thread_ready_next;
114
115 /* Mark the new thread as the one to execute. */
116 _tx_thread_execute_ptr = thread_ptr -> tx_thread_ready_next;
117 }
118
119 /* Determine if there is a higher-priority thread ready. */
120 if (_tx_thread_highest_priority < priority)
121 {
122
123 /* Yes, there is a higher priority thread ready to execute. Make
124 it visible to the thread scheduler. */
125 _tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
126
127 /* No need to clear the preempted bit in this case, since the currently running
128 thread must already have its preempted bit clear. */
129 }
130
131 /* If trace is enabled, insert this event into the trace buffer. */
132 TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RELINQUISH, &thread_ptr, TX_POINTER_TO_ULONG_CONVERT(_tx_thread_execute_ptr), 0, 0, TX_TRACE_THREAD_EVENTS)
133
134 /* Log this kernel call. */
135 TX_EL_THREAD_RELINQUISH_INSERT
136
137 /* Restore previous interrupt posture. */
138 TX_RESTORE
139
140 /* Determine if this thread needs to return to the system. */
141 if (_tx_thread_execute_ptr != thread_ptr)
142 {
143
144 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
145
146 /* Increment the number of thread relinquishes. */
147 thread_ptr -> tx_thread_performance_relinquish_count++;
148
149 /* Increment the total number of thread relinquish operations. */
150 _tx_thread_performance_relinquish_count++;
151
152 /* Increment the non-idle return count. */
153 _tx_thread_performance_non_idle_return_count++;
154 #endif
155
156 #ifdef TX_ENABLE_STACK_CHECKING
157
158 /* Pickup the next execute pointer. */
159 thread_ptr = _tx_thread_execute_ptr;
160
161 /* Check this thread's stack. */
162 TX_THREAD_STACK_CHECK(thread_ptr)
163 #endif
164
165 /* Transfer control to the system so the scheduler can execute
166 the next thread. */
167 _tx_thread_system_return();
168 }
169 }
170
171