Introducing thread..

This commit is contained in:
plutoo 2017-10-08 18:39:33 +02:00
parent a9555bb5b5
commit 85538c9fb3
7 changed files with 181 additions and 0 deletions

View File

@ -16,6 +16,7 @@ extern "C" {
#include <switch/kernel/tmem.h>
#include <switch/kernel/mutex.h>
#include <switch/kernel/thread.h>
#include <switch/kernel/virtmem.h>
#include <switch/services/sm.h>

View 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);

View File

@ -1,2 +1,5 @@
void* virtmemReserve(size_t size);
void virtmemFree(void* addr, size_t size);
void* virtmemReserveMap(size_t size);
void virtmemFreeMap(void* addr, size_t size);

View File

@ -41,8 +41,13 @@ typedef struct {
} __attribute__((packed)) SecmonArgs;
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);
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 svcCloseHandle(Handle handle);
Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm);

View File

@ -19,6 +19,16 @@ SVC_BEGIN svcSetHeapSize
ret
SVC_END
SVC_BEGIN svcMapMemory
svc 0x4
ret
SVC_END
SVC_BEGIN svcUnmapMemory
svc 0x5
ret
SVC_END
SVC_BEGIN svcQueryMemory
str x1, [sp, #-16]!
svc 0x6
@ -32,6 +42,25 @@ SVC_BEGIN svcExitProcess
ret
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 0xB
ret

76
nx/source/kernel/thread.c Normal file
View 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;
}

View File

@ -15,6 +15,7 @@ enum {
static VirtualRegion g_AddressSpace;
static VirtualRegion g_Region[REGION_MAX];
static u64 g_CurrentAddr;
static u64 g_CurrentMapAddr;
static Result _GetRegionFromInfo(VirtualRegion* r, u64 id0_addr, u32 id0_sz) {
u64 base;
@ -127,3 +128,53 @@ void virtmemFree(void* addr, size_t size) {
IGNORE_ARG(addr);
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);
}