1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * https://opensource.org/licenses/MIT.
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
;#define TX_SOURCE_CODE
;
;
.equ BTA, 0x412
;
;/* Include necessary system files. */
;
;#include "tx_api.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
; /* Define the lock for the ARC simulator workaround. The ARC HS SMP
; simulator does not execute cores in a lock-step fashion, i.e., a
; core can stall for many cycles while the other core executes. This
; does not happen on actual hardware and thus the need for a schedule
; lock is not required since: 1) ThreadX SMP will not load the same
; thread into two places on the _tx_thread_execute_list, and moving
; a thread from one entry on the _tx_thread_execute_list to another
; is more than the 5 instructions executed between examination of the
; the _tx_thread_execute_list thread and clearing its ready bit in
; preparation for scheduling. */
;
.ifdef TX_ARC_SIMULATOR_WORKAROUND
.globl _tx_thread_schedule_lock
.size _tx_thread_schedule_lock, 4
.type _tx_thread_schedule_lock,@object
_tx_thread_schedule_lock:
.word 0
.endif
;
;
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_schedule SMP/ARC_HS/MetaWare */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function waits for a thread control block pointer to appear in */
;/* the _tx_thread_execute_ptr array. Once a thread pointer appears */
;/* in the variable, the corresponding thread is resumed. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_initialize_kernel_enter ThreadX entry function */
;/* _tx_thread_system_return Return to system from thread */
;/* _tx_thread_context_restore Restore thread's context */
;/* */
;/**************************************************************************/
;VOID _tx_thread_schedule(VOID)
;{
.global _tx_thread_schedule_restart
_tx_thread_schedule_restart:
.ifdef TX_ARC_SIMULATOR_WORKAROUND
mov r7, _tx_thread_schedule_lock
dmb 3
mov r3, 0
st r3, [r7]
dmb 3
.endif
.global _tx_thread_schedule
.type _tx_thread_schedule, @function
_tx_thread_schedule:
;
;
; /* Enable interrupts. */
;
mov r0, 0x1F ; Build enable interrupt value
seti r0 ; Enable interrupts
;
; /* Wait for a thread to execute. */
; do
; {
;
lr r1, [IDENTITY] ; Pickup core ID
xbfu r1, r1, 8, 8 ; Shift down and isolate core ID
.ifndef TX_ZERO_BASED_CORE_ID
sub r1, r1, 1 ; Subtract 1 to make 0-based
.endif
asl r4, r1, 2 ; Build index into core arrays
mov r7, _tx_thread_execute_ptr ; Pickup base of the execute thread pointer
add r7, r7, r4 ; Build address of current thread pointer
__tx_thread_schedule_loop:
;
clri ; Lockout interrupts
nop ; Delay for interrupts to really be disabled
.ifdef TX_ARC_SIMULATOR_WORKAROUND
mov r0, _tx_thread_schedule_lock
llock r5, [r0]
breq r5, 0, _continue
b _tx_thread_schedule
_continue:
add r5, r1, 1
scond r5, [r0]
beq_s _got_lock
b _tx_thread_schedule
_got_lock:
.endif
ld r0, [r7] ; Pickup next thread to execute
breq r0, 0, _tx_thread_schedule_restart ; If NULL, keep looking
;
; }
; while(_tx_thread_execute_ptr[core] == TX_NULL);
;
;
; /* Now make sure the thread's ready bit is set. */
;
ld r5, [r0, 164] ; Pickup the ready bit for this thread to see if it can be executed
breq r5, 0, _tx_thread_schedule_restart ; If not set, start over
st 0, [r0, 164] ; Clear the ready bit now that this thread is being executed
dmb 3 ; Data memory barrier
.ifdef TX_ARC_SIMULATOR_WORKAROUND
mov r7, _tx_thread_schedule_lock
dmb 3
mov r3, 0
st r3, [r7]
dmb 3
.endif
;
; /* Yes! We have a thread to execute - transfer control to it. */
;
; /* Setup the current thread pointer. */
; _tx_thread_current_ptr[core] = _tx_thread_execute_ptr[core];
;
mov r7, _tx_thread_current_ptr ; Build address of current thread pointer
add r7, r7, r4 ;
st r0, [r7] ; Setup current thread pointer
;
; /* Increment the run count for this thread. */
; _tx_thread_current_ptr[core] -> tx_thread_run_count++;
;
ld r3, [r0, 4] ; Pickup run counter
ld r5, [r0, 24] ; Pickup time-slice for this thread
add r3, r3, 1 ; Increment run counter
st r3, [r0, 4] ; Store the new run counter
;
; /* Setup time-slice, if present. */
; _tx_timer_time_slice[core] = _tx_thread_current_ptr -> tx_thread_time_slice;
;
mov r6, _tx_timer_time_slice ; Build address of time-slice for this core
add r6, r6, r4 ;
st r5, [r6] ; Setup time-slice
;
.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the thread entry function to indicate the thread is executing. */
;
mov r13, r0 ; Save thread control block pointer
bl.d _tx_execution_thread_enter ; Call the thread execution enter function
sub sp, sp, 16 ; ..allocating some space on the stack
add sp, sp, 16 ; Recover the stack space
mov r0, r13 ; Recover thread control block pointer
.endif
;
; /* Switch to the thread's stack. */
; sp = _tx_thread_execute_ptr[core] -> tx_thread_stack_ptr;
;
ld sp, [r0, 8] ; Switch to thread's stack
;
; /* Determine if an interrupt frame or a synchronous task suspension frame
; is present. */
;
ld r1, [sp, 0] ; Pickup the stack type
brne r1, 0, __tx_thread_schedule_int_ret ; Compare to solicited stack type. If not, thread was interrupted
ld blink, [sp, 4] ; Recover blink
ld fp, [sp, 8] ; Recover fp
ld gp, [sp, 12] ; Recover gp
ld r25, [sp, 16] ; Recover r25
ld r24, [sp, 20] ; Recover r24
ld r23, [sp, 24] ; Recover r23
ld r22, [sp, 28] ; Recover r22
ld r21, [sp, 32] ; Recover r21
ld r20, [sp, 36] ; Recover r20
ld r19, [sp, 40] ; Recover r19
ld r18, [sp, 44] ; Recover r18
ld r17, [sp, 48] ; Recover r17
ld r16, [sp, 52] ; Recover r16
ld r15, [sp, 56] ; Recover r15
ld r14, [sp, 60] ; Recover r14
ld r13, [sp, 64] ; Recover r13
ld r1, [sp, 68] ; Pickup status32
ld r30, [sp, 72] ; Recover r30
add sp, sp, 76 ; Recover solicited stack frame
j_s.d [blink] ; Return to thread and restore flags
seti r1 ; Recover STATUS32
;
__tx_thread_schedule_int_ret:
;
mov r0, 0x2 ; Pretend level 1 interrupt is returning
sr r0, [AUX_IRQ_ACT] ;
.ifndef TX_DISABLE_LP
ld r0, [sp, 4] ; Recover LP_START
sr r0, [LP_START] ; Restore LP_START
ld r1, [sp, 8] ; Recover LP_END
sr r1, [LP_END] ; Restore LP_END
ld r2, [sp, 12] ; Recover LP_COUNT
mov LP_COUNT, r2
.endif
ld r0, [sp, 156] ; Pickup saved BTA
sr r0, [BTA] ; Recover BTA
ld blink, [sp, 16] ; Recover blink
ld ilink, [sp, 20] ; Recover ilink
ld fp, [sp, 24] ; Recover fp
ld gp, [sp, 28] ; Recover gp
ld r25, [sp, 32] ; Recover r25
ld r24, [sp, 36] ; Recover r24
ld r23, [sp, 40] ; Recover r23
ld r22, [sp, 44] ; Recover r22
ld r21, [sp, 48] ; Recover r21
ld r20, [sp, 52] ; Recover r20
ld r19, [sp, 56] ; Recover r19
ld r18, [sp, 60] ; Recover r18
ld r17, [sp, 64] ; Recover r17
ld r16, [sp, 68] ; Recover r16
ld r15, [sp, 72] ; Recover r15
ld r14, [sp, 76] ; Recover r14
ld r13, [sp, 80] ; Recover r13
ld r12, [sp, 84] ; Recover r12
ld r11, [sp, 88] ; Recover r11
ld r10, [sp, 92] ; Recover r10
ld r9, [sp, 96] ; Recover r9
ld r8, [sp, 100] ; Recover r8
ld r7, [sp, 104] ; Recover r7
ld r6, [sp, 108] ; Recover r6
ld r5, [sp, 112] ; Recover r5
ld r4, [sp, 116] ; Recover r4
ld r3, [sp, 120] ; Recover r3
ld r2, [sp, 124] ; Recover r2
ld r1, [sp, 128] ; Recover r1
ld r0, [sp, 132] ; Recover r0
ld r30, [sp, 136] ; Recover r30
.ifdef TX_ENABLE_ACC
ld r58, [sp, 140] ; Recover r58
ld r59, [sp, 144] ; Recover r59
.endif
add sp, sp, 160 ; Recover interrupt stack frame
rtie ; Return to point of interrupt
;
;}
;
.end
|