mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
243 lines
5.8 KiB
Text
243 lines
5.8 KiB
Text
|
|
Some interesting facts :
|
|
-------------------------
|
|
|
|
- threads are rescheduled after every interrupt, in dispatch handler
|
|
- same priorities are controlled by "round robin"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
struct OSThread
|
|
{
|
|
// theese offsets are correct (see os/OSContext.h)
|
|
OSContext context; +0
|
|
{
|
|
u32 gpr[32]; +0
|
|
u32 cr; +128
|
|
u32 lr; +132
|
|
u32 ctr; +136
|
|
u32 xer; +140
|
|
f64 fpr[32]; +144
|
|
u32 fpscr_pad; +400
|
|
u32 fpscr; +404
|
|
u32 srr0; +408
|
|
u32 srr1; +412
|
|
u16 mode; +416
|
|
u16 state; +418
|
|
u32 gqr[8]; +420
|
|
f64 psf[32]; +456
|
|
} OSContext;
|
|
|
|
// all offsets are correct
|
|
u16 state; +712
|
|
u16 attr; +714
|
|
s32 suspend; +716
|
|
OSPriority priority; +720
|
|
OSPriority base; +724
|
|
void* val; +728
|
|
|
|
OSThreadQueue* queue; +732
|
|
OSThreadLink link;
|
|
OSThread* next; +736
|
|
OSThread* prev; +740
|
|
OSThreadQueue queueJoin;
|
|
OSThread* head; +744
|
|
OSThread* tail; +748
|
|
OSMutex* mutex; +752
|
|
OSMutexQueue queueMutex;
|
|
OSMutex* head; +756
|
|
OSMutex* tail; +760
|
|
OSThreadLink linkActive;
|
|
OSThread* next; +764
|
|
OSThread* prev; +768
|
|
|
|
u8* stackBase; +772
|
|
u32* stackEnd; +776
|
|
};
|
|
|
|
// definitions, locals etc
|
|
|
|
static u32 RunQueueBits;
|
|
static BOOL RunQueueHint;
|
|
static s32 Reschedule;
|
|
|
|
OSThreadQueue RunQueue[32];
|
|
OSThread IdleThread; // +256
|
|
OSThread DefaultThread; // +1040
|
|
OSContext IdleContext; // +1824
|
|
|
|
// from os/OSLoMem.h
|
|
OSThread *__OSDefaultThread AT_ADDRESS(OS_BASE_CACHED | 0x00D8);
|
|
OSThreadLink __OSLinkActive AT_ADDRESS(OS_BASE_CACHED | 0x00DC);
|
|
OSThread *__OSCurrentThread AT_ADDRESS(OS_BASE_CACHED | 0x00E4);
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// OSThread.c
|
|
|
|
// TODO : check teh damn offsets
|
|
void __OSThreadInit(void)
|
|
{
|
|
OSThread *thread;
|
|
OSPriority prio;
|
|
|
|
DefaultThread.state = OS_THREAD_STATE_RUNNING;
|
|
DefaultThread.attr = OS_THREAD_ATTR_DETACH;
|
|
DefaultThread.priority =
|
|
DefaultThread.base = 16;
|
|
DefaultThread.suspend = 0;
|
|
DefaultThread.val = (void *)0xffffffff;
|
|
DefaultThread.mutex = NULL;
|
|
|
|
OSInitThreadQueue(&DefaultThread.queueJoin);
|
|
|
|
DefaultThread.queueMutex.head = DefaultThread.queueMutex.tail = NULL;
|
|
|
|
__OSDefaultThread = &DefaultThread;
|
|
|
|
OSClearContext(&DefaultThread.context);
|
|
OSSetCurrentContext(&DefaultThread.context);
|
|
|
|
DefaultThread.stackBase = _stack_addr;
|
|
DefaultThread.stackEnd = _stack_end;
|
|
|
|
*DefaultThread.stackEnd = OS_THREAD_STACK_MAGIC;
|
|
|
|
RunQueueHint = FALSE;
|
|
RunQueueBits = 0;
|
|
__OSCurrentThread = &DefaultThread;
|
|
|
|
for(prio=OS_PRIORITY_MIN; prio<=OS_PRIORITY_MAX; prio++)
|
|
{
|
|
OSInitThreadQueue(&RunQueue[prio]);
|
|
}
|
|
|
|
//
|
|
// start active threads queue
|
|
//
|
|
|
|
OSInitThreadQueue(&__OSLinkActive);
|
|
|
|
if((thread = __OSLinkActive.tail) == NULL)
|
|
{
|
|
__OSLinkActive.head = &DefaultThread;
|
|
}
|
|
else
|
|
{
|
|
thread.next = &DefaultThread;
|
|
}
|
|
|
|
DefaultThread.prev = thread;
|
|
DefaultThread.next = NULL;
|
|
|
|
__OSLinkActive.tail = &DefaultThread;
|
|
|
|
OSClearContext(&IdleContext.context);
|
|
|
|
Reschedule = 0;
|
|
}
|
|
|
|
void OSInitThreadQueue(OSThreadQueue *queue)
|
|
{
|
|
queue->head = queue->tail = NULL;
|
|
}
|
|
|
|
OSThread *OSGetCurrentThread(void)
|
|
{
|
|
return __OSCurrentThread;
|
|
}
|
|
|
|
void __OSSwitchThread(OSThread *nextThread)
|
|
{
|
|
__OSCurrentThread = nextThread;
|
|
|
|
OSSetCurrentContext(nextThread->context);
|
|
OSLoadContext(nextThread->context);
|
|
}
|
|
|
|
BOOL OSIsThreadSuspended(OSThread *thread)
|
|
{
|
|
return (thread->suspend > 0) ? (TRUE) : (FALSE);
|
|
}
|
|
|
|
BOOL OSIsThreadTerminated(OSThread *thread)
|
|
{
|
|
return (thread->state == OS_THREAD_STATE_MORIBUND) ?
|
|
(
|
|
TRUE
|
|
) :
|
|
(
|
|
(thread->state == 0) ? ( TRUE ) : ( FALSE );
|
|
) ;
|
|
}
|
|
|
|
BOOL __OSIsThreadActive(OSThread *thread)
|
|
{
|
|
OSThread *active;
|
|
|
|
if(thread->state != 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// try to find thread in active threads
|
|
//
|
|
|
|
active = __OSLinkActive.head
|
|
|
|
while(active)
|
|
{
|
|
// our thread is in active threads queue
|
|
if(active == thread)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// get next thread from list
|
|
active = active->linkActive.next;
|
|
}
|
|
|
|
// this thread isn't active
|
|
return FALSE;
|
|
}
|
|
|
|
s32 OSDisableScheduler()
|
|
{
|
|
BOOL enabled = OSDisableInterrupts();
|
|
s32 count = Reschedule++;
|
|
OSRestoreInterrupts(enabled);
|
|
return count;
|
|
}
|
|
|
|
s32 OSEnableScheduler()
|
|
{
|
|
BOOL enabled = OSDisableInterrupts();
|
|
s32 count = Reschedule--;
|
|
OSRestoreInterrupts(enabled);
|
|
return count;
|
|
}
|
|
|
|
void SetRun(OSThread *thread)
|
|
{
|
|
OSThread *__prev;
|
|
|
|
thread->queue = &RunQueue[thread->priority];
|
|
|
|
if((__prev = thread->queue.tail) == NULL)
|
|
{
|
|
thread->queue.head = thread;
|
|
}
|
|
else
|
|
{
|
|
__prev->link.next = thread;
|
|
}
|
|
|
|
thread->link.prev = __prev;
|
|
|
|
thread->link.next = NULL;
|
|
thread->queue->prev = thread;
|
|
|
|
RunQueueBits |= 1 << (31 - thread->priotity);
|
|
RunQueueHint = TRUE;
|
|
}
|