mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 04:22:50 +02:00
Introducing thread..
This commit is contained in:
parent
a9555bb5b5
commit
85538c9fb3
@ -16,6 +16,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <switch/kernel/tmem.h>
|
#include <switch/kernel/tmem.h>
|
||||||
#include <switch/kernel/mutex.h>
|
#include <switch/kernel/mutex.h>
|
||||||
|
#include <switch/kernel/thread.h>
|
||||||
#include <switch/kernel/virtmem.h>
|
#include <switch/kernel/virtmem.h>
|
||||||
|
|
||||||
#include <switch/services/sm.h>
|
#include <switch/services/sm.h>
|
||||||
|
16
nx/include/switch/kernel/thread.h
Normal file
16
nx/include/switch/kernel/thread.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
typedef struct {
|
||||||
|
Handle handle;
|
||||||
|
ThreadFunc entry;
|
||||||
|
void* arg;
|
||||||
|
void* stack_mem;
|
||||||
|
void* stack_mirror;
|
||||||
|
size_t stack_sz;
|
||||||
|
} Thread;
|
||||||
|
|
||||||
|
Result threadCreate(
|
||||||
|
Thread* t, ThreadFunc entry, void* arg, size_t stack_sz, int prio,
|
||||||
|
int cpuid);
|
||||||
|
|
||||||
|
Result threadStart(Thread* t);
|
||||||
|
Result threadWaitForExit(Thread* t);
|
||||||
|
Result threadClose(Thread* t);
|
@ -1,2 +1,5 @@
|
|||||||
void* virtmemReserve(size_t size);
|
void* virtmemReserve(size_t size);
|
||||||
void virtmemFree(void* addr, size_t size);
|
void virtmemFree(void* addr, size_t size);
|
||||||
|
|
||||||
|
void* virtmemReserveMap(size_t size);
|
||||||
|
void virtmemFreeMap(void* addr, size_t size);
|
||||||
|
@ -41,8 +41,13 @@ typedef struct {
|
|||||||
} __attribute__((packed)) SecmonArgs;
|
} __attribute__((packed)) SecmonArgs;
|
||||||
|
|
||||||
Result svcSetHeapSize(void** out_addr, u64 size);
|
Result svcSetHeapSize(void** out_addr, u64 size);
|
||||||
|
Result svcMapMemory(void* dst_addr, void* src_addr, u64 size);
|
||||||
|
Result svcUnmapMemory(void* dst_addr, void* src_addr, u64 size);
|
||||||
Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
|
Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
|
||||||
void NORETURN svcExitProcess();
|
void NORETURN svcExitProcess();
|
||||||
|
Result svcCreateThread(Handle* out, void* entry, void* arg, void* stack_top, int prio, int cpuid);
|
||||||
|
Result svcStartThread(Handle handle);
|
||||||
|
void NORETURN svcExitThread();
|
||||||
Result svcSleepThread(u64 nano);
|
Result svcSleepThread(u64 nano);
|
||||||
Result svcCloseHandle(Handle handle);
|
Result svcCloseHandle(Handle handle);
|
||||||
Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm);
|
Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm);
|
||||||
|
@ -19,6 +19,16 @@ SVC_BEGIN svcSetHeapSize
|
|||||||
ret
|
ret
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcMapMemory
|
||||||
|
svc 0x4
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcUnmapMemory
|
||||||
|
svc 0x5
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcQueryMemory
|
SVC_BEGIN svcQueryMemory
|
||||||
str x1, [sp, #-16]!
|
str x1, [sp, #-16]!
|
||||||
svc 0x6
|
svc 0x6
|
||||||
@ -32,6 +42,25 @@ SVC_BEGIN svcExitProcess
|
|||||||
ret
|
ret
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcCreateThread
|
||||||
|
str x0, [sp, #-16]!
|
||||||
|
svc 0x8
|
||||||
|
ldr x2, [sp]
|
||||||
|
str w1, [x2]
|
||||||
|
add sp, sp, #16
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcStartThread
|
||||||
|
svc 0x9
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
|
SVC_BEGIN svcExitThread
|
||||||
|
svc 0xA
|
||||||
|
ret
|
||||||
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcSleepThread
|
SVC_BEGIN svcSleepThread
|
||||||
svc 0xB
|
svc 0xB
|
||||||
ret
|
ret
|
||||||
|
76
nx/source/kernel/thread.c
Normal file
76
nx/source/kernel/thread.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2017 plutoo
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
static void _EntryWrap(Thread* t) {
|
||||||
|
t->entry(t->arg);
|
||||||
|
svcExitThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result threadCreate(
|
||||||
|
Thread* t, ThreadFunc entry, void* arg, size_t stack_sz, int prio,
|
||||||
|
int cpuid)
|
||||||
|
{
|
||||||
|
Result rc = 0;
|
||||||
|
void* stack = heapAllocPages(stack_sz);
|
||||||
|
|
||||||
|
if (stack == NULL) {
|
||||||
|
rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// todo: svcMapMemory returns 0xDC01
|
||||||
|
void* stack_mirror = stack;//virtmemReserveMap(stack_sz);
|
||||||
|
//rc = svcMapMemory(stack_mirror, stack, stack_sz);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
u64 stack_top = ((u64)stack_mirror) + t->stack_sz;
|
||||||
|
Handle handle;
|
||||||
|
|
||||||
|
rc = svcCreateThread(
|
||||||
|
&handle, (ThreadFunc) &_EntryWrap, (void*) t, (void*) stack_top,
|
||||||
|
prio, cpuid);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
t->handle = handle;
|
||||||
|
t->entry = entry;
|
||||||
|
t->arg = arg;
|
||||||
|
t->stack_mem = stack;
|
||||||
|
t->stack_mirror = stack_mirror;
|
||||||
|
t->stack_sz = stack_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
svcUnmapMemory(stack_mirror, stack, stack_sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
virtmemFreeMap(stack_mirror, stack_sz);
|
||||||
|
//heapFree(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result threadStart(Thread* t) {
|
||||||
|
return svcStartThread(t->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result threadWaitForExit(Thread* t) {
|
||||||
|
Handle handle = t->handle;
|
||||||
|
s32 idx = 0;
|
||||||
|
return svcWaitSynchronization(&idx, &handle, 1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result threadClose(Thread* t) {
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
rc = svcUnmapMemory(t->stack_mirror, t->stack_mem, t->stack_sz);
|
||||||
|
virtmemFreeMap(t->stack_mirror, t->stack_sz);
|
||||||
|
//heapFree(t->stack);
|
||||||
|
svcCloseHandle(t->handle);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
@ -15,6 +15,7 @@ enum {
|
|||||||
static VirtualRegion g_AddressSpace;
|
static VirtualRegion g_AddressSpace;
|
||||||
static VirtualRegion g_Region[REGION_MAX];
|
static VirtualRegion g_Region[REGION_MAX];
|
||||||
static u64 g_CurrentAddr;
|
static u64 g_CurrentAddr;
|
||||||
|
static u64 g_CurrentMapAddr;
|
||||||
|
|
||||||
static Result _GetRegionFromInfo(VirtualRegion* r, u64 id0_addr, u32 id0_sz) {
|
static Result _GetRegionFromInfo(VirtualRegion* r, u64 id0_addr, u32 id0_sz) {
|
||||||
u64 base;
|
u64 base;
|
||||||
@ -127,3 +128,53 @@ void virtmemFree(void* addr, size_t size) {
|
|||||||
IGNORE_ARG(addr);
|
IGNORE_ARG(addr);
|
||||||
IGNORE_ARG(size);
|
IGNORE_ARG(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* virtmemReserveMap(size_t size)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
MemInfo meminfo;
|
||||||
|
u32 pageinfo;
|
||||||
|
|
||||||
|
size = (size + 0xFFF) &~ 0xFFF;
|
||||||
|
|
||||||
|
u64 addr = g_CurrentMapAddr;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Add a guard page.
|
||||||
|
addr += 0x1000;
|
||||||
|
|
||||||
|
// Make sure we stay inside the reserved map region.
|
||||||
|
if (!_InRegion(&g_Region[REGION_MAP], addr)) {
|
||||||
|
addr = g_Region[REGION_MAP].start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query information about address.
|
||||||
|
rc = svcQueryMemory(&meminfo, &pageinfo, addr);
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_BADQUERYMEMORY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meminfo.memorytype != 0) {
|
||||||
|
// Address is already taken, let's move past it.
|
||||||
|
addr = meminfo.base_addr + meminfo.size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > meminfo.size) {
|
||||||
|
// We can't fit in this region, let's move past it.
|
||||||
|
addr = meminfo.base_addr + meminfo.size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_CurrentMapAddr = addr + size;
|
||||||
|
return (void*) addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtmemFreeMap(void* addr, size_t size) {
|
||||||
|
IGNORE_ARG(addr);
|
||||||
|
IGNORE_ARG(size);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user