mirror of
https://github.com/fincs/FeOS.git
synced 2025-06-19 03:25:33 -04:00
Integrate MultiFeOS into the kernel
This commit is contained in:
parent
a53ba81701
commit
f52d938521
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,7 +31,6 @@ build/
|
||||
!/sdk/userlib/README.txt
|
||||
!/sdk/userlib/feoswifi/
|
||||
!/sdk/userlib/feos3d/
|
||||
!/sdk/userlib/multifeos/
|
||||
!/sdk/userlib/libfar/
|
||||
!/sdk/userlib/libitcm/
|
||||
!/sdk/userlib/md5/
|
||||
|
@ -285,6 +285,14 @@ __isEmulator: @ Only to be called once!
|
||||
.Lmov_r0_1:
|
||||
mov r0, #1
|
||||
|
||||
.align 2
|
||||
.global __enterThread
|
||||
.type __enterThread, %function
|
||||
__enterThread: @ r0 - param, r1 - entrypoint, r2 - stack pointer
|
||||
mov sp, r2
|
||||
ldr lr, =ThrExit
|
||||
bx r1
|
||||
|
||||
.macro swiimp name num
|
||||
.align 2
|
||||
.global \name
|
||||
|
@ -159,13 +159,12 @@ BEGIN_TABLE(FEOSDSHW)
|
||||
ADD_FUNC_(DSLoadARM7),
|
||||
ADD_FUNC_(DSModeShim),
|
||||
ADD_FUNC_(DSProcessIRQs),
|
||||
ADD_FUNC_(DSSetIRQWaitFunc),
|
||||
ADD_FUNC_(DSSetSuspendMode),
|
||||
ADD_FUNC_(DSTimerTick),
|
||||
ADD_FUNC_(DSTimerWrite),
|
||||
ADD_FUNC_(DSVideoReset),
|
||||
ADD_FUNC_(DSWaitForIRQ),
|
||||
ADD_ALIAS(DSWaitForNextIRQ, DSWaitForNextIRQRaw),
|
||||
ADD_FUNC_(DSWaitForNextIRQ),
|
||||
ADD_FUNC_(bgClearControlBits),
|
||||
ADD_FUNC_(bgExtPaletteDisable),
|
||||
ADD_FUNC_(bgExtPaletteDisableSub),
|
||||
|
@ -64,8 +64,6 @@ static inline bool AddressCheckMainRAM(const void* addr)
|
||||
#define E_INVALIDARG (-11)
|
||||
#define E_APPKILLED (-12)
|
||||
|
||||
typedef void (*irqWaitFunc_t)(word_t);
|
||||
|
||||
void DSRunFifoQueue();
|
||||
void DSFifoSetDatamsgHandler(int channel, FifoDatamsgHandlerFunc handler, void* userdata);
|
||||
void DSFifoSetValue32Handler(int channel, FifoValue32HandlerFunc handler, void* userdata);
|
||||
@ -76,6 +74,7 @@ word_t DSProcessIRQs();
|
||||
void DSWaitForIRQ(word_t mask);
|
||||
void DSWaitForIRQRaw(word_t mask);
|
||||
word_t DSWaitForNextIRQRaw();
|
||||
word_t DSWaitForNextIRQ();
|
||||
|
||||
static inline void DSWaitForVBlank()
|
||||
{
|
||||
@ -87,9 +86,6 @@ static inline void DSWaitForVBlankRaw()
|
||||
DSWaitForIRQRaw(IRQ_VBLANK);
|
||||
}
|
||||
|
||||
#define GET_IRQFUNC ((irqWaitFunc_t)0xFFFFFFFF)
|
||||
irqWaitFunc_t DSSetIRQWaitFunc(irqWaitFunc_t newFunc);
|
||||
|
||||
int __getMode();
|
||||
#define isUserMode() (__getMode() == 0x10)
|
||||
|
||||
@ -130,6 +126,13 @@ typedef struct
|
||||
} executeStatus_t;
|
||||
|
||||
extern executeStatus_t* curExecStatus;
|
||||
typedef executeStatus_t* execstat_t;
|
||||
|
||||
execstat_t KeExecStatusCreate();
|
||||
void KeExecStatusAddRef(execstat_t hSt);
|
||||
void KeExecStatusRelease(execstat_t hSt);
|
||||
void KeSetCurExecStatus(execstat_t hSt);
|
||||
execstat_t KeGetCurExecStatus();
|
||||
|
||||
#ifdef LIBFAT_FEOS_MULTICWD
|
||||
char* _getCwdBuf();
|
||||
|
@ -375,23 +375,6 @@ void coop_swiIntrWaitCompat(word_t how, word_t what)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ARM9
|
||||
static irqWaitFunc_t irqWaitFunc = NULL;
|
||||
|
||||
void DSWaitForIRQ(word_t mask)
|
||||
{
|
||||
irqWaitFunc ? irqWaitFunc(mask) : DSWaitForIRQRaw(mask);
|
||||
}
|
||||
|
||||
irqWaitFunc_t DSSetIRQWaitFunc(irqWaitFunc_t newFunc)
|
||||
{
|
||||
irqWaitFunc_t oldFunc = irqWaitFunc;
|
||||
if (newFunc != GET_IRQFUNC)
|
||||
irqWaitFunc = newFunc;
|
||||
return oldFunc;
|
||||
}
|
||||
#endif
|
||||
|
||||
word_t DSWaitForNextIRQRaw()
|
||||
{
|
||||
word_t flags = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "feos.h"
|
||||
#include "loader.h"
|
||||
#include "feosfifo.h"
|
||||
#include "thread.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -38,14 +39,6 @@ void KeSetExcptHandler(void*);
|
||||
|
||||
// Execution status functions
|
||||
|
||||
typedef void* execstat_t;
|
||||
|
||||
execstat_t KeExecStatusCreate();
|
||||
void KeExecStatusAddRef(execstat_t hSt);
|
||||
void KeExecStatusRelease(execstat_t hSt);
|
||||
void KeSetCurExecStatus(execstat_t hSt);
|
||||
execstat_t KeGetCurExecStatus();
|
||||
|
||||
typedef int (* systemfunc_t)(const char* command);
|
||||
|
||||
systemfunc_t __system;
|
||||
@ -404,10 +397,6 @@ BEGIN_TABLE(FEOSKRNL)
|
||||
ADD_FUNC_(KeDiv3232),
|
||||
ADD_FUNC_(KeDiv6432),
|
||||
ADD_FUNC_(KeDiv6464),
|
||||
ADD_FUNC_(KeExecStatusAddRef),
|
||||
ADD_FUNC_(KeExecStatusCreate),
|
||||
ADD_FUNC_(KeExecStatusRelease),
|
||||
ADD_FUNC_(KeGetCurExecStatus),
|
||||
ADD_FUNC_(KeGetDiskStats),
|
||||
ADD_ALIAS(KeGetErrnoPtr, __errno),
|
||||
ADD_FUNC_(KeGetMemStats),
|
||||
@ -417,7 +406,6 @@ BEGIN_TABLE(FEOSKRNL)
|
||||
ADD_FUNC_(KeMod3232),
|
||||
ADD_FUNC_(KeMod6432),
|
||||
ADD_FUNC_(KeMod6464),
|
||||
ADD_FUNC_(KeSetCurExecStatus),
|
||||
ADD_FUNC_(KeSetExcptHandler),
|
||||
ADD_FUNC_(KeSqrt32),
|
||||
ADD_FUNC_(KeSqrt64),
|
||||
@ -432,11 +420,24 @@ BEGIN_TABLE(FEOSKRNL)
|
||||
ADD_FUNC_(LdrLoadModule),
|
||||
ADD_FUNC_(LdrLockModule),
|
||||
ADD_FUNC_(LdrResGetSize),
|
||||
ADD_FUNC_(LdrResolveAddr),
|
||||
ADD_FUNC_(LdrResRead),
|
||||
ADD_FUNC_(LdrResSeek),
|
||||
ADD_FUNC_(LdrResTell),
|
||||
ADD_FUNC_(LdrResolveAddr),
|
||||
ADD_FUNC_(LdrUnlockModule),
|
||||
ADD_FUNC_(PsCreateFromArgv),
|
||||
ADD_FUNC_(PsCreateFromCmdLine),
|
||||
ADD_FUNC_(ThrCreate),
|
||||
ADD_FUNC_(ThrDetach),
|
||||
ADD_FUNC_(ThrGetSelf),
|
||||
ADD_FUNC_(ThrExit),
|
||||
ADD_FUNC_(ThrFree),
|
||||
ADD_FUNC_(ThrGetExitCode),
|
||||
ADD_FUNC_(ThrIsActive),
|
||||
ADD_FUNC_(ThrJoin),
|
||||
ADD_FUNC_(ThrRunInContext),
|
||||
ADD_FUNC_(ThrSetPriority),
|
||||
ADD_FUNC_(ThrYield),
|
||||
ADD_FUNC_(__aeabi_idiv),
|
||||
ADD_FUNC_(__aeabi_idivmod),
|
||||
ADD_FUNC_(__aeabi_ldivmod),
|
||||
@ -605,14 +606,14 @@ execstat_t KeExecStatusCreate()
|
||||
|
||||
void KeExecStatusAddRef(execstat_t hSt)
|
||||
{
|
||||
if (hSt == (execstat_t) &defaultExecStatus) return;
|
||||
((executeStatus_t*)hSt)->refcount ++;
|
||||
if (hSt == &defaultExecStatus) return;
|
||||
hSt->refcount ++;
|
||||
}
|
||||
|
||||
void KeExecStatusRelease(execstat_t hSt)
|
||||
{
|
||||
if (hSt == (execstat_t) &defaultExecStatus) return;
|
||||
word_t r = --((executeStatus_t*)hSt)->refcount;
|
||||
if (hSt == &defaultExecStatus) return;
|
||||
word_t r = --hSt->refcount;
|
||||
if (r == 0)
|
||||
free(hSt);
|
||||
}
|
||||
@ -622,7 +623,7 @@ void KeSetCurExecStatus(execstat_t hSt)
|
||||
#ifdef LIBFAT_FEOS_MULTICWD
|
||||
curExecStatus->cwdCluster = g_fatCwdCluster;
|
||||
#endif
|
||||
curExecStatus = (executeStatus_t*) hSt;
|
||||
curExecStatus = hSt;
|
||||
#ifdef LIBFAT_FEOS_MULTICWD
|
||||
g_fatCwdCluster = curExecStatus->cwdCluster;
|
||||
_setCwdBuf(curExecStatus->cwdBuffer);
|
||||
@ -631,7 +632,7 @@ void KeSetCurExecStatus(execstat_t hSt)
|
||||
|
||||
execstat_t KeGetCurExecStatus()
|
||||
{
|
||||
return (execstat_t) curExecStatus;
|
||||
return curExecStatus;
|
||||
}
|
||||
|
||||
#define LdrCurModule curExecStatus->curModule
|
||||
|
@ -527,6 +527,10 @@ void* LdrFindInTbl(const fxe_inmem_exports* exphdr, const char* name)
|
||||
return exphdr->table[mid].addr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
iprintf("{DBG} Cannot resolve %s\n", name);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "feos.h"
|
||||
#include "thread.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@ -378,6 +379,7 @@ int main()
|
||||
#ifdef LIBFAT_FEOS_MULTICWD
|
||||
g_fatCwdClusterPtr = (vu32*) _FAT_getCwdClusterPtr("/");
|
||||
KeInitDefaultExecStatus();
|
||||
ThrInit();
|
||||
#endif
|
||||
InstallThunks();
|
||||
#ifdef LIBFAT_FEOS_MULTICWD
|
||||
|
@ -1,20 +1,4 @@
|
||||
#include <multifeos.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum { THREAD_EXIT = BIT(0), THREAD_IRQWAIT = BIT(1), THREAD_EXECBITS = 3, THREAD_HIGHPRIO = BIT(2), THREAD_DETACHED = BIT(3) };
|
||||
|
||||
typedef struct tag_threadSt
|
||||
{
|
||||
jmp_buf ctx;
|
||||
word_t* stack;
|
||||
struct tag_threadSt* prev;
|
||||
struct tag_threadSt* next;
|
||||
execstat_t execStat;
|
||||
word_t flags;
|
||||
union { int rc; word_t irqMask; };
|
||||
} threadSt;
|
||||
#include "thread.h"
|
||||
|
||||
threadSt _firstThread;
|
||||
|
||||
@ -25,22 +9,18 @@ int threadsFinished = 0;
|
||||
|
||||
#define inactiveThreadCount() (threadsWaiting + threadsFinished)
|
||||
|
||||
void __attribute__((noreturn)) __newThread(void* param, threadEP_t entryPoint, word_t* stackPtr);
|
||||
void __attribute__((noreturn)) __enterThread(void* param, threadEP_t entryPoint, word_t* stackPtr);
|
||||
|
||||
static irqWaitFunc_t oldIrqWaitFunc;
|
||||
static void _irqWaitYield(word_t mask);
|
||||
static threadSt* _irqWaitCheck();
|
||||
|
||||
FEOSINIT void initFirstThread()
|
||||
void ThrInit()
|
||||
{
|
||||
curThread->execStat = FeOS_GetCurExecStatus();
|
||||
curThread->execStat = KeGetCurExecStatus();
|
||||
curThread->prev = curThread;
|
||||
curThread->next = curThread;
|
||||
oldIrqWaitFunc = FeOS_SetIRQWaitFunc(_irqWaitYield);
|
||||
FeOS_StayResident();
|
||||
}
|
||||
|
||||
thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param)
|
||||
thread_t ThrCreate(word_t stackSize, threadEP_t entryPoint, void* param)
|
||||
{
|
||||
// 32-bit align the stack size
|
||||
stackSize += 3;
|
||||
@ -51,8 +31,8 @@ thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param)
|
||||
|
||||
threadSt* t = (threadSt*) (mem + stackSize);
|
||||
t->stack = (word_t*) mem;
|
||||
t->execStat = FeOS_GetCurExecStatus();
|
||||
FeOS_ExecStatusAddRef(t->execStat);
|
||||
t->execStat = KeGetCurExecStatus();
|
||||
KeExecStatusAddRef(t->execStat);
|
||||
t->flags = curThread->flags & THREAD_HIGHPRIO;
|
||||
|
||||
threadSt* insPoint;
|
||||
@ -75,20 +55,20 @@ thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param)
|
||||
nThreads ++;
|
||||
|
||||
if (!setjmp(thisThread->ctx))
|
||||
__newThread(param, entryPoint, (word_t*) t);
|
||||
__enterThread(param, entryPoint, (word_t*) t);
|
||||
|
||||
return (thread_t) t;
|
||||
return t;
|
||||
}
|
||||
|
||||
void _doYield(threadSt* t)
|
||||
{
|
||||
curThread = t;
|
||||
|
||||
FeOS_SetCurExecStatus(curThread->execStat);
|
||||
KeSetCurExecStatus(curThread->execStat);
|
||||
longjmp(curThread->ctx, 1);
|
||||
}
|
||||
|
||||
void FeOS_Yield()
|
||||
void ThrYield()
|
||||
{
|
||||
threadSt* t = curThread;
|
||||
|
||||
@ -113,7 +93,7 @@ void FeOS_Yield()
|
||||
while ((t->flags & THREAD_DETACHED) && (t->flags & THREAD_EXIT))
|
||||
{
|
||||
threadSt* next = t->next;
|
||||
FeOS_FreeThread(t);
|
||||
ThrFree(t);
|
||||
t = next;
|
||||
}
|
||||
} while (t->flags & THREAD_EXECBITS);
|
||||
@ -121,31 +101,30 @@ void FeOS_Yield()
|
||||
_doYield(t);
|
||||
}
|
||||
|
||||
thread_t FeOS_GetCurrentThread()
|
||||
thread_t ThrGetSelf()
|
||||
{
|
||||
return (thread_t) curThread;
|
||||
return curThread;
|
||||
}
|
||||
|
||||
void FeOS_ExitThread(int rc)
|
||||
void ThrExit(int rc)
|
||||
{
|
||||
if (curThread == &_firstThread) return;
|
||||
curThread->flags |= THREAD_EXIT;
|
||||
curThread->rc = rc;
|
||||
threadsFinished ++;
|
||||
FeOS_Yield();
|
||||
ThrYield();
|
||||
}
|
||||
|
||||
bool FeOS_IsThreadActive(thread_t hThread)
|
||||
bool ThrIsActive(thread_t hThread)
|
||||
{
|
||||
return (((threadSt*)hThread)->flags & THREAD_EXIT) == 0;
|
||||
return (hThread->flags & THREAD_EXIT) == 0;
|
||||
}
|
||||
|
||||
void FeOS_FreeThread(thread_t hThread)
|
||||
void ThrFree(thread_t t)
|
||||
{
|
||||
if (hThread == (thread_t) &_firstThread) return;
|
||||
if (hThread == (thread_t) curThread) return;
|
||||
if (t == &_firstThread) return;
|
||||
if (t == curThread) return;
|
||||
|
||||
threadSt* t = (threadSt*) hThread;
|
||||
if (t->flags & THREAD_IRQWAIT)
|
||||
threadsWaiting --;
|
||||
if (t->flags & THREAD_EXIT)
|
||||
@ -153,29 +132,28 @@ void FeOS_FreeThread(thread_t hThread)
|
||||
t->prev->next = t->next;
|
||||
t->next->prev = t->prev;
|
||||
free(t->stack);
|
||||
FeOS_ExecStatusRelease(t->execStat);
|
||||
KeExecStatusRelease(t->execStat);
|
||||
nThreads --;
|
||||
}
|
||||
|
||||
int FeOS_ThreadJoin(thread_t hThread)
|
||||
int ThrJoin(thread_t hThread)
|
||||
{
|
||||
int rc;
|
||||
while (FeOS_IsThreadActive(hThread)) FeOS_Idle();
|
||||
rc = FeOS_GetThreadRC(hThread);
|
||||
FeOS_FreeThread(hThread);
|
||||
while (ThrIsActive(hThread)) DSWaitForIRQ(~0);
|
||||
rc = ThrGetExitCode(hThread);
|
||||
ThrFree(hThread);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void FeOS_SetThreadPrio(thread_t hThread, int prio)
|
||||
void ThrSetPriority(thread_t t, int prio)
|
||||
{
|
||||
threadSt* t = (threadSt*) hThread;
|
||||
word_t flag = (prio == PRIORITY_HIGH) ? THREAD_HIGHPRIO : 0;
|
||||
if ((t->flags & flag) == flag) return;
|
||||
t->flags &= ~THREAD_HIGHPRIO;
|
||||
t->flags |= flag;
|
||||
|
||||
// Can't change position of the first thread
|
||||
if (hThread == (thread_t) &_firstThread) return;
|
||||
if (t == &_firstThread) return;
|
||||
|
||||
// Pull the thread out of the list
|
||||
t->prev->next = t->next;
|
||||
@ -189,9 +167,9 @@ void FeOS_SetThreadPrio(thread_t hThread, int prio)
|
||||
t->prev->next = t;
|
||||
}
|
||||
|
||||
int FeOS_GetThreadRC(thread_t hThread)
|
||||
int ThrGetExitCode(thread_t hThread)
|
||||
{
|
||||
return ((threadSt*)hThread)->rc;
|
||||
return hThread->rc;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@ -203,16 +181,17 @@ typedef struct
|
||||
static int _execAsyncEP(void* _param)
|
||||
{
|
||||
execParams* params = (void*) _param;
|
||||
FeOS_ExecStatusRelease(curThread->execStat);
|
||||
curThread->execStat = FeOS_ExecStatusCreate();
|
||||
if (!curThread->execStat) return -1;
|
||||
FeOS_SetCurExecStatus(curThread->execStat);
|
||||
int rc = FeOS_Execute(params->argc, params->argv);
|
||||
execstat_t es = KeExecStatusCreate();
|
||||
if (!es) return -4;
|
||||
KeExecStatusRelease(curThread->execStat);
|
||||
curThread->execStat = es;
|
||||
KeSetCurExecStatus(curThread->execStat);
|
||||
int rc = LdrExecuteArgv(params->argc, params->argv);
|
||||
free(_param);
|
||||
return rc;
|
||||
}
|
||||
|
||||
thread_t FeOS_CreateProcess(int argc, const char* argv[])
|
||||
thread_t PsCreateFromArgv(int argc, const char* argv[])
|
||||
{
|
||||
execParams* params = (execParams*) malloc(sizeof(execParams));
|
||||
if (!params) return NULL;
|
||||
@ -220,7 +199,7 @@ thread_t FeOS_CreateProcess(int argc, const char* argv[])
|
||||
params->argc = argc;
|
||||
params->argv = argv;
|
||||
|
||||
thread_t t = FeOS_CreateThread(16*1024, _execAsyncEP, params);
|
||||
thread_t t = ThrCreate(16*1024, _execAsyncEP, params);
|
||||
if (!t)
|
||||
{
|
||||
free(params);
|
||||
@ -232,52 +211,54 @@ thread_t FeOS_CreateProcess(int argc, const char* argv[])
|
||||
|
||||
static int _runAsyncEP(void* _param)
|
||||
{
|
||||
FeOS_ExecStatusRelease(curThread->execStat);
|
||||
curThread->execStat = FeOS_ExecStatusCreate();
|
||||
execstat_t es = KeExecStatusCreate();
|
||||
if (!es) return -4;
|
||||
KeExecStatusRelease(curThread->execStat);
|
||||
curThread->execStat = es;
|
||||
if (!curThread->execStat) return -1;
|
||||
FeOS_SetCurExecStatus(curThread->execStat);
|
||||
KeSetCurExecStatus(curThread->execStat);
|
||||
return system((const char*)_param);
|
||||
}
|
||||
|
||||
thread_t FeOS_RunAsync(const char* command)
|
||||
thread_t PsCreateFromCmdLine(const char* command)
|
||||
{
|
||||
return FeOS_CreateThread(16*1024, _runAsyncEP, (void*)command);
|
||||
return ThrCreate(16*1024, _runAsyncEP, (void*)command);
|
||||
}
|
||||
|
||||
void FeOS_DetachThread(thread_t hThread)
|
||||
void ThrDetach(thread_t t)
|
||||
{
|
||||
if (hThread == &_firstThread || hThread == curThread)
|
||||
if (t == &_firstThread || t == curThread)
|
||||
return;
|
||||
threadSt* t = (threadSt*) hThread;
|
||||
t->flags |= THREAD_DETACHED;
|
||||
}
|
||||
|
||||
int FeOS_RunInContext(thread_t hThread, threadEP_t func, void* param)
|
||||
int ThrRunInContext(thread_t t, threadEP_t func, void* param)
|
||||
{
|
||||
threadSt* t = (threadSt*) hThread;
|
||||
execstat_t oldSt = curThread->execStat;
|
||||
curThread->execStat = t->execStat;
|
||||
FeOS_SetCurExecStatus(curThread->execStat);
|
||||
KeExecStatusAddRef(curThread->execStat);
|
||||
KeSetCurExecStatus(curThread->execStat);
|
||||
int rc = func(param);
|
||||
curThread->execStat = oldSt;
|
||||
FeOS_SetCurExecStatus(curThread->execStat);
|
||||
KeSetCurExecStatus(curThread->execStat);
|
||||
KeExecStatusRelease(curThread->execStat);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void _irqWaitYield(word_t mask)
|
||||
void DSWaitForIRQ(word_t mask)
|
||||
{
|
||||
threadsWaiting ++;
|
||||
curThread->irqMask = mask;
|
||||
curThread->flags |= THREAD_IRQWAIT;
|
||||
FeOS_Yield();
|
||||
ThrYield();
|
||||
}
|
||||
|
||||
word_t FeOS_NextIRQYield()
|
||||
word_t DSWaitForNextIRQ()
|
||||
{
|
||||
threadsWaiting ++;
|
||||
curThread->irqMask = 0;
|
||||
curThread->flags |= THREAD_IRQWAIT;
|
||||
FeOS_Yield();
|
||||
ThrYield();
|
||||
return curThread->irqMask;
|
||||
}
|
||||
|
||||
@ -299,7 +280,7 @@ threadSt* _irqWaitCheck()
|
||||
|
||||
// Get the interrupt mask. If all other threads are inactive (such as waiting for IRQs),
|
||||
// we can then perform the wait for IRQ.
|
||||
word_t mask = (inactiveThreadCount() == nThreads) ? FeOS_NextIRQ() : FeOS_CheckPendingIRQs();
|
||||
word_t mask = (inactiveThreadCount() == nThreads) ? DSWaitForNextIRQRaw() : DSProcessIRQs();
|
||||
|
||||
if (!mask) // implies inactiveThreadCount() != nThreads
|
||||
return NULL;
|
39
kernel/source/thread.h
Normal file
39
kernel/source/thread.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "feos.h"
|
||||
#include "loader.h"
|
||||
|
||||
#define PRIORITY_HIGH 0x7FFFFFFF
|
||||
#define PRIORITY_NORMAL 0
|
||||
|
||||
enum { THREAD_EXIT = BIT(0), THREAD_IRQWAIT = BIT(1), THREAD_EXECBITS = 3, THREAD_HIGHPRIO = BIT(2), THREAD_DETACHED = BIT(3) };
|
||||
|
||||
typedef struct tag_threadSt
|
||||
{
|
||||
jmp_buf ctx;
|
||||
word_t* stack;
|
||||
struct tag_threadSt* prev;
|
||||
struct tag_threadSt* next;
|
||||
execstat_t execStat;
|
||||
word_t flags;
|
||||
union { int rc; word_t irqMask; };
|
||||
} threadSt;
|
||||
|
||||
typedef threadSt* thread_t;
|
||||
typedef int (*threadEP_t)(void* param);
|
||||
|
||||
void ThrInit();
|
||||
|
||||
thread_t ThrCreate(word_t stackSize, threadEP_t entryPoint, void* param);
|
||||
void ThrYield();
|
||||
thread_t ThrGetSelf();
|
||||
void ThrExit(int rc);
|
||||
bool ThrIsActive(thread_t hThread);
|
||||
void ThrFree(thread_t hThread);
|
||||
void ThrSetPriority(thread_t hThread, int prio);
|
||||
int ThrGetExitCode(thread_t hThread);
|
||||
int ThrJoin();
|
||||
void ThrDetach(thread_t hThread);
|
||||
int ThrRunInContext(thread_t hThread, threadEP_t func, void* param);
|
||||
|
||||
thread_t PsCreateFromArgv(int argc, const char* argv[]);
|
||||
thread_t PsCreateFromCmdLine(const char* command);
|
@ -42,6 +42,7 @@ extern "C"
|
||||
|
||||
\subsection api FeOS API
|
||||
- \ref api_base "Core FeOS API"
|
||||
- \ref api_thr "FeOS Threading API"
|
||||
- **FeOS libnds-compatible DS hardware access API**
|
||||
- \ref api_ds "Basic functions"
|
||||
- \ref api_math "Math functions"
|
||||
@ -49,7 +50,6 @@ extern "C"
|
||||
- \ref api_dsspr "Sprite functions"
|
||||
|
||||
\subsection userlibs System Libraries
|
||||
- \ref multifeos.h "MultiFeOS (cooperative multitasking)"
|
||||
- \ref feoswifi "FeOSWifi (dswifi for FeOS)"
|
||||
- \ref feos3d.h "FeOS3D (libnds videoGL for FeOS)"
|
||||
- \ref far.h "libfar (FeOS ARchives)"
|
||||
@ -67,6 +67,7 @@ extern "C"
|
||||
#include <feosuser.h>
|
||||
#include <feosmath.h>
|
||||
#include <feosdsapi.h>
|
||||
#include <feosthr.h>
|
||||
#include <feosdsspr.h>
|
||||
#include <feosdsbg.h>
|
||||
#else
|
||||
|
@ -401,13 +401,6 @@ static inline void swiWaitForVBlank()
|
||||
DSWaitForIRQ(IRQ_VBLANK);
|
||||
}
|
||||
|
||||
#define DEFAULT_IRQFUNC ((irqWaitFunc_t)0) //!< Internal macro not for public consumption.
|
||||
#define GET_IRQFUNC ((irqWaitFunc_t)0xFFFFFFFF) //!< Internal macro not for public consumption.
|
||||
typedef void (*irqWaitFunc_t)(word_t); //!< Internal data type not for public consumption.
|
||||
|
||||
//! \brief Internal function not for public consumption.
|
||||
irqWaitFunc_t DSSetIRQWaitFunc(irqWaitFunc_t newFunc);
|
||||
|
||||
//! \brief Writes a value into a timer register.
|
||||
void DSTimerWrite(int, word_t);
|
||||
//! \brief Reads a timer's counting value.
|
||||
|
79
sdk/include/feosthr.h
Normal file
79
sdk/include/feosthr.h
Normal file
@ -0,0 +1,79 @@
|
||||
//
|
||||
// FeOS Standard Library
|
||||
// feosthr.h
|
||||
// FeOS Threading API
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <feos.h>
|
||||
|
||||
/** @file feosthr.h
|
||||
* \brief FeOS Threading API
|
||||
*/
|
||||
|
||||
/** @addtogroup api_thr FeOS Threading API
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define DEFAULT_STACK_SIZE (8*1024) //!< Default thread stack size.
|
||||
// Ersatz future-proof binary priority system
|
||||
#define PRIORITY_HIGH 0x7FFFFFFF //!< High priority.
|
||||
#define PRIORITY_NORMAL 0 //!< Low priority
|
||||
|
||||
typedef void* thread_t; //!< Thread handle datatype.
|
||||
typedef int (*threadEP_t)(void* param); //!< Thread entry point callback datatype.
|
||||
|
||||
//! \brief Creates a thread.
|
||||
thread_t ThrCreate(word_t stackSize, threadEP_t entryPoint, void* param);
|
||||
//! \brief Yields thread execution. Normally an IRQ wait function should be used instead.
|
||||
void ThrYield();
|
||||
//! \brief Gets the currently executing thread.
|
||||
thread_t ThrGetSelf();
|
||||
//! \brief Exits the current thread.
|
||||
void ThrExit(int rc);
|
||||
//! \brief Determines whether a certain thread has not finished.
|
||||
bool ThrIsActive(thread_t hThread);
|
||||
//! \brief Frees/deletes a thread.
|
||||
void ThrFree(thread_t hThread);
|
||||
//! \brief Sets the priority of a thread.
|
||||
void ThrSetPriority(thread_t hThread, int prio);
|
||||
//! \brief Gets the exit code of a thread.
|
||||
int ThrGetExitCode(thread_t hThread);
|
||||
//! \brief Waits for a thread to finish executing. The thread is additionally freed.
|
||||
int ThrJoin();
|
||||
|
||||
//! \brief Makes the thread be automatically free when it exits.
|
||||
void ThrDetach(thread_t hThread);
|
||||
//! \brief Runs a piece of code in the context of another thread.
|
||||
int ThrRunInContext(thread_t hThread, threadEP_t func, void* param);
|
||||
|
||||
//! \brief Recommended way to idle.
|
||||
static inline void ThrIdle()
|
||||
{
|
||||
DSWaitForIRQ(~0);
|
||||
}
|
||||
|
||||
//! \brief Creates a process using an argv array.
|
||||
thread_t PsCreateFromArgv(int argc, const char* argv[]);
|
||||
//! \brief Creates a process using a command line.
|
||||
thread_t PsCreateFromCmdLine(const char* command);
|
||||
|
||||
// Simple lock API
|
||||
|
||||
typedef volatile word_t lock_t; //!< Simple lock datatype
|
||||
|
||||
//! \brief Acquires a lock.
|
||||
//! \param bIrqIdling Determines if IRQ-waiting is to be used as an idling method.
|
||||
static inline void ThrAcquireLock(lock_t* pLock, bool bIrqIdling)
|
||||
{
|
||||
while (*pLock) bIrqIdling ? ThrIdle() : ThrYield();
|
||||
*pLock = 1;
|
||||
}
|
||||
|
||||
//! \brief Releases a lock.
|
||||
static inline void ThrReleaseLock(lock_t* pLock)
|
||||
{
|
||||
*pLock = 0;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -70,12 +70,6 @@ void LdrEnumModules(ModuleEnumCallback, void*);
|
||||
//! \brief Decreases the reference count of the callers' module.
|
||||
#define LdrEndResidency() LdrUnlockModule(LdrGetSelf())
|
||||
|
||||
execstat_t KeExecStatusCreate(); //!< (Low-level) Creates a new execution status object.
|
||||
void KeExecStatusAddRef(execstat_t); //!< (Low-level) Increases the reference count of an execstat object.
|
||||
void KeExecStatusRelease(execstat_t); //!< (Low-level) Decreases the reference count of an execstat object.
|
||||
void KeSetCurExecStatus(execstat_t); //!< (Low-level) Sets the current execution status.
|
||||
execstat_t KeGetCurExecStatus(); //!< (Low-level) Gets the current execution status.
|
||||
|
||||
//! \brief Executes the specified argc and argv.
|
||||
int LdrExecuteArgv(int, const char*[]);
|
||||
|
||||
|
31
sdk/include/multifeos.h
Normal file
31
sdk/include/multifeos.h
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
//
|
||||
// FeOS Standard Library
|
||||
// multifeos.h
|
||||
// MultiFeOS compatibility defines
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <feos.h>
|
||||
|
||||
#define FeOS_CancelThread ThrFree
|
||||
#define FeOS_CreateThread ThrCreate
|
||||
#define FeOS_Yield ThrYield
|
||||
#define FeOS_GetCurrentThread ThrGetSelf
|
||||
#define FeOS_ExitThread ThrExit
|
||||
#define FeOS_IsThreadActive ThrIsActive
|
||||
#define FeOS_FreeThread ThrFree
|
||||
#define FeOS_SetThreadPrio ThrSetPriority
|
||||
#define FeOS_GetThreadRC ThrGetExitCode
|
||||
#define FeOS_ThreadJoin ThrJoin
|
||||
#define FeOS_DetachThread ThrDetach
|
||||
#define FeOS_RunInContext ThrRunInContext
|
||||
#define FeOS_Idle ThrIdle
|
||||
|
||||
#define FeOS_CreateProcess PsCreateFromArgv
|
||||
#define FeOS_RunAsync PsCreateFromCmdLine
|
||||
|
||||
#define FeOS_NextIRQYield DSWaitForNextIRQ
|
||||
|
||||
#define FeOS_AcquireLock ThrAcquireLock
|
||||
#define FeOS_ReleaseLock ThrReleaseLock
|
@ -13,7 +13,6 @@ DSGetSubOAM \
|
||||
DSLoadARM7 \
|
||||
DSModeShim \
|
||||
DSProcessIRQs \
|
||||
DSSetIRQWaitFunc \
|
||||
DSSetSuspendMode \
|
||||
DSTimerTick \
|
||||
DSTimerWrite \
|
||||
|
@ -20,10 +20,6 @@ IoSetStdout \
|
||||
KeDiv3232 \
|
||||
KeDiv6432 \
|
||||
KeDiv6464 \
|
||||
KeExecStatusAddRef \
|
||||
KeExecStatusCreate \
|
||||
KeExecStatusRelease \
|
||||
KeGetCurExecStatus \
|
||||
KeGetDiskStats \
|
||||
KeGetErrnoPtr \
|
||||
KeGetMemStats \
|
||||
@ -33,7 +29,6 @@ KeGetTickCount \
|
||||
KeMod3232 \
|
||||
KeMod6432 \
|
||||
KeMod6464 \
|
||||
KeSetCurExecStatus \
|
||||
KeSetExcptHandler \
|
||||
KeSqrt32 \
|
||||
KeSqrt64 \
|
||||
@ -48,11 +43,24 @@ LdrGetModuleName \
|
||||
LdrLoadModule \
|
||||
LdrLockModule \
|
||||
LdrResGetSize \
|
||||
LdrResolveAddr \
|
||||
LdrResRead \
|
||||
LdrResSeek \
|
||||
LdrResTell \
|
||||
LdrResolveAddr \
|
||||
LdrUnlockModule \
|
||||
PsCreateFromArgv \
|
||||
PsCreateFromCmdLine \
|
||||
ThrCreate \
|
||||
ThrDetach \
|
||||
ThrGetSelf \
|
||||
ThrExit \
|
||||
ThrFree \
|
||||
ThrGetExitCode \
|
||||
ThrIsActive \
|
||||
ThrJoin \
|
||||
ThrRunInContext \
|
||||
ThrSetPriority \
|
||||
ThrYield \
|
||||
__aeabi_idiv \
|
||||
__aeabi_idivmod \
|
||||
__aeabi_ldivmod \
|
||||
|
@ -1,37 +0,0 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPro")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(FEOSSDK)),)
|
||||
$(error "Please set FEOSSDK in your environment. export FEOSSDK=<path to>FeOS/sdk")
|
||||
endif
|
||||
|
||||
FEOSMK = $(FEOSSDK)/mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(shell basename $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
CONF_DEFINES = -DMULTIFEOS_BUILD
|
||||
|
||||
include $(FEOSMK)/dynlib.mk
|
||||
|
||||
install: all
|
||||
@cp $(TARGET).fx2 $(FEOSDEST)/data/FeOS/lib/$(TARGET).fx2
|
@ -1,92 +0,0 @@
|
||||
//
|
||||
// MultiFeOS
|
||||
// multifeos.h
|
||||
// FeOS user-mode cooperative multithreading library
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <feos.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef MULTIFEOS_BUILD
|
||||
#define MULTIFEOS_API FEOS_EXPORT
|
||||
#else
|
||||
#define MULTIFEOS_API
|
||||
#endif
|
||||
|
||||
/*! \file multifeos.h
|
||||
\brief FeOS user-mode cooperative multithreading library
|
||||
*/
|
||||
|
||||
#define DEFAULT_STACK_SIZE (8*1024) //!< Default thread stack size.
|
||||
// Ersatz future-proof binary priority system
|
||||
#define PRIORITY_HIGH 0x7FFFFFFF //!< High priority.
|
||||
#define PRIORITY_NORMAL 0 //!< Low priority
|
||||
|
||||
typedef void* thread_t; //!< Thread handle datatype.
|
||||
typedef int (*threadEP_t)(void* param); //!< Thread entry point callback datatype.
|
||||
|
||||
#define FeOS_CancelThread FeOS_FreeThread //!< Alternative name for FeOS_FreeThread().
|
||||
|
||||
//! \brief Creates a thread.
|
||||
MULTIFEOS_API thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param);
|
||||
//! \brief Yields thread execution. Normally an IRQ wait function should be used instead.
|
||||
MULTIFEOS_API void FeOS_Yield();
|
||||
//! \brief Gets the currently executing thread.
|
||||
MULTIFEOS_API thread_t FeOS_GetCurrentThread();
|
||||
//! \brief Exits the current thread.
|
||||
MULTIFEOS_API void FeOS_ExitThread(int rc);
|
||||
//! \brief Determines whether a certain thread has not finished.
|
||||
MULTIFEOS_API bool FeOS_IsThreadActive(thread_t hThread);
|
||||
//! \brief Frees/deletes a thread.
|
||||
MULTIFEOS_API void FeOS_FreeThread(thread_t hThread);
|
||||
//! \brief Sets the priority of a thread.
|
||||
MULTIFEOS_API void FeOS_SetThreadPrio(thread_t hThread, int prio);
|
||||
//! \brief Gets the exit code of a thread.
|
||||
MULTIFEOS_API int FeOS_GetThreadRC(thread_t hThread);
|
||||
//! \brief Waits for a thread to finish executing. The thread is additionally freed.
|
||||
MULTIFEOS_API int FeOS_ThreadJoin();
|
||||
|
||||
//! \brief Asynchronously runs a command.
|
||||
MULTIFEOS_API thread_t FeOS_CreateProcess(int argc, const char* argv[]);
|
||||
//! \brief Asynchronously runs a shell command.
|
||||
MULTIFEOS_API thread_t FeOS_RunAsync(const char* command);
|
||||
|
||||
//! \brief Makes the thread be automatically free when it exits.
|
||||
MULTIFEOS_API void FeOS_DetachThread(thread_t hThread);
|
||||
//! \brief Runs a piece of code in the context of another thread.
|
||||
MULTIFEOS_API int FeOS_RunInContext(thread_t hThread, threadEP_t func, void* param);
|
||||
|
||||
//! \brief MultiFeOS-safe version of FeOS_NextIRQ().
|
||||
MULTIFEOS_API word_t FeOS_NextIRQYield();
|
||||
|
||||
//! \brief MultiFeOS-safe way of idling.
|
||||
static inline void FeOS_Idle()
|
||||
{
|
||||
FeOS_WaitForIRQ(~0);
|
||||
}
|
||||
|
||||
// Simple lock API
|
||||
|
||||
typedef volatile word_t lock_t; //!< Simple lock datatype
|
||||
|
||||
//! \brief Acquires a lock.
|
||||
//! \param bIrqIdling Determines if IRQ-waiting is to be used as an idling method.
|
||||
static inline void FeOS_AcquireLock(lock_t* pLock, bool bIrqIdling)
|
||||
{
|
||||
while (*pLock) (bIrqIdling ? FeOS_Idle : FeOS_Yield)();
|
||||
*pLock = 1;
|
||||
}
|
||||
|
||||
//! \brief Releases a lock.
|
||||
static inline void FeOS_ReleaseLock(lock_t* pLock)
|
||||
{
|
||||
*pLock = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
.arch armv5te
|
||||
.text
|
||||
.global __newThread
|
||||
.hidden __newThread
|
||||
.type __newThread STT_FUNC
|
||||
|
||||
.align 2
|
||||
__newThread: @ r0 - param, r1 - entrypoint, r2 - stack pointer
|
||||
mov sp, r2
|
||||
ldr lr, =FeOS_ExitThread
|
||||
bx r1
|
Loading…
Reference in New Issue
Block a user