2 #include <lwp_watchdog.h>
4 #include "lwp_threadq.h"
6 //#define _LWPTHRQ_DEBUG
8 static void __lwp_threadqueue_timeout(void *usr_data
)
11 lwp_thrqueue
*thequeue
;
13 __lwp_thread_dispatchdisable();
14 thethread
= (lwp_cntrl
*)usr_data
;
15 thequeue
= thethread
->wait
.queue
;
16 if(thequeue
->sync_state
!=LWP_THREADQ_SYNCHRONIZED
&& __lwp_thread_isexec(thethread
)) {
17 if(thequeue
->sync_state
!=LWP_THREADQ_SATISFIED
) thequeue
->sync_state
= LWP_THREADQ_TIMEOUT
;
19 thethread
->wait
.ret_code
= thethread
->wait
.queue
->timeout_state
;
20 __lwp_threadqueue_extract(thethread
->wait
.queue
,thethread
);
22 __lwp_thread_dispatchunnest();
25 lwp_cntrl
* __lwp_threadqueue_firstfifo(lwp_thrqueue
*queue
)
27 if(!__lwp_queue_isempty(&queue
->queues
.fifo
))
28 return (lwp_cntrl
*)queue
->queues
.fifo
.first
;
33 lwp_cntrl
* __lwp_threadqueue_firstpriority(lwp_thrqueue
*queue
)
37 for(index
=0;index
<LWP_THREADQ_NUM_PRIOHEADERS
;index
++) {
38 if(!__lwp_queue_isempty(&queue
->queues
.priority
[index
]))
39 return (lwp_cntrl
*)queue
->queues
.priority
[index
].first
;
44 void __lwp_threadqueue_enqueuefifo(lwp_thrqueue
*queue
,lwp_cntrl
*thethread
,u64 timeout
)
48 _CPU_ISR_Disable(level
);
50 sync_state
= queue
->sync_state
;
51 queue
->sync_state
= LWP_THREADQ_SYNCHRONIZED
;
53 printf("__lwp_threadqueue_enqueuefifo(%p,%d)\n",thethread
,sync_state
);
56 case LWP_THREADQ_SYNCHRONIZED
:
58 case LWP_THREADQ_NOTHINGHAPPEND
:
59 __lwp_queue_appendI(&queue
->queues
.fifo
,&thethread
->object
.node
);
60 _CPU_ISR_Restore(level
);
62 case LWP_THREADQ_TIMEOUT
:
63 thethread
->wait
.ret_code
= thethread
->wait
.queue
->timeout_state
;
64 _CPU_ISR_Restore(level
);
66 case LWP_THREADQ_SATISFIED
:
67 if(__lwp_wd_isactive(&thethread
->timer
)) {
68 __lwp_wd_deactivate(&thethread
->timer
);
69 _CPU_ISR_Restore(level
);
70 __lwp_wd_remove_ticks(&thethread
->timer
);
72 _CPU_ISR_Restore(level
);
76 __lwp_thread_unblock(thethread
);
79 lwp_cntrl
* __lwp_threadqueue_dequeuefifo(lwp_thrqueue
*queue
)
84 _CPU_ISR_Disable(level
);
85 if(!__lwp_queue_isempty(&queue
->queues
.fifo
)) {
86 ret
= (lwp_cntrl
*)__lwp_queue_firstnodeI(&queue
->queues
.fifo
);
87 if(!__lwp_wd_isactive(&ret
->timer
)) {
88 _CPU_ISR_Restore(level
);
89 __lwp_thread_unblock(ret
);
91 __lwp_wd_deactivate(&ret
->timer
);
92 _CPU_ISR_Restore(level
);
93 __lwp_wd_remove_ticks(&ret
->timer
);
94 __lwp_thread_unblock(ret
);
99 switch(queue
->sync_state
) {
100 case LWP_THREADQ_SYNCHRONIZED
:
101 case LWP_THREADQ_SATISFIED
:
102 _CPU_ISR_Restore(level
);
104 case LWP_THREADQ_NOTHINGHAPPEND
:
105 case LWP_THREADQ_TIMEOUT
:
106 queue
->sync_state
= LWP_THREADQ_SATISFIED
;
107 _CPU_ISR_Restore(level
);
108 return _thr_executing
;
113 void __lwp_threadqueue_enqueuepriority(lwp_thrqueue
*queue
,lwp_cntrl
*thethread
,u64 timeout
)
115 u32 level
,search_prio
,header_idx
,prio
,block_state
,sync_state
;
116 lwp_cntrl
*search_thread
;
118 lwp_node
*cur_node
,*next_node
,*prev_node
,*search_node
;
120 __lwp_queue_init_empty(&thethread
->wait
.block2n
);
122 prio
= thethread
->cur_prio
;
123 header_idx
= prio
/LWP_THREADQ_PRIOPERHEADER
;
124 header
= &queue
->queues
.priority
[header_idx
];
125 block_state
= queue
->state
;
127 if(prio
&LWP_THREADQ_REVERSESEARCHMASK
) {
128 #ifdef _LWPTHRQ_DEBUG
129 printf("__lwp_threadqueue_enqueuepriority(%p,reverse_search)\n",thethread
);
134 #ifdef _LWPTHRQ_DEBUG
135 printf("__lwp_threadqueue_enqueuepriority(%p,forward_search)\n",thethread
);
138 search_prio
= LWP_PRIO_MIN
- 1;
139 _CPU_ISR_Disable(level
);
140 search_thread
= (lwp_cntrl
*)header
->first
;
141 while(!__lwp_queue_istail(header
,(lwp_node
*)search_thread
)) {
142 search_prio
= search_thread
->cur_prio
;
143 if(prio
<=search_prio
) break;
144 _CPU_ISR_Flash(level
);
146 if(!__lwp_statesset(search_thread
->cur_state
,block_state
)) {
147 _CPU_ISR_Restore(level
);
150 search_thread
= (lwp_cntrl
*)search_thread
->object
.node
.next
;
152 if(queue
->sync_state
!=LWP_THREADQ_NOTHINGHAPPEND
) goto synchronize
;
153 queue
->sync_state
= LWP_THREADQ_SYNCHRONIZED
;
154 if(prio
==search_prio
) goto equal_prio
;
156 search_node
= (lwp_node
*)search_thread
;
157 prev_node
= search_node
->prev
;
158 cur_node
= (lwp_node
*)thethread
;
160 cur_node
->next
= search_node
;
161 cur_node
->prev
= prev_node
;
162 prev_node
->next
= cur_node
;
163 search_node
->prev
= cur_node
;
164 _CPU_ISR_Restore(level
);
168 search_prio
= LWP_PRIO_MAX
+ 1;
169 _CPU_ISR_Disable(level
);
170 search_thread
= (lwp_cntrl
*)header
->last
;
171 while(!__lwp_queue_ishead(header
,(lwp_node
*)search_thread
)) {
172 search_prio
= search_thread
->cur_prio
;
173 if(prio
>=search_prio
) break;
174 _CPU_ISR_Flash(level
);
176 if(!__lwp_statesset(search_thread
->cur_state
,block_state
)) {
177 _CPU_ISR_Restore(level
);
180 search_thread
= (lwp_cntrl
*)search_thread
->object
.node
.prev
;
182 if(queue
->sync_state
!=LWP_THREADQ_NOTHINGHAPPEND
) goto synchronize
;
183 queue
->sync_state
= LWP_THREADQ_SYNCHRONIZED
;
184 if(prio
==search_prio
) goto equal_prio
;
186 search_node
= (lwp_node
*)search_thread
;
187 next_node
= search_node
->next
;
188 cur_node
= (lwp_node
*)thethread
;
190 cur_node
->next
= next_node
;
191 cur_node
->prev
= search_node
;
192 search_node
->next
= cur_node
;
193 next_node
->prev
= cur_node
;
194 _CPU_ISR_Restore(level
);
198 #ifdef _LWPTHRQ_DEBUG
199 printf("__lwp_threadqueue_enqueuepriority(%p,equal_prio)\n",thethread
);
201 search_node
= __lwp_queue_tail(&search_thread
->wait
.block2n
);
202 prev_node
= search_node
->prev
;
203 cur_node
= (lwp_node
*)thethread
;
205 cur_node
->next
= search_node
;
206 cur_node
->prev
= prev_node
;
207 prev_node
->next
= cur_node
;
208 search_node
->prev
= cur_node
;
209 _CPU_ISR_Restore(level
);
213 sync_state
= queue
->sync_state
;
214 queue
->sync_state
= LWP_THREADQ_SYNCHRONIZED
;
216 #ifdef _LWPTHRQ_DEBUG
217 printf("__lwp_threadqueue_enqueuepriority(%p,sync_state = %d)\n",thethread
,sync_state
);
220 case LWP_THREADQ_SYNCHRONIZED
:
222 case LWP_THREADQ_NOTHINGHAPPEND
:
224 case LWP_THREADQ_TIMEOUT
:
225 thethread
->wait
.ret_code
= thethread
->wait
.queue
->timeout_state
;
226 _CPU_ISR_Restore(level
);
228 case LWP_THREADQ_SATISFIED
:
229 if(__lwp_wd_isactive(&thethread
->timer
)) {
230 __lwp_wd_deactivate(&thethread
->timer
);
231 _CPU_ISR_Restore(level
);
232 __lwp_wd_remove_ticks(&thethread
->timer
);
234 _CPU_ISR_Restore(level
);
237 __lwp_thread_unblock(thethread
);
240 lwp_cntrl
* __lwp_threadqueue_dequeuepriority(lwp_thrqueue
*queue
)
243 lwp_cntrl
*newfirstthr
,*ret
= NULL
;
244 lwp_node
*newfirstnode
,*newsecnode
,*last_node
,*next_node
,*prev_node
;
246 _CPU_ISR_Disable(level
);
247 for(idx
=0;idx
<LWP_THREADQ_NUM_PRIOHEADERS
;idx
++) {
248 if(!__lwp_queue_isempty(&queue
->queues
.priority
[idx
])) {
249 ret
= (lwp_cntrl
*)queue
->queues
.priority
[idx
].first
;
254 #ifdef _LWPTHRQ_DEBUG
255 printf("__lwp_threadqueue_dequeuepriority(%p,sync_state = %d)\n",ret
,queue
->sync_state
);
257 switch(queue
->sync_state
) {
258 case LWP_THREADQ_SYNCHRONIZED
:
259 case LWP_THREADQ_SATISFIED
:
260 _CPU_ISR_Restore(level
);
262 case LWP_THREADQ_NOTHINGHAPPEND
:
263 case LWP_THREADQ_TIMEOUT
:
264 queue
->sync_state
= LWP_THREADQ_SATISFIED
;
265 _CPU_ISR_Restore(level
);
266 return _thr_executing
;
270 #ifdef _LWPTHRQ_DEBUG
271 printf("__lwp_threadqueue_dequeuepriority(%p,dequeue)\n",ret
);
273 newfirstnode
= ret
->wait
.block2n
.first
;
274 newfirstthr
= (lwp_cntrl
*)newfirstnode
;
275 next_node
= ret
->object
.node
.next
;
276 prev_node
= ret
->object
.node
.prev
;
277 if(!__lwp_queue_isempty(&ret
->wait
.block2n
)) {
278 last_node
= ret
->wait
.block2n
.last
;
279 newsecnode
= newfirstnode
->next
;
280 prev_node
->next
= newfirstnode
;
281 next_node
->prev
= newfirstnode
;
282 newfirstnode
->next
= next_node
;
283 newfirstnode
->prev
= prev_node
;
285 if(!__lwp_queue_onenode(&ret
->wait
.block2n
)) {
286 newsecnode
->prev
= __lwp_queue_head(&newfirstthr
->wait
.block2n
);
287 newfirstthr
->wait
.block2n
.first
= newsecnode
;
288 newfirstthr
->wait
.block2n
.last
= last_node
;
289 last_node
->next
= __lwp_queue_tail(&newfirstthr
->wait
.block2n
);
292 prev_node
->next
= next_node
;
293 next_node
->prev
= prev_node
;
296 if(!__lwp_wd_isactive(&ret
->timer
)) {
297 _CPU_ISR_Restore(level
);
298 __lwp_thread_unblock(ret
);
300 __lwp_wd_deactivate(&ret
->timer
);
301 _CPU_ISR_Restore(level
);
302 __lwp_wd_remove_ticks(&ret
->timer
);
303 __lwp_thread_unblock(ret
);
308 void __lwp_threadqueue_init(lwp_thrqueue
*queue
,u32 mode
,u32 state
,u32 timeout_state
)
312 queue
->state
= state
;
314 queue
->timeout_state
= timeout_state
;
315 queue
->sync_state
= LWP_THREADQ_SYNCHRONIZED
;
316 #ifdef _LWPTHRQ_DEBUG
317 printf("__lwp_threadqueue_init(%p,%08x,%d,%d)\n",queue
,state
,timeout_state
,mode
);
320 case LWP_THREADQ_MODEFIFO
:
321 __lwp_queue_init_empty(&queue
->queues
.fifo
);
323 case LWP_THREADQ_MODEPRIORITY
:
324 for(index
=0;index
<LWP_THREADQ_NUM_PRIOHEADERS
;index
++)
325 __lwp_queue_init_empty(&queue
->queues
.priority
[index
]);
330 lwp_cntrl
* __lwp_threadqueue_first(lwp_thrqueue
*queue
)
334 switch(queue
->mode
) {
335 case LWP_THREADQ_MODEFIFO
:
336 ret
= __lwp_threadqueue_firstfifo(queue
);
338 case LWP_THREADQ_MODEPRIORITY
:
339 ret
= __lwp_threadqueue_firstpriority(queue
);
349 void __lwp_threadqueue_enqueue(lwp_thrqueue
*queue
,u64 timeout
)
351 lwp_cntrl
*thethread
;
353 thethread
= _thr_executing
;
354 __lwp_thread_setstate(thethread
,queue
->state
);
357 __lwp_wd_initialize(&thethread
->timer
,__lwp_threadqueue_timeout
,thethread
->object
.id
,thethread
);
358 __lwp_wd_insert_ticks(&thethread
->timer
,timeout
);
361 #ifdef _LWPTHRQ_DEBUG
362 printf("__lwp_threadqueue_enqueue(%p,%p,%d)\n",queue
,thethread
,queue
->mode
);
364 switch(queue
->mode
) {
365 case LWP_THREADQ_MODEFIFO
:
366 __lwp_threadqueue_enqueuefifo(queue
,thethread
,timeout
);
368 case LWP_THREADQ_MODEPRIORITY
:
369 __lwp_threadqueue_enqueuepriority(queue
,thethread
,timeout
);
374 lwp_cntrl
* __lwp_threadqueue_dequeue(lwp_thrqueue
*queue
)
376 lwp_cntrl
*ret
= NULL
;
378 #ifdef _LWPTHRQ_DEBUG
379 printf("__lwp_threadqueue_dequeue(%p,%p,%d,%d)\n",queue
,_thr_executing
,queue
->mode
,queue
->sync_state
);
381 switch(queue
->mode
) {
382 case LWP_THREADQ_MODEFIFO
:
383 ret
= __lwp_threadqueue_dequeuefifo(queue
);
385 case LWP_THREADQ_MODEPRIORITY
:
386 ret
= __lwp_threadqueue_dequeuepriority(queue
);
392 #ifdef _LWPTHRQ_DEBUG
393 printf("__lwp_threadqueue_dequeue(%p,%p,%d,%d)\n",queue
,ret
,queue
->mode
,queue
->sync_state
);
398 void __lwp_threadqueue_flush(lwp_thrqueue
*queue
,u32 status
)
400 lwp_cntrl
*thethread
;
401 while((thethread
=__lwp_threadqueue_dequeue(queue
))) {
402 thethread
->wait
.ret_code
= status
;
406 void __lwp_threadqueue_extract(lwp_thrqueue
*queue
,lwp_cntrl
*thethread
)
408 switch(queue
->mode
) {
409 case LWP_THREADQ_MODEFIFO
:
410 __lwp_threadqueue_extractfifo(queue
,thethread
);
412 case LWP_THREADQ_MODEPRIORITY
:
413 __lwp_threadqueue_extractpriority(queue
,thethread
);
419 void __lwp_threadqueue_extractfifo(lwp_thrqueue
*queue
,lwp_cntrl
*thethread
)
423 _CPU_ISR_Disable(level
);
424 if(!__lwp_statewaitthreadqueue(thethread
->cur_state
)) {
425 _CPU_ISR_Restore(level
);
429 __lwp_queue_extractI(&thethread
->object
.node
);
430 if(!__lwp_wd_isactive(&thethread
->timer
)) {
431 _CPU_ISR_Restore(level
);
433 __lwp_wd_deactivate(&thethread
->timer
);
434 _CPU_ISR_Restore(level
);
435 __lwp_wd_remove_ticks(&thethread
->timer
);
437 __lwp_thread_unblock(thethread
);
440 void __lwp_threadqueue_extractpriority(lwp_thrqueue
*queue
,lwp_cntrl
*thethread
)
444 lwp_node
*curr
,*next
,*prev
,*new_first
,*new_sec
,*last
;
446 curr
= (lwp_node
*)thethread
;
448 _CPU_ISR_Disable(level
);
449 if(__lwp_statewaitthreadqueue(thethread
->cur_state
)) {
453 if(!__lwp_queue_isempty(&thethread
->wait
.block2n
)) {
454 new_first
= thethread
->wait
.block2n
.first
;
455 first
= (lwp_cntrl
*)new_first
;
456 last
= thethread
->wait
.block2n
.last
;
457 new_sec
= new_first
->next
;
459 prev
->next
= new_first
;
460 next
->prev
= new_first
;
461 new_first
->next
= next
;
462 new_first
->prev
= prev
;
464 if(!__lwp_queue_onenode(&thethread
->wait
.block2n
)) {
465 new_sec
->prev
= __lwp_queue_head(&first
->wait
.block2n
);
466 first
->wait
.block2n
.first
= new_sec
;
467 first
->wait
.block2n
.last
= last
;
468 last
->next
= __lwp_queue_tail(&first
->wait
.block2n
);
474 if(!__lwp_wd_isactive(&thethread
->timer
)) {
475 _CPU_ISR_Restore(level
);
476 __lwp_thread_unblock(thethread
);
478 __lwp_wd_deactivate(&thethread
->timer
);
479 _CPU_ISR_Restore(level
);
480 __lwp_wd_remove_ticks(&thethread
->timer
);
481 __lwp_thread_unblock(thethread
);
484 _CPU_ISR_Restore(level
);
487 u32
__lwp_threadqueue_extractproxy(lwp_cntrl
*thethread
)
491 state
= thethread
->cur_state
;
492 if(__lwp_statewaitthreadqueue(state
)) {
493 __lwp_threadqueue_extract(thethread
->wait
.queue
,thethread
);