ARM9 OS: Difference between revisions
Hallowizer (talk | contribs) →Threads: info on how the scheduler works |
Hallowizer (talk | contribs) →Threads: kernelSp is a system stack used for thread cleanup and SVCs |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 4: | Line 4: | ||
The scheduler only runs the thread with the highest priority, and does not switch between threads if two threads have the same priority. Because of this, rescheduling only happens when a thread-related function is called and the thread with the highest priority can no longer run. | The scheduler only runs the thread with the highest priority, and does not switch between threads if two threads have the same priority. Because of this, rescheduling only happens when a thread-related function is called and the thread with the highest priority can no longer run. | ||
<pre> | <pre> | ||
struct | struct OSMathContext { | ||
u64 REG_DIV_NUMER; // 0x0 | |||
u64 REG_DIV_DENOM; // 0x8 | |||
u64 SQRT_PARAM; // 0x10 | |||
u16 REG_DIVCNT; // 0x18 | u16 REG_DIVCNT; // 0x18 | ||
u16 REG_SQRTCNT; // 0x1a | u16 REG_SQRTCNT; // 0x1a | ||
| Line 30: | Line 30: | ||
void *lr; // 0x3c | void *lr; // 0x3c | ||
void *pc; // 0x40 | void *pc; // 0x40 | ||
void * | void *systemStack; // 0x44 | ||
struct | struct OSMathContext math; // 0x48 | ||
} | } | ||
| Line 43: | Line 43: | ||
struct OSThreadQueue *queue; // 0x78 | struct OSThreadQueue *queue; // 0x78 | ||
struct OSThreadLink linkQueue; // 0x7c | struct OSThreadLink linkQueue; // 0x7c | ||
u32 | struct OSMutex *mutex; // 0x84 - set to the mutex the thread is currently trying to lock | ||
struct | struct OSMutexQueue queueMutex; // 0x88 | ||
// | void *stackLo; // 0x90 | ||
void *stackHi; // 0x94 | |||
void *unknown2; // 0x98 | |||
struct OSThreadQueue queueJoin; // 0x9c | |||
u32 unknown3[3]; // 0xa4 | |||
struct OSAlarm *timedSleepAlarm; // 0xb0 | |||
void (*cleanupFunc)(u32 res); // 0xb4 | |||
u32 unknown4[2]; | |||
} | } | ||
| Line 67: | Line 74: | ||
struct OSMutexQueue { | struct OSMutexQueue { | ||
struct OSMutex *head; | struct OSMutex *head; | ||
struct OSMutex *tail; | struct OSMutex *tail; | ||
| Line 87: | Line 93: | ||
== Memory allocation == | == Memory allocation == | ||
3 types of heaps exist: EXPH (exponential heap), FRMH (frame heap), and UNTH (unit heap). | 3 types of heaps exist: EXPH (exponential heap), FRMH (frame heap), and UNTH (unit heap). | ||
== Time == | |||
Timer 0 is used to keep track of global time by manually incrementing a global, while timer 1 is used to generate an interrupt for alarms. The OS orders the alarms by alert time, so that it only needs to keep track of the frontmost alarm. | |||
<pre> | |||
struct OSAlarm { | |||
void (*handler)(void *userData); | |||
void *userData; | |||
u32 unknown; | |||
u64 alertTime; | |||
struct OSAlarm *prev; | |||
struct OSAlarm *next; | |||
u64 repeatInterval; // 0 for non-repeating alarms | |||
u64 repeatStart; // undefined value for non-repeating alarms | |||
} | |||
struct OSAlarmQueue { | |||
u32 unknown; | |||
struct OSAlarm *head; | |||
struct OSAlarm *tail; | |||
} | |||
</pre> | |||
== Interrupts == | |||
The interrupt handler called by the [[ARM9 BIOS]] calls a handler in a table mapping the raw IRQ IDs to handlers. Each handler is either a no-op (not listed in the table below) or a stub that calls <code>__OSDispatchInterrupt</code> with an OS interrupt ID. <code>__OSDispatchInterrupt</code> then calls the handler registered with <code>__OSSetInterruptHandler</code>. | |||
{| class="wikitable sortable" | |||
! Hardware ID | |||
! Translated ID | |||
! Name | |||
|- | |||
| 3 | |||
| 8 | |||
| Timer 0 overflow | |||
|- | |||
| 4 | |||
| 9 | |||
| Timer 1 overflow | |||
|- | |||
| 5 | |||
| 10 | |||
| Timer 2 overflow | |||
|- | |||
| 6 | |||
| 11 | |||
| Timer 3 overflow | |||
|- | |||
| 8 | |||
| 0 | |||
| DMA 0 | |||
|- | |||
| 9 | |||
| 1 | |||
| DMA 1 | |||
|- | |||
| 10 | |||
| 2 | |||
| DMA 2 | |||
|- | |||
| 11 | |||
| 3 | |||
| DMA 3 | |||
|- | |||
| 28 | |||
| 4 | |||
| New DMA 0 | |||
|- | |||
| 29 | |||
| 5 | |||
| New DMA 1 | |||
|- | |||
| 30 | |||
| 6 | |||
| New DMA 2 | |||
|- | |||
| 31 | |||
| 7 | |||
| New DMA 3 | |||
|} | |||