8 #include "lwp_threads.h"
9 #include "lwp_threadq.h"
10 #include "lwp_watchdog.h"
12 #define LWP_MAXPRIORITIES 256
15 frame_context core_context
;
17 lwp_cntrl
*_thr_main
= NULL
;
18 lwp_cntrl
*_thr_idle
= NULL
;
20 lwp_cntrl
*_thr_executing
= NULL
;
21 lwp_cntrl
*_thr_heir
= NULL
;
22 lwp_cntrl
*_thr_allocated_fp
= NULL
;
24 vu32 _context_switch_want
;
25 vu32 _thread_dispatch_disable_level
;
27 wd_cntrl _lwp_wd_timeslice
;
28 u32 _lwp_ticks_per_timeslice
= 0;
29 void **__lwp_thr_libc_reent
= NULL
;
30 lwp_queue _lwp_thr_ready
[LWP_MAXPRIORITIES
];
32 static void (*_lwp_exitfunc
)(void);
34 extern void _cpu_context_switch(void *,void *);
35 extern void _cpu_context_switch_ex(void *,void *);
36 extern void _cpu_context_save(void *);
37 extern void _cpu_context_restore(void *);
38 extern void _cpu_context_save_fp(void *);
39 extern void _cpu_context_restore_fp(void *);
41 extern int __libc_create_hook(lwp_cntrl
*,lwp_cntrl
*);
42 extern int __libc_start_hook(lwp_cntrl
*,lwp_cntrl
*);
43 extern int __libc_delete_hook(lwp_cntrl
*, lwp_cntrl
*);
45 extern void kprintf(const char *str
, ...);
47 #ifdef _LWPTHREADS_DEBUG
48 static void __lwp_dumpcontext(frame_context
*ctx
)
50 kprintf("GPR00 %08x GPR08 %08x GPR16 %08x GPR24 %08x\n",ctx
->GPR
[0], ctx
->GPR
[8], ctx
->GPR
[16], ctx
->GPR
[24]);
51 kprintf("GPR01 %08x GPR09 %08x GPR17 %08x GPR25 %08x\n",ctx
->GPR
[1], ctx
->GPR
[9], ctx
->GPR
[17], ctx
->GPR
[25]);
52 kprintf("GPR02 %08x GPR10 %08x GPR18 %08x GPR26 %08x\n",ctx
->GPR
[2], ctx
->GPR
[10], ctx
->GPR
[18], ctx
->GPR
[26]);
53 kprintf("GPR03 %08x GPR11 %08x GPR19 %08x GPR27 %08x\n",ctx
->GPR
[3], ctx
->GPR
[11], ctx
->GPR
[19], ctx
->GPR
[27]);
54 kprintf("GPR04 %08x GPR12 %08x GPR20 %08x GPR28 %08x\n",ctx
->GPR
[4], ctx
->GPR
[12], ctx
->GPR
[20], ctx
->GPR
[28]);
55 kprintf("GPR05 %08x GPR13 %08x GPR21 %08x GPR29 %08x\n",ctx
->GPR
[5], ctx
->GPR
[13], ctx
->GPR
[21], ctx
->GPR
[29]);
56 kprintf("GPR06 %08x GPR14 %08x GPR22 %08x GPR30 %08x\n",ctx
->GPR
[6], ctx
->GPR
[14], ctx
->GPR
[22], ctx
->GPR
[30]);
57 kprintf("GPR07 %08x GPR15 %08x GPR23 %08x GPR31 %08x\n",ctx
->GPR
[7], ctx
->GPR
[15], ctx
->GPR
[23], ctx
->GPR
[31]);
58 kprintf("LR %08x SRR0 %08x SRR1 %08x MSR %08x\n\n", ctx
->LR
, ctx
->SRR0
, ctx
->SRR1
,ctx
->MSR
);
65 kprintf("msr: %08x\n",msr
);
68 void __lwp_dumpcontext_fp(lwp_cntrl
*thrA
,lwp_cntrl
*thrB
)
70 kprintf("_cpu_contextfp_dump(%p,%p)\n",thrA
,thrB
);
75 void __lwp_getthreadlist(lwp_obj **thrs)
80 u32
__lwp_isr_in_progress()
82 register u32 isr_nest_level
;
83 isr_nest_level
= mfspr(272);
84 return isr_nest_level
;
87 static inline void __lwp_msr_setlevel(u32 level
)
91 if(!(level
&CPU_MODES_INTERRUPT_MASK
))
98 static inline u32
__lwp_msr_getlevel()
102 if(msr
&MSR_EE
) return 0;
106 void __lwp_thread_delayended(void *arg
)
108 lwp_cntrl
*thethread
= (lwp_cntrl
*)arg
;
109 #ifdef _LWPTHREADS_DEBUG
110 kprintf("__lwp_thread_delayended(%p)\n",thethread
);
112 if(!thethread
) return;
114 __lwp_thread_dispatchdisable();
115 __lwp_thread_unblock(thethread
);
116 __lwp_thread_dispatchunnest();
119 void __lwp_thread_tickle_timeslice(void *arg
)
124 exec
= _thr_executing
;
125 ticks
= millisecs_to_ticks(1);
127 __lwp_thread_dispatchdisable();
129 if(!exec
->is_preemptible
) {
130 __lwp_wd_insert_ticks(&_lwp_wd_timeslice
,ticks
);
131 __lwp_thread_dispatchunnest();
134 if(!__lwp_stateready(exec
->cur_state
)) {
135 __lwp_wd_insert_ticks(&_lwp_wd_timeslice
,ticks
);
136 __lwp_thread_dispatchunnest();
140 switch(exec
->budget_algo
) {
141 case LWP_CPU_BUDGET_ALGO_NONE
:
143 case LWP_CPU_BUDGET_ALGO_TIMESLICE
:
144 if((--exec
->cpu_time_budget
)==0) {
145 __lwp_thread_resettimeslice();
146 exec
->cpu_time_budget
= _lwp_ticks_per_timeslice
;
151 __lwp_wd_insert_ticks(&_lwp_wd_timeslice
,ticks
);
152 __lwp_thread_dispatchunnest();
155 void __thread_dispatch_fp()
160 _CPU_ISR_Disable(level
);
161 exec
= _thr_executing
;
162 #ifdef _LWPTHREADS_DEBUG
163 __lwp_dumpcontext_fp(exec
,_thr_allocated_fp
);
165 if(!__lwp_thread_isallocatedfp(exec
)) {
166 if(_thr_allocated_fp
) _cpu_context_save_fp(&_thr_allocated_fp
->context
);
167 _cpu_context_restore_fp(&exec
->context
);
168 _thr_allocated_fp
= exec
;
170 _CPU_ISR_Restore(level
);
173 void __thread_dispatch()
176 lwp_cntrl
*exec
,*heir
;
178 _CPU_ISR_Disable(level
);
179 exec
= _thr_executing
;
180 while(_context_switch_want
==TRUE
) {
182 _thread_dispatch_disable_level
= 1;
183 _context_switch_want
= FALSE
;
184 _thr_executing
= heir
;
185 _CPU_ISR_Restore(level
);
187 if(__lwp_thr_libc_reent
) {
188 exec
->libc_reent
= *__lwp_thr_libc_reent
;
189 *__lwp_thr_libc_reent
= heir
->libc_reent
;
192 _cpu_context_switch_ex((void*)&exec
->context
,(void*)&heir
->context
);
194 _cpu_context_switch((void*)&exec
->context
,(void*)&heir
->context
);
196 exec
= _thr_executing
;
197 _CPU_ISR_Disable(level
);
199 _thread_dispatch_disable_level
= 0;
200 _CPU_ISR_Restore(level
);
203 static void __lwp_thread_handler()
208 exec
= _thr_executing
;
209 #ifdef _LWPTHREADS_DEBUG
210 kprintf("__lwp_thread_handler(%p,%d)\n",exec
,_thread_dispatch_disable_level
);
212 level
= exec
->isr_level
;
213 __lwp_msr_setlevel(level
);
214 __lwp_thread_dispatchenable();
215 exec
->wait
.ret_arg
= exec
->entry(exec
->arg
);
217 __lwp_thread_exit(exec
->wait
.ret_arg
);
218 #ifdef _LWPTHREADS_DEBUG
219 kprintf("__lwp_thread_handler(%p): thread returned(%p)\n",exec
,exec
->wait
.ret_arg
);
223 void __lwp_rotate_readyqueue(u32 prio
)
230 ready
= &_lwp_thr_ready
[prio
];
231 exec
= _thr_executing
;
233 if(ready
==exec
->ready
) {
234 __lwp_thread_yield();
238 _CPU_ISR_Disable(level
);
239 if(!__lwp_queue_isempty(ready
) && !__lwp_queue_onenode(ready
)) {
240 node
= __lwp_queue_firstnodeI(ready
);
241 __lwp_queue_appendI(ready
,node
);
243 _CPU_ISR_Flash(level
);
245 if(_thr_heir
->ready
==ready
)
246 _thr_heir
= (lwp_cntrl
*)ready
->first
;
249 _context_switch_want
= TRUE
;
251 #ifdef _LWPTHREADS_DEBUG
252 kprintf("__lwp_rotate_readyqueue(%d,%p,%p)\n",prio
,exec
,_thr_heir
);
254 _CPU_ISR_Restore(level
);
257 void __lwp_thread_yield()
263 exec
= _thr_executing
;
266 _CPU_ISR_Disable(level
);
267 if(!__lwp_queue_onenode(ready
)) {
268 __lwp_queue_extractI(&exec
->object
.node
);
269 __lwp_queue_appendI(ready
,&exec
->object
.node
);
270 _CPU_ISR_Flash(level
);
271 if(__lwp_thread_isheir(exec
))
272 _thr_heir
= (lwp_cntrl
*)ready
->first
;
273 _context_switch_want
= TRUE
;
274 } else if(!__lwp_thread_isheir(exec
))
275 _context_switch_want
= TRUE
;
276 _CPU_ISR_Restore(level
);
279 void __lwp_thread_resettimeslice()
285 exec
= _thr_executing
;
288 _CPU_ISR_Disable(level
);
289 if(__lwp_queue_onenode(ready
)) {
290 _CPU_ISR_Restore(level
);
294 __lwp_queue_extractI(&exec
->object
.node
);
295 __lwp_queue_appendI(ready
,&exec
->object
.node
);
297 _CPU_ISR_Flash(level
);
299 if(__lwp_thread_isheir(exec
))
300 _thr_heir
= (lwp_cntrl
*)ready
->first
;
302 _context_switch_want
= TRUE
;
303 _CPU_ISR_Restore(level
);
306 void __lwp_thread_setstate(lwp_cntrl
*thethread
,u32 state
)
311 ready
= thethread
->ready
;
312 #ifdef _LWPTHREADS_DEBUG
313 kprintf("__lwp_thread_setstate(%d,%p,%p,%08x)\n",_context_switch_want
,_thr_heir
,thethread
,thethread
->cur_state
);
315 _CPU_ISR_Disable(level
);
316 if(!__lwp_stateready(thethread
->cur_state
)) {
317 thethread
->cur_state
= __lwp_clearstate(thethread
->cur_state
,state
);
318 _CPU_ISR_Restore(level
);
322 thethread
->cur_state
= state
;
323 if(__lwp_queue_onenode(ready
)) {
324 __lwp_queue_init_empty(ready
);
325 __lwp_priomap_removefrom(&thethread
->priomap
);
327 __lwp_queue_extractI(&thethread
->object
.node
);
328 _CPU_ISR_Flash(level
);
330 if(__lwp_thread_isheir(thethread
))
331 __lwp_thread_calcheir();
332 if(__lwp_thread_isexec(thethread
))
333 _context_switch_want
= TRUE
;
334 #ifdef _LWPTHREADS_DEBUG
335 kprintf("__lwp_thread_setstate(%d,%p,%p,%08x)\n",_context_switch_want
,_thr_heir
,thethread
,thethread
->cur_state
);
337 _CPU_ISR_Restore(level
);
340 void __lwp_thread_clearstate(lwp_cntrl
*thethread
,u32 state
)
344 _CPU_ISR_Disable(level
);
346 cur_state
= thethread
->cur_state
;
347 if(cur_state
&state
) {
348 cur_state
= thethread
->cur_state
= __lwp_clearstate(cur_state
,state
);
349 if(__lwp_stateready(cur_state
)) {
350 __lwp_priomap_addto(&thethread
->priomap
);
351 __lwp_queue_appendI(thethread
->ready
,&thethread
->object
.node
);
352 _CPU_ISR_Flash(level
);
354 if(thethread
->cur_prio
<_thr_heir
->cur_prio
) {
355 _thr_heir
= thethread
;
356 if(_thr_executing
->is_preemptible
357 || thethread
->cur_prio
==0)
358 _context_switch_want
= TRUE
;
363 _CPU_ISR_Restore(level
);
366 u32
__lwp_evaluatemode()
370 exec
= _thr_executing
;
371 if(!__lwp_stateready(exec
->cur_state
)
372 || (!__lwp_thread_isheir(exec
) && exec
->is_preemptible
)){
373 _context_switch_want
= TRUE
;
379 void __lwp_thread_changepriority(lwp_cntrl
*thethread
,u32 prio
,u32 prependit
)
383 __lwp_thread_settransient(thethread
);
385 if(thethread
->cur_prio
!=prio
)
386 __lwp_thread_setpriority(thethread
,prio
);
388 _CPU_ISR_Disable(level
);
390 thethread
->cur_state
= __lwp_clearstate(thethread
->cur_state
,LWP_STATES_TRANSIENT
);
391 if(!__lwp_stateready(thethread
->cur_state
)) {
392 _CPU_ISR_Restore(level
);
396 __lwp_priomap_addto(&thethread
->priomap
);
398 __lwp_queue_prependI(thethread
->ready
,&thethread
->object
.node
);
400 __lwp_queue_appendI(thethread
->ready
,&thethread
->object
.node
);
402 _CPU_ISR_Flash(level
);
404 __lwp_thread_calcheir();
406 if(!(_thr_executing
==_thr_heir
)
407 && _thr_executing
->is_preemptible
)
408 _context_switch_want
= TRUE
;
410 _CPU_ISR_Restore(level
);
413 void __lwp_thread_setpriority(lwp_cntrl
*thethread
,u32 prio
)
415 thethread
->cur_prio
= prio
;
416 thethread
->ready
= &_lwp_thr_ready
[prio
];
417 __lwp_priomap_init(&thethread
->priomap
,prio
);
418 #ifdef _LWPTHREADS_DEBUG
419 kprintf("__lwp_thread_setpriority(%p,%d,%p)\n",thethread
,prio
,thethread
->ready
);
423 void __lwp_thread_suspend(lwp_cntrl
*thethread
)
428 ready
= thethread
->ready
;
430 _CPU_ISR_Disable(level
);
431 thethread
->suspendcnt
++;
432 if(!__lwp_stateready(thethread
->cur_state
)) {
433 thethread
->cur_state
= __lwp_setstate(thethread
->cur_state
,LWP_STATES_SUSPENDED
);
434 _CPU_ISR_Restore(level
);
438 thethread
->cur_state
= LWP_STATES_SUSPENDED
;
439 if(__lwp_queue_onenode(ready
)) {
440 __lwp_queue_init_empty(ready
);
441 __lwp_priomap_removefrom(&thethread
->priomap
);
443 __lwp_queue_extractI(&thethread
->object
.node
);
445 _CPU_ISR_Flash(level
);
447 if(__lwp_thread_isheir(thethread
))
448 __lwp_thread_calcheir();
450 if(__lwp_thread_isexec(thethread
))
451 _context_switch_want
= TRUE
;
453 _CPU_ISR_Restore(level
);
456 void __lwp_thread_settransient(lwp_cntrl
*thethread
)
461 ready
= thethread
->ready
;
463 _CPU_ISR_Disable(level
);
465 oldstates
= thethread
->cur_state
;
466 thethread
->cur_state
= __lwp_setstate(oldstates
,LWP_STATES_TRANSIENT
);
468 if(__lwp_stateready(oldstates
)) {
469 if(__lwp_queue_onenode(ready
)) {
470 __lwp_queue_init_empty(ready
);
471 __lwp_priomap_removefrom(&thethread
->priomap
);
473 __lwp_queue_extractI(&thethread
->object
.node
);
477 _CPU_ISR_Restore(level
);
480 void __lwp_thread_resume(lwp_cntrl
*thethread
,u32 force
)
484 _CPU_ISR_Disable(level
);
487 thethread
->suspendcnt
= 0;
489 thethread
->suspendcnt
--;
491 if(thethread
->suspendcnt
>0) {
492 _CPU_ISR_Restore(level
);
496 state
= thethread
->cur_state
;
497 if(state
&LWP_STATES_SUSPENDED
) {
498 state
= thethread
->cur_state
= __lwp_clearstate(thethread
->cur_state
,LWP_STATES_SUSPENDED
);
499 if(__lwp_stateready(state
)) {
500 __lwp_priomap_addto(&thethread
->priomap
);
501 __lwp_queue_appendI(thethread
->ready
,&thethread
->object
.node
);
502 _CPU_ISR_Flash(level
);
503 if(thethread
->cur_prio
<_thr_heir
->cur_prio
) {
504 _thr_heir
= thethread
;
505 if(_thr_executing
->is_preemptible
506 || thethread
->cur_prio
==0)
507 _context_switch_want
= TRUE
;
511 _CPU_ISR_Restore(level
);
514 void __lwp_thread_loadenv(lwp_cntrl
*thethread
)
516 u32 stackbase
,sp
,size
;
517 u32 r2
,r13
,msr_value
;
519 thethread
->context
.FPSCR
= 0x000000f8;
521 stackbase
= (u32
)thethread
->stack
;
522 size
= thethread
->stack_size
;
524 // tag both bottom & head of stack
525 *((u32
*)stackbase
) = 0xDEADBABE;
526 sp
= stackbase
+size
-CPU_MINIMUM_STACK_FRAME_SIZE
;
527 sp
&= ~(CPU_STACK_ALIGNMENT
-1);
530 thethread
->context
.GPR
[1] = sp
;
532 msr_value
= (MSR_ME
|MSR_IR
|MSR_DR
|MSR_RI
);
533 if(!(thethread
->isr_level
&CPU_MODES_INTERRUPT_MASK
))
536 thethread
->context
.MSR
= msr_value
;
537 thethread
->context
.LR
= (u32
)__lwp_thread_handler
;
539 __asm__
__volatile__ ("mr %0,2; mr %1,13" : "=r" ((r2
)), "=r" ((r13
)));
540 thethread
->context
.GPR
[2] = r2
;
541 thethread
->context
.GPR
[13] = r13
;
543 #ifdef _LWPTHREADS_DEBUG
544 kprintf("__lwp_thread_loadenv(%p,%p,%d,%p)\n",thethread
,(void*)stackbase
,size
,(void*)sp
);
549 void __lwp_thread_ready(lwp_cntrl
*thethread
)
554 _CPU_ISR_Disable(level
);
555 #ifdef _LWPTHREADS_DEBUG
556 kprintf("__lwp_thread_ready(%p)\n",thethread
);
558 thethread
->cur_state
= LWP_STATES_READY
;
559 __lwp_priomap_addto(&thethread
->priomap
);
560 __lwp_queue_appendI(thethread
->ready
,&thethread
->object
.node
);
561 _CPU_ISR_Flash(level
);
563 __lwp_thread_calcheir();
565 if(!(__lwp_thread_isexec(heir
)) && _thr_executing
->is_preemptible
)
566 _context_switch_want
= TRUE
;
568 _CPU_ISR_Restore(level
);
571 u32
__lwp_thread_init(lwp_cntrl
*thethread
,void *stack_area
,u32 stack_size
,u32 prio
,u32 isr_level
,bool is_preemtible
)
573 u32 act_stack_size
= 0;
575 #ifdef _LWPTHREADS_DEBUG
576 kprintf("__lwp_thread_init(%p,%p,%d,%d,%d)\n",thethread
,stack_area
,stack_size
,prio
,isr_level
);
580 if(!__lwp_stack_isenough(stack_size
))
581 act_stack_size
= CPU_MINIMUM_STACK_SIZE
;
583 act_stack_size
= stack_size
;
585 act_stack_size
= __lwp_stack_allocate(thethread
,act_stack_size
);
586 if(!act_stack_size
) return 0;
588 thethread
->stack_allocated
= TRUE
;
590 thethread
->stack
= stack_area
;
591 act_stack_size
= stack_size
;
592 thethread
->stack_allocated
= FALSE
;
594 thethread
->stack_size
= act_stack_size
;
596 __lwp_threadqueue_init(&thethread
->join_list
,LWP_THREADQ_MODEFIFO
,LWP_STATES_WAITING_FOR_JOINATEXIT
,0);
598 memset(&thethread
->context
,0,sizeof(thethread
->context
));
599 memset(&thethread
->wait
,0,sizeof(thethread
->wait
));
601 thethread
->budget_algo
= (prio
<128 ? LWP_CPU_BUDGET_ALGO_NONE
: LWP_CPU_BUDGET_ALGO_TIMESLICE
);
602 thethread
->is_preemptible
= is_preemtible
;
603 thethread
->isr_level
= isr_level
;
604 thethread
->real_prio
= prio
;
605 thethread
->cur_state
= LWP_STATES_DORMANT
;
606 thethread
->cpu_time_budget
= _lwp_ticks_per_timeslice
;
607 thethread
->suspendcnt
= 0;
608 thethread
->res_cnt
= 0;
609 __lwp_thread_setpriority(thethread
,prio
);
611 __libc_create_hook(_thr_executing
,thethread
);
616 void __lwp_thread_close(lwp_cntrl
*thethread
)
622 __lwp_thread_setstate(thethread
,LWP_STATES_TRANSIENT
);
624 if(!__lwp_threadqueue_extractproxy(thethread
)) {
625 if(__lwp_wd_isactive(&thethread
->timer
))
626 __lwp_wd_remove_ticks(&thethread
->timer
);
629 _CPU_ISR_Disable(level
);
630 value_ptr
= (void**)thethread
->wait
.ret_arg
;
631 while((p
=__lwp_threadqueue_dequeue(&thethread
->join_list
))!=NULL
) {
632 *(void**)p
->wait
.ret_arg
= value_ptr
;
634 thethread
->cpu_time_budget
= 0;
635 thethread
->budget_algo
= LWP_CPU_BUDGET_ALGO_NONE
;
636 _CPU_ISR_Restore(level
);
638 __libc_delete_hook(_thr_executing
,thethread
);
640 if(__lwp_thread_isallocatedfp(thethread
))
641 __lwp_thread_deallocatefp();
643 __lwp_stack_free(thethread
);
645 __lwp_objmgr_close(thethread
->object
.information
,&thethread
->object
);
646 __lwp_objmgr_free(thethread
->object
.information
,&thethread
->object
);
649 void __lwp_thread_closeall()
653 lwp_cntrl
*ptr
,*next
;
654 #ifdef _LWPTHREADS_DEBUG
655 kprintf("__lwp_thread_closeall(enter)\n");
657 _CPU_ISR_Disable(level
);
658 for(i
=0;i
<LWP_MAXPRIORITIES
;i
++) {
659 header
= &_lwp_thr_ready
[i
];
660 ptr
= (lwp_cntrl
*)header
->first
;
661 while(ptr
!=(lwp_cntrl
*)__lwp_queue_tail(&_lwp_thr_ready
[i
])) {
662 next
= (lwp_cntrl
*)ptr
->object
.node
.next
;
663 if(ptr
!=_thr_executing
)
664 __lwp_thread_close(ptr
);
669 _CPU_ISR_Restore(level
);
670 #ifdef _LWPTHREADS_DEBUG
671 kprintf("__lwp_thread_closeall(leave)\n");
675 void __lwp_thread_exit(void *value_ptr
)
677 __lwp_thread_dispatchdisable();
678 _thr_executing
->wait
.ret_arg
= (u32
*)value_ptr
;
679 __lwp_thread_close(_thr_executing
);
680 __lwp_thread_dispatchenable();
683 u32
__lwp_thread_start(lwp_cntrl
*thethread
,void* (*entry
)(void*),void *arg
)
685 #ifdef _LWPTHREADS_DEBUG
686 kprintf("__lwp_thread_start(%p,%p,%p,%d)\n",thethread
,entry
,arg
,thethread
->cur_state
);
688 if(__lwp_statedormant(thethread
->cur_state
)) {
689 thethread
->entry
= entry
;
690 thethread
->arg
= arg
;
691 __lwp_thread_loadenv(thethread
);
692 __lwp_thread_ready(thethread
);
693 __libc_start_hook(_thr_executing
,thethread
);
699 void __lwp_thread_startmultitasking()
701 _lwp_exitfunc
= NULL
;
703 __sys_state_set(SYS_STATE_BEGIN_MT
);
704 __sys_state_set(SYS_STATE_UP
);
706 _context_switch_want
= FALSE
;
707 _thr_executing
= _thr_heir
;
708 #ifdef _LWPTHREADS_DEBUG
709 kprintf("__lwp_start_multitasking(%p,%p)\n",_thr_executing
,_thr_heir
);
711 __lwp_thread_starttimeslice();
712 _cpu_context_switch((void*)&core_context
,(void*)&_thr_heir
->context
);
714 if(_lwp_exitfunc
) _lwp_exitfunc();
717 void __lwp_thread_stopmultitasking(void (*exitfunc
)())
719 _lwp_exitfunc
= exitfunc
;
720 if(__sys_state_get()!=SYS_STATE_SHUTDOWN
) {
721 __lwp_thread_stoptimeslice();
722 __sys_state_set(SYS_STATE_SHUTDOWN
);
723 _cpu_context_switch((void*)&_thr_executing
->context
,(void*)&core_context
);
727 void __lwp_thread_coreinit()
731 #ifdef _LWPTHREADS_DEBUG
732 kprintf("__lwp_sys_init()\n\n");
734 __lwp_thread_dispatchinitialize();
735 __lwp_thread_inittimeslice();
737 _context_switch_want
= FALSE
;
738 _thr_executing
= NULL
;
740 _thr_allocated_fp
= NULL
;
741 _lwp_ticks_per_timeslice
= 10;
743 memset(&core_context
,0,sizeof(core_context
));
745 for(index
=0;index
<=LWP_PRIO_MAX
;index
++)
746 __lwp_queue_init_empty(&_lwp_thr_ready
[index
]);
748 __sys_state_set(SYS_STATE_BEFORE_MT
);