Changes

3,519 bytes added ,  20:20, 25 May 2015
no edit summary
Line 8: Line 8:     
Though it is possible to run multi-threaded programs, running those on different cores is not possible "as-is". One core is always dedicated to the OS, hence you will never get 100% of both cores.
 
Though it is possible to run multi-threaded programs, running those on different cores is not possible "as-is". One core is always dedicated to the OS, hence you will never get 100% of both cores.
 +
 +
Using CloseHandle() with a KThread handle will terminate the specified thread, only if the reference count reaches 0.
 +
 +
Lower priority values give the thread higher priority. For userland apps, priorities between 0x18 and 0x3F are allowed. The priority of the app's main thread seems to be 0x30.
 +
 +
The thread scheduler is cooperative, therefore if a thread takes up all the CPU time (for example if it enters an endless loop), all the other threads that run on the same CPU core won't get a chance to run. The main way of yielding another thread is using an address arbiter.
    
== Usage ==
 
== Usage ==
   −
=== CreateThread ===
+
=== CreateThread (svc 0x08) ===
 +
 
 +
'''Definition'''
 +
Result CreateThread(Handle* thread, func entrypoint, u32 arg, u32 stacktop, s32 threadpriority, s32 processorid);
 +
 
 +
'''Configuration'''
 +
R0=s32 threadpriority
 +
R1=func entrypoint
 +
R2=u32 arg
 +
R3=u32 stacktop
 +
R4=s32 processorid
 +
 
 +
Result result=R0
 +
Handle* thread=R1
 +
 
 +
'''Details'''
 +
The processorid parameter specifies which processor the thread can run on. Non-negative values correspond to a specific CPU. (e.g. 0 for the Appcore and 1 for the Syscore on Old3DS) Special value -1 means all CPUs, and -2 means the default CPU for the process (Read from the [[NCCH/Extended Header|Exheader]], usually 0 for applications, 1 for system services). Games usually create threads using -2.
 +
 
 +
With the Old3DS kernel, the s32 processorid must be <=2.
 +
 
 +
With the New3DS kernel: processorid must be <= <total cores(MPCore "SCU Configuration Register" CPU number value + 1)>. When processorid==0x2 and the process is not an APPLICATION mem-region process, exheader kernel-flags bitmask 0x2000 must be set otherwise error 0xD9001BEA is returned. When processorid==0x3 and the process is not an APPLICATION mem-region process, error 0xD9001BEA is returned. These are the only restriction checks done by the kernel for processorid.
 +
 
 +
The thread priority value must be in the following range: 0x0..0x3F.
 +
 
 +
The stacktop must be aligned to 0x8-bytes, otherwise when not aligned to 0x8-bytes the ARM11 kernel clears the low 3-bits of the stacktop address.
 +
 
 +
The input address used for Entrypoint_Param and StackTop are normally the same, however these can be arbitrary. For the main thread the Entrypoint_Param is value 0.
 +
 
 +
=== ExitThread (svc 0x09)===
 +
 
 +
'''Definition'''
 +
void ExitThread(void);
 +
 
 +
=== SleepThread (svc 0x0A)===
 +
 
 +
'''Definition'''
 +
void SleepThread(s64 nanoseconds);
 +
 
 +
=== GetThreadPriority (svc 0x0B) ===
   −
=== ExitThread ===
+
'''Definition'''
 +
Result GetThreadPriority(s32* priority, Handle thread);
   −
=== SleepThread ===
+
'''asm'''
 +
.global svcGetThreadPriority
 +
.type svcGetThreadPriority, %function
 +
svcGetThreadPriority:
 +
str r0, [sp, #-0x4]!
 +
svc 0x0B
 +
ldr r3, [sp], #4
 +
str r1, [r3]
 +
bx  lr
   −
=== GetThreadPriority ===
+
=== SetThreadPriority (svc 0x0C) ===
   −
=== SetThreadPriority ===
+
'''Definition'''
 +
Result SetThreadPriority(Handle thread, s32 priority);
    
=== OpenThread ===
 
=== OpenThread ===
 +
 +
'''Definition'''
 +
Result OpenThread(Handle* thread, Handle process, u32 threadId);
    
=== GetProcessIdOfThread ===
 
=== GetProcessIdOfThread ===
 +
 +
'''Definition'''
 +
Result GetProcessIdOfThread(u32* processId, Handle thread);
    
=== GetThreadId ===
 
=== GetThreadId ===
 +
 +
'''Definition'''
 +
Result GetThreadId(u32* threadId, Handle thread);
    
=== GetThreadInfo ===
 
=== GetThreadInfo ===
 +
 +
'''Definition'''
 +
Result GetThreadInfo(s64* out, Handle thread, ThreadInfoType type);
 +
 +
{| class="wikitable" border="1"
 +
!  ThreadInfoType value
 +
!  Description
 +
|-
 +
| ?
 +
| ?
 +
|}
    
=== GetThreadContext ===
 
=== GetThreadContext ===
 +
 +
'''Definition'''
 +
Result GetThreadContext(ThreadContext* context, Handle thread);
 +
 +
'''Details'''
 +
Stubbed?
    
== Core affinity ==  
 
== Core affinity ==  
    
=== GetThreadAffinityMask ===
 
=== GetThreadAffinityMask ===
 +
 +
'''Definition'''
 +
Result GetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount);
    
=== SetThreadAffinityMask ===
 
=== SetThreadAffinityMask ===
 +
 +
'''Definition'''
 +
Result SetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount);
    
=== GetThreadIdealProcessor ===
 
=== GetThreadIdealProcessor ===
 +
 +
'''Definition'''
 +
Result GetThreadIdealProcessor(s32* processorid, Handle thread);
    
=== SetThreadIdealProcessor ===
 
=== SetThreadIdealProcessor ===
Line 56: Line 145:     
== Mutex (normal) ==
 
== Mutex (normal) ==
 +
 +
For Kernel implementation details, see [[KMutex]]
    
===  CreateMutex ===
 
===  CreateMutex ===
48

edits