Line 1: |
Line 1: |
− | [[Category:Kernel objects]] | + | [[Category:Kernel synchronization objects]] |
− | class [[KThread]] extends [[KSynchronizationObject]]; | + | [[Category:Kernel interrupt events]] |
| + | class [[KThread]] extends [[KSynchronizationObject]], [[KTimeableInterruptEvent]], [[KSendableInterruptEvent]] and [[KSchedulableInterruptEvent]]; |
| | | |
| Size : 0xB0 bytes | | Size : 0xB0 bytes |
Line 6: |
Line 7: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Offset | + | ! Offset |
| ! Type | | ! Type |
− | ! Description | + | ! Description |
| |- | | |- |
| | 0x0 | | | 0x0 |
Line 17: |
Line 18: |
| | u32 | | | u32 |
| | Reference count | | | Reference count |
| + | |- |
| + | | 0x8 |
| + | | u32 |
| + | | Count of KThreads that sync with this object - number of nodes in the linked list below |
| + | |- |
| + | | 0xC |
| + | | KLinkedListNode* |
| + | | Pointer to first KLinkedListNode in node list of KThreads that sync with this object |
| + | |- |
| + | | 0x10 |
| + | | KLinkedListNode* |
| + | | Pointer to last KLinkedListNode in node list of KThreads that sync with this object |
| + | |- |
| + | | 0x14 |
| + | | [[KTimeableInterruptEvent]] |
| + | | Used to suspend threads (*this) |
| + | |- |
| + | | 0x24 |
| + | | [[KSendableInterruptEvent]] |
| + | | Interrupt event (*this) sent to terminate a thread, except in the case just below |
| + | |- |
| + | | 0x2C |
| + | | [[KSchedulableInterruptEvent]] |
| + | | Interrupt event (*this) scheduled by the IRQ handler when the thread should terminate (*this) |
| + | |- |
| + | | 0x34 |
| + | | u8 |
| + | | Scheduling mask |
| + | |- |
| + | | 0x35 |
| + | | u8 |
| + | | Set to 1 when a thread is woken up from a svcSendSyncRequest call due to the ServerSession endpoint closing down |
| + | |- |
| + | | 0x36 |
| + | | s8 |
| + | | Indicates that the thread shall terminate |
| + | |- |
| + | | 0x37 |
| + | | u8 |
| + | | Indicates there was an error translating the parameters in the command buffer during an IPC call |
| + | |- |
| + | | 0x38 |
| + | | KDebugThread* |
| + | | Pointer to KDebugThread object used with the current KThread |
| + | |- |
| + | | 0x3C |
| + | | u32 |
| + | | Base thread priority |
| |- | | |- |
| | 0x40 | | | 0x40 |
| | u32 | | | u32 |
− | | Arbitration ??? | + | | Pointer to object the KThread is waiting on- can be a timer, event, session, etc. |
| + | |- |
| + | | 0x44 |
| + | | Result |
| + | | Status for object above |
| |- | | |- |
| | 0x48 | | | 0x48 |
− | | u32 | + | | KObjectMutex* |
− | | Arbitration ??? | + | | Locking kernel mutex |
| |- | | |- |
| | 0x4C | | | 0x4C |
| | u32 | | | u32 |
| | Arbitration address | | | Arbitration address |
| + | |- |
| + | | 0x50 |
| + | | KLinkedListNode* |
| + | | Pointer to first KLinkedListNode in node list of objects this thread is waiting on |
| + | |- |
| + | | 0x54 |
| + | | KLinkedListNode* |
| + | | Pointer to last KLinkedListNode in node list of objects this thread is |
| + | |- |
| + | | 0x5C |
| + | | [[KMutex|KMutexLinkedList]] * |
| + | | Set in some very specific circumstances |
| + | |- |
| + | | 0x60 |
| + | | u32 |
| + | | Count of KMutex objects this thread is using |
| + | |- |
| + | | 0x64 |
| + | | KLinkedListNode* |
| + | | Pointer to first KLinkedListNode in node list of KMutex objects this thread is using |
| + | |- |
| + | | 0x68 |
| + | | KLinkedListNode* |
| + | | Pointer to last KLinkedListNode in node list of KMutex objects this thread is using |
| |- | | |- |
| | 0x6C | | | 0x6C |
| | s32 | | | s32 |
− | | Thread priority | + | | Dynamic thread priority |
| |- | | |- |
| | 0x70 | | | 0x70 |
| | s32 | | | s32 |
− | | Processor that created the thread | + | | Processor that created the thread (in the sense of "first ran") ; processor the thread is running in |
| + | |- |
| + | | 0x74 |
| + | | [[KResourceLimit|KPreemptionTimer]] * |
| + | | Points to [[KResourceLimit]]+0x60, which among other things holds the amount of CPU time available in ticks, or NULL |
| + | |- |
| + | | 0x7C |
| + | | u8 |
| + | | Thread is alive |
| + | |- |
| + | | 0x7D |
| + | | u8 |
| + | | Thread has been terminated |
| + | |- |
| + | | 0x7E |
| + | | u8 |
| + | | Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel |
| |- | | |- |
| | 0x80 | | | 0x80 |
Line 48: |
Line 141: |
| | 0x88 | | | 0x88 |
| | u32* | | | u32* |
− | | ptr = *(KThread+0x8C) - 0xB0 | + | | Ptr to svc mode register storage for KThread inside the thread context. |
| |- | | |- |
| | 0x8C | | | 0x8C |
| | u32* | | | u32* |
− | | End-address of the page for this thread allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. | + | | End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread. |
| |- | | |- |
| | 0x90 | | | 0x90 |
Line 60: |
Line 153: |
| | 0x94 | | | 0x94 |
| | void* | | | void* |
− | | Ptr to threadlocalstorage | + | | Ptr to [[Thread Local Storage]] |
| + | |- |
| + | | 0x98 |
| + | | void* |
| + | | Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem |
| |- | | |- |
| | 0xA0 | | | 0xA0 |
− | | KThread* | + | | KThreadLinkedListNode |
− | | Previous (virtual address) | + | | Previous and next scheduled threads |
| |- | | |- |
− | | 0xA4 | + | | 0xA8 |
− | | KThread* | + | | KThreadLinkedList * |
− | | Next (virtual address) | + | | Pointer to linked list of scheduled threads that has stolen it, or 0 if in normal list |
| |- | | |- |
− | | 0xA8 | + | | 0xAC |
− | | struct { KThread* first; KThread* last; } ptr | + | | s32 |
− | | Pointer to linked list that has stolen it, or 0 if in normal list | + | | Priority to restore after sleep if suspended, otherwise -1 |
| + | |} |
| + | |
| + | With the following declarations: <code>struct KThreadLinkedList { KThread *first, *last; };</code> and <code>struct KThreadLinkedListNode { KThread *prev, *next; };</code>. |
| + | |
| + | =Thread Scheduling Mask= |
| + | The thread scheduling mask is made of a low nibble (enum) and a high nibble (bitfield). |
| + | |
| + | Low nibble: |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0 |
| + | | The thread is not scheduled |
| + | |- |
| + | | 1 |
| + | | The thread is scheduled |
| + | |- |
| + | | 2 |
| + | | The thread is being terminated |
| + | |} |
| + | |
| + | High nibble: |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Mask |
| + | ! Description |
| + | |- |
| + | | 0 |
| + | | Nothing special |
| + | |- |
| + | | 0x8 (bit 3) |
| + | | The thread has been debug-locked |
| |} | | |} |
| + | |
| + | A thread is scheduled *if and only if* its (full) scheduling mask is exactly 1. This allows debug-(un)locking of threads to be done transparently. |
| + | =Thread Affinity Mask= |
| + | |
| + | If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1. |
| + | |
| + | If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1. |