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/README.txt
|
||||||
!/sdk/userlib/feoswifi/
|
!/sdk/userlib/feoswifi/
|
||||||
!/sdk/userlib/feos3d/
|
!/sdk/userlib/feos3d/
|
||||||
!/sdk/userlib/multifeos/
|
|
||||||
!/sdk/userlib/libfar/
|
!/sdk/userlib/libfar/
|
||||||
!/sdk/userlib/libitcm/
|
!/sdk/userlib/libitcm/
|
||||||
!/sdk/userlib/md5/
|
!/sdk/userlib/md5/
|
||||||
|
@ -285,6 +285,14 @@ __isEmulator: @ Only to be called once!
|
|||||||
.Lmov_r0_1:
|
.Lmov_r0_1:
|
||||||
mov 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
|
.macro swiimp name num
|
||||||
.align 2
|
.align 2
|
||||||
.global \name
|
.global \name
|
||||||
|
@ -159,13 +159,12 @@ BEGIN_TABLE(FEOSDSHW)
|
|||||||
ADD_FUNC_(DSLoadARM7),
|
ADD_FUNC_(DSLoadARM7),
|
||||||
ADD_FUNC_(DSModeShim),
|
ADD_FUNC_(DSModeShim),
|
||||||
ADD_FUNC_(DSProcessIRQs),
|
ADD_FUNC_(DSProcessIRQs),
|
||||||
ADD_FUNC_(DSSetIRQWaitFunc),
|
|
||||||
ADD_FUNC_(DSSetSuspendMode),
|
ADD_FUNC_(DSSetSuspendMode),
|
||||||
ADD_FUNC_(DSTimerTick),
|
ADD_FUNC_(DSTimerTick),
|
||||||
ADD_FUNC_(DSTimerWrite),
|
ADD_FUNC_(DSTimerWrite),
|
||||||
ADD_FUNC_(DSVideoReset),
|
ADD_FUNC_(DSVideoReset),
|
||||||
ADD_FUNC_(DSWaitForIRQ),
|
ADD_FUNC_(DSWaitForIRQ),
|
||||||
ADD_ALIAS(DSWaitForNextIRQ, DSWaitForNextIRQRaw),
|
ADD_FUNC_(DSWaitForNextIRQ),
|
||||||
ADD_FUNC_(bgClearControlBits),
|
ADD_FUNC_(bgClearControlBits),
|
||||||
ADD_FUNC_(bgExtPaletteDisable),
|
ADD_FUNC_(bgExtPaletteDisable),
|
||||||
ADD_FUNC_(bgExtPaletteDisableSub),
|
ADD_FUNC_(bgExtPaletteDisableSub),
|
||||||
|
@ -64,8 +64,6 @@ static inline bool AddressCheckMainRAM(const void* addr)
|
|||||||
#define E_INVALIDARG (-11)
|
#define E_INVALIDARG (-11)
|
||||||
#define E_APPKILLED (-12)
|
#define E_APPKILLED (-12)
|
||||||
|
|
||||||
typedef void (*irqWaitFunc_t)(word_t);
|
|
||||||
|
|
||||||
void DSRunFifoQueue();
|
void DSRunFifoQueue();
|
||||||
void DSFifoSetDatamsgHandler(int channel, FifoDatamsgHandlerFunc handler, void* userdata);
|
void DSFifoSetDatamsgHandler(int channel, FifoDatamsgHandlerFunc handler, void* userdata);
|
||||||
void DSFifoSetValue32Handler(int channel, FifoValue32HandlerFunc handler, void* userdata);
|
void DSFifoSetValue32Handler(int channel, FifoValue32HandlerFunc handler, void* userdata);
|
||||||
@ -76,6 +74,7 @@ word_t DSProcessIRQs();
|
|||||||
void DSWaitForIRQ(word_t mask);
|
void DSWaitForIRQ(word_t mask);
|
||||||
void DSWaitForIRQRaw(word_t mask);
|
void DSWaitForIRQRaw(word_t mask);
|
||||||
word_t DSWaitForNextIRQRaw();
|
word_t DSWaitForNextIRQRaw();
|
||||||
|
word_t DSWaitForNextIRQ();
|
||||||
|
|
||||||
static inline void DSWaitForVBlank()
|
static inline void DSWaitForVBlank()
|
||||||
{
|
{
|
||||||
@ -87,9 +86,6 @@ static inline void DSWaitForVBlankRaw()
|
|||||||
DSWaitForIRQRaw(IRQ_VBLANK);
|
DSWaitForIRQRaw(IRQ_VBLANK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GET_IRQFUNC ((irqWaitFunc_t)0xFFFFFFFF)
|
|
||||||
irqWaitFunc_t DSSetIRQWaitFunc(irqWaitFunc_t newFunc);
|
|
||||||
|
|
||||||
int __getMode();
|
int __getMode();
|
||||||
#define isUserMode() (__getMode() == 0x10)
|
#define isUserMode() (__getMode() == 0x10)
|
||||||
|
|
||||||
@ -130,6 +126,13 @@ typedef struct
|
|||||||
} executeStatus_t;
|
} executeStatus_t;
|
||||||
|
|
||||||
extern executeStatus_t* curExecStatus;
|
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
|
#ifdef LIBFAT_FEOS_MULTICWD
|
||||||
char* _getCwdBuf();
|
char* _getCwdBuf();
|
||||||
|
@ -375,23 +375,6 @@ void coop_swiIntrWaitCompat(word_t how, word_t what)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 DSWaitForNextIRQRaw()
|
||||||
{
|
{
|
||||||
word_t flags = 0;
|
word_t flags = 0;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "feos.h"
|
#include "feos.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "feosfifo.h"
|
#include "feosfifo.h"
|
||||||
|
#include "thread.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -38,14 +39,6 @@ void KeSetExcptHandler(void*);
|
|||||||
|
|
||||||
// Execution status functions
|
// 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);
|
typedef int (* systemfunc_t)(const char* command);
|
||||||
|
|
||||||
systemfunc_t __system;
|
systemfunc_t __system;
|
||||||
@ -404,10 +397,6 @@ BEGIN_TABLE(FEOSKRNL)
|
|||||||
ADD_FUNC_(KeDiv3232),
|
ADD_FUNC_(KeDiv3232),
|
||||||
ADD_FUNC_(KeDiv6432),
|
ADD_FUNC_(KeDiv6432),
|
||||||
ADD_FUNC_(KeDiv6464),
|
ADD_FUNC_(KeDiv6464),
|
||||||
ADD_FUNC_(KeExecStatusAddRef),
|
|
||||||
ADD_FUNC_(KeExecStatusCreate),
|
|
||||||
ADD_FUNC_(KeExecStatusRelease),
|
|
||||||
ADD_FUNC_(KeGetCurExecStatus),
|
|
||||||
ADD_FUNC_(KeGetDiskStats),
|
ADD_FUNC_(KeGetDiskStats),
|
||||||
ADD_ALIAS(KeGetErrnoPtr, __errno),
|
ADD_ALIAS(KeGetErrnoPtr, __errno),
|
||||||
ADD_FUNC_(KeGetMemStats),
|
ADD_FUNC_(KeGetMemStats),
|
||||||
@ -417,7 +406,6 @@ BEGIN_TABLE(FEOSKRNL)
|
|||||||
ADD_FUNC_(KeMod3232),
|
ADD_FUNC_(KeMod3232),
|
||||||
ADD_FUNC_(KeMod6432),
|
ADD_FUNC_(KeMod6432),
|
||||||
ADD_FUNC_(KeMod6464),
|
ADD_FUNC_(KeMod6464),
|
||||||
ADD_FUNC_(KeSetCurExecStatus),
|
|
||||||
ADD_FUNC_(KeSetExcptHandler),
|
ADD_FUNC_(KeSetExcptHandler),
|
||||||
ADD_FUNC_(KeSqrt32),
|
ADD_FUNC_(KeSqrt32),
|
||||||
ADD_FUNC_(KeSqrt64),
|
ADD_FUNC_(KeSqrt64),
|
||||||
@ -432,11 +420,24 @@ BEGIN_TABLE(FEOSKRNL)
|
|||||||
ADD_FUNC_(LdrLoadModule),
|
ADD_FUNC_(LdrLoadModule),
|
||||||
ADD_FUNC_(LdrLockModule),
|
ADD_FUNC_(LdrLockModule),
|
||||||
ADD_FUNC_(LdrResGetSize),
|
ADD_FUNC_(LdrResGetSize),
|
||||||
ADD_FUNC_(LdrResolveAddr),
|
|
||||||
ADD_FUNC_(LdrResRead),
|
ADD_FUNC_(LdrResRead),
|
||||||
ADD_FUNC_(LdrResSeek),
|
ADD_FUNC_(LdrResSeek),
|
||||||
ADD_FUNC_(LdrResTell),
|
ADD_FUNC_(LdrResTell),
|
||||||
|
ADD_FUNC_(LdrResolveAddr),
|
||||||
ADD_FUNC_(LdrUnlockModule),
|
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_idiv),
|
||||||
ADD_FUNC_(__aeabi_idivmod),
|
ADD_FUNC_(__aeabi_idivmod),
|
||||||
ADD_FUNC_(__aeabi_ldivmod),
|
ADD_FUNC_(__aeabi_ldivmod),
|
||||||
@ -605,14 +606,14 @@ execstat_t KeExecStatusCreate()
|
|||||||
|
|
||||||
void KeExecStatusAddRef(execstat_t hSt)
|
void KeExecStatusAddRef(execstat_t hSt)
|
||||||
{
|
{
|
||||||
if (hSt == (execstat_t) &defaultExecStatus) return;
|
if (hSt == &defaultExecStatus) return;
|
||||||
((executeStatus_t*)hSt)->refcount ++;
|
hSt->refcount ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeExecStatusRelease(execstat_t hSt)
|
void KeExecStatusRelease(execstat_t hSt)
|
||||||
{
|
{
|
||||||
if (hSt == (execstat_t) &defaultExecStatus) return;
|
if (hSt == &defaultExecStatus) return;
|
||||||
word_t r = --((executeStatus_t*)hSt)->refcount;
|
word_t r = --hSt->refcount;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
free(hSt);
|
free(hSt);
|
||||||
}
|
}
|
||||||
@ -622,7 +623,7 @@ void KeSetCurExecStatus(execstat_t hSt)
|
|||||||
#ifdef LIBFAT_FEOS_MULTICWD
|
#ifdef LIBFAT_FEOS_MULTICWD
|
||||||
curExecStatus->cwdCluster = g_fatCwdCluster;
|
curExecStatus->cwdCluster = g_fatCwdCluster;
|
||||||
#endif
|
#endif
|
||||||
curExecStatus = (executeStatus_t*) hSt;
|
curExecStatus = hSt;
|
||||||
#ifdef LIBFAT_FEOS_MULTICWD
|
#ifdef LIBFAT_FEOS_MULTICWD
|
||||||
g_fatCwdCluster = curExecStatus->cwdCluster;
|
g_fatCwdCluster = curExecStatus->cwdCluster;
|
||||||
_setCwdBuf(curExecStatus->cwdBuffer);
|
_setCwdBuf(curExecStatus->cwdBuffer);
|
||||||
@ -631,7 +632,7 @@ void KeSetCurExecStatus(execstat_t hSt)
|
|||||||
|
|
||||||
execstat_t KeGetCurExecStatus()
|
execstat_t KeGetCurExecStatus()
|
||||||
{
|
{
|
||||||
return (execstat_t) curExecStatus;
|
return curExecStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LdrCurModule curExecStatus->curModule
|
#define LdrCurModule curExecStatus->curModule
|
||||||
|
@ -527,6 +527,10 @@ void* LdrFindInTbl(const fxe_inmem_exports* exphdr, const char* name)
|
|||||||
return exphdr->table[mid].addr;
|
return exphdr->table[mid].addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
iprintf("{DBG} Cannot resolve %s\n", name);
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "feos.h"
|
#include "feos.h"
|
||||||
|
#include "thread.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -378,6 +379,7 @@ int main()
|
|||||||
#ifdef LIBFAT_FEOS_MULTICWD
|
#ifdef LIBFAT_FEOS_MULTICWD
|
||||||
g_fatCwdClusterPtr = (vu32*) _FAT_getCwdClusterPtr("/");
|
g_fatCwdClusterPtr = (vu32*) _FAT_getCwdClusterPtr("/");
|
||||||
KeInitDefaultExecStatus();
|
KeInitDefaultExecStatus();
|
||||||
|
ThrInit();
|
||||||
#endif
|
#endif
|
||||||
InstallThunks();
|
InstallThunks();
|
||||||
#ifdef LIBFAT_FEOS_MULTICWD
|
#ifdef LIBFAT_FEOS_MULTICWD
|
||||||
|
@ -1,20 +1,4 @@
|
|||||||
#include <multifeos.h>
|
#include "thread.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;
|
|
||||||
|
|
||||||
threadSt _firstThread;
|
threadSt _firstThread;
|
||||||
|
|
||||||
@ -25,22 +9,18 @@ int threadsFinished = 0;
|
|||||||
|
|
||||||
#define inactiveThreadCount() (threadsWaiting + threadsFinished)
|
#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();
|
static threadSt* _irqWaitCheck();
|
||||||
|
|
||||||
FEOSINIT void initFirstThread()
|
void ThrInit()
|
||||||
{
|
{
|
||||||
curThread->execStat = FeOS_GetCurExecStatus();
|
curThread->execStat = KeGetCurExecStatus();
|
||||||
curThread->prev = curThread;
|
curThread->prev = curThread;
|
||||||
curThread->next = 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
|
// 32-bit align the stack size
|
||||||
stackSize += 3;
|
stackSize += 3;
|
||||||
@ -51,8 +31,8 @@ thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param)
|
|||||||
|
|
||||||
threadSt* t = (threadSt*) (mem + stackSize);
|
threadSt* t = (threadSt*) (mem + stackSize);
|
||||||
t->stack = (word_t*) mem;
|
t->stack = (word_t*) mem;
|
||||||
t->execStat = FeOS_GetCurExecStatus();
|
t->execStat = KeGetCurExecStatus();
|
||||||
FeOS_ExecStatusAddRef(t->execStat);
|
KeExecStatusAddRef(t->execStat);
|
||||||
t->flags = curThread->flags & THREAD_HIGHPRIO;
|
t->flags = curThread->flags & THREAD_HIGHPRIO;
|
||||||
|
|
||||||
threadSt* insPoint;
|
threadSt* insPoint;
|
||||||
@ -75,20 +55,20 @@ thread_t FeOS_CreateThread(word_t stackSize, threadEP_t entryPoint, void* param)
|
|||||||
nThreads ++;
|
nThreads ++;
|
||||||
|
|
||||||
if (!setjmp(thisThread->ctx))
|
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)
|
void _doYield(threadSt* t)
|
||||||
{
|
{
|
||||||
curThread = t;
|
curThread = t;
|
||||||
|
|
||||||
FeOS_SetCurExecStatus(curThread->execStat);
|
KeSetCurExecStatus(curThread->execStat);
|
||||||
longjmp(curThread->ctx, 1);
|
longjmp(curThread->ctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeOS_Yield()
|
void ThrYield()
|
||||||
{
|
{
|
||||||
threadSt* t = curThread;
|
threadSt* t = curThread;
|
||||||
|
|
||||||
@ -113,7 +93,7 @@ void FeOS_Yield()
|
|||||||
while ((t->flags & THREAD_DETACHED) && (t->flags & THREAD_EXIT))
|
while ((t->flags & THREAD_DETACHED) && (t->flags & THREAD_EXIT))
|
||||||
{
|
{
|
||||||
threadSt* next = t->next;
|
threadSt* next = t->next;
|
||||||
FeOS_FreeThread(t);
|
ThrFree(t);
|
||||||
t = next;
|
t = next;
|
||||||
}
|
}
|
||||||
} while (t->flags & THREAD_EXECBITS);
|
} while (t->flags & THREAD_EXECBITS);
|
||||||
@ -121,31 +101,30 @@ void FeOS_Yield()
|
|||||||
_doYield(t);
|
_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;
|
if (curThread == &_firstThread) return;
|
||||||
curThread->flags |= THREAD_EXIT;
|
curThread->flags |= THREAD_EXIT;
|
||||||
curThread->rc = rc;
|
curThread->rc = rc;
|
||||||
threadsFinished ++;
|
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 (t == &_firstThread) return;
|
||||||
if (hThread == (thread_t) curThread) return;
|
if (t == curThread) return;
|
||||||
|
|
||||||
threadSt* t = (threadSt*) hThread;
|
|
||||||
if (t->flags & THREAD_IRQWAIT)
|
if (t->flags & THREAD_IRQWAIT)
|
||||||
threadsWaiting --;
|
threadsWaiting --;
|
||||||
if (t->flags & THREAD_EXIT)
|
if (t->flags & THREAD_EXIT)
|
||||||
@ -153,29 +132,28 @@ void FeOS_FreeThread(thread_t hThread)
|
|||||||
t->prev->next = t->next;
|
t->prev->next = t->next;
|
||||||
t->next->prev = t->prev;
|
t->next->prev = t->prev;
|
||||||
free(t->stack);
|
free(t->stack);
|
||||||
FeOS_ExecStatusRelease(t->execStat);
|
KeExecStatusRelease(t->execStat);
|
||||||
nThreads --;
|
nThreads --;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FeOS_ThreadJoin(thread_t hThread)
|
int ThrJoin(thread_t hThread)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
while (FeOS_IsThreadActive(hThread)) FeOS_Idle();
|
while (ThrIsActive(hThread)) DSWaitForIRQ(~0);
|
||||||
rc = FeOS_GetThreadRC(hThread);
|
rc = ThrGetExitCode(hThread);
|
||||||
FeOS_FreeThread(hThread);
|
ThrFree(hThread);
|
||||||
return rc;
|
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;
|
word_t flag = (prio == PRIORITY_HIGH) ? THREAD_HIGHPRIO : 0;
|
||||||
if ((t->flags & flag) == flag) return;
|
if ((t->flags & flag) == flag) return;
|
||||||
t->flags &= ~THREAD_HIGHPRIO;
|
t->flags &= ~THREAD_HIGHPRIO;
|
||||||
t->flags |= flag;
|
t->flags |= flag;
|
||||||
|
|
||||||
// Can't change position of the first thread
|
// 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
|
// Pull the thread out of the list
|
||||||
t->prev->next = t->next;
|
t->prev->next = t->next;
|
||||||
@ -189,9 +167,9 @@ void FeOS_SetThreadPrio(thread_t hThread, int prio)
|
|||||||
t->prev->next = t;
|
t->prev->next = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FeOS_GetThreadRC(thread_t hThread)
|
int ThrGetExitCode(thread_t hThread)
|
||||||
{
|
{
|
||||||
return ((threadSt*)hThread)->rc;
|
return hThread->rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -203,16 +181,17 @@ typedef struct
|
|||||||
static int _execAsyncEP(void* _param)
|
static int _execAsyncEP(void* _param)
|
||||||
{
|
{
|
||||||
execParams* params = (void*) _param;
|
execParams* params = (void*) _param;
|
||||||
FeOS_ExecStatusRelease(curThread->execStat);
|
execstat_t es = KeExecStatusCreate();
|
||||||
curThread->execStat = FeOS_ExecStatusCreate();
|
if (!es) return -4;
|
||||||
if (!curThread->execStat) return -1;
|
KeExecStatusRelease(curThread->execStat);
|
||||||
FeOS_SetCurExecStatus(curThread->execStat);
|
curThread->execStat = es;
|
||||||
int rc = FeOS_Execute(params->argc, params->argv);
|
KeSetCurExecStatus(curThread->execStat);
|
||||||
|
int rc = LdrExecuteArgv(params->argc, params->argv);
|
||||||
free(_param);
|
free(_param);
|
||||||
return rc;
|
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));
|
execParams* params = (execParams*) malloc(sizeof(execParams));
|
||||||
if (!params) return NULL;
|
if (!params) return NULL;
|
||||||
@ -220,7 +199,7 @@ thread_t FeOS_CreateProcess(int argc, const char* argv[])
|
|||||||
params->argc = argc;
|
params->argc = argc;
|
||||||
params->argv = argv;
|
params->argv = argv;
|
||||||
|
|
||||||
thread_t t = FeOS_CreateThread(16*1024, _execAsyncEP, params);
|
thread_t t = ThrCreate(16*1024, _execAsyncEP, params);
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
free(params);
|
free(params);
|
||||||
@ -232,52 +211,54 @@ thread_t FeOS_CreateProcess(int argc, const char* argv[])
|
|||||||
|
|
||||||
static int _runAsyncEP(void* _param)
|
static int _runAsyncEP(void* _param)
|
||||||
{
|
{
|
||||||
FeOS_ExecStatusRelease(curThread->execStat);
|
execstat_t es = KeExecStatusCreate();
|
||||||
curThread->execStat = FeOS_ExecStatusCreate();
|
if (!es) return -4;
|
||||||
|
KeExecStatusRelease(curThread->execStat);
|
||||||
|
curThread->execStat = es;
|
||||||
if (!curThread->execStat) return -1;
|
if (!curThread->execStat) return -1;
|
||||||
FeOS_SetCurExecStatus(curThread->execStat);
|
KeSetCurExecStatus(curThread->execStat);
|
||||||
return system((const char*)_param);
|
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;
|
return;
|
||||||
threadSt* t = (threadSt*) hThread;
|
|
||||||
t->flags |= THREAD_DETACHED;
|
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;
|
execstat_t oldSt = curThread->execStat;
|
||||||
curThread->execStat = t->execStat;
|
curThread->execStat = t->execStat;
|
||||||
FeOS_SetCurExecStatus(curThread->execStat);
|
KeExecStatusAddRef(curThread->execStat);
|
||||||
|
KeSetCurExecStatus(curThread->execStat);
|
||||||
int rc = func(param);
|
int rc = func(param);
|
||||||
curThread->execStat = oldSt;
|
curThread->execStat = oldSt;
|
||||||
FeOS_SetCurExecStatus(curThread->execStat);
|
KeSetCurExecStatus(curThread->execStat);
|
||||||
|
KeExecStatusRelease(curThread->execStat);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _irqWaitYield(word_t mask)
|
void DSWaitForIRQ(word_t mask)
|
||||||
{
|
{
|
||||||
threadsWaiting ++;
|
threadsWaiting ++;
|
||||||
curThread->irqMask = mask;
|
curThread->irqMask = mask;
|
||||||
curThread->flags |= THREAD_IRQWAIT;
|
curThread->flags |= THREAD_IRQWAIT;
|
||||||
FeOS_Yield();
|
ThrYield();
|
||||||
}
|
}
|
||||||
|
|
||||||
word_t FeOS_NextIRQYield()
|
word_t DSWaitForNextIRQ()
|
||||||
{
|
{
|
||||||
threadsWaiting ++;
|
threadsWaiting ++;
|
||||||
curThread->irqMask = 0;
|
curThread->irqMask = 0;
|
||||||
curThread->flags |= THREAD_IRQWAIT;
|
curThread->flags |= THREAD_IRQWAIT;
|
||||||
FeOS_Yield();
|
ThrYield();
|
||||||
return curThread->irqMask;
|
return curThread->irqMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +280,7 @@ threadSt* _irqWaitCheck()
|
|||||||
|
|
||||||
// Get the interrupt mask. If all other threads are inactive (such as waiting for IRQs),
|
// Get the interrupt mask. If all other threads are inactive (such as waiting for IRQs),
|
||||||
// we can then perform the wait for IRQ.
|
// 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
|
if (!mask) // implies inactiveThreadCount() != nThreads
|
||||||
return NULL;
|
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
|
\subsection api FeOS API
|
||||||
- \ref api_base "Core FeOS API"
|
- \ref api_base "Core FeOS API"
|
||||||
|
- \ref api_thr "FeOS Threading API"
|
||||||
- **FeOS libnds-compatible DS hardware access API**
|
- **FeOS libnds-compatible DS hardware access API**
|
||||||
- \ref api_ds "Basic functions"
|
- \ref api_ds "Basic functions"
|
||||||
- \ref api_math "Math functions"
|
- \ref api_math "Math functions"
|
||||||
@ -49,7 +50,6 @@ extern "C"
|
|||||||
- \ref api_dsspr "Sprite functions"
|
- \ref api_dsspr "Sprite functions"
|
||||||
|
|
||||||
\subsection userlibs System Libraries
|
\subsection userlibs System Libraries
|
||||||
- \ref multifeos.h "MultiFeOS (cooperative multitasking)"
|
|
||||||
- \ref feoswifi "FeOSWifi (dswifi for FeOS)"
|
- \ref feoswifi "FeOSWifi (dswifi for FeOS)"
|
||||||
- \ref feos3d.h "FeOS3D (libnds videoGL for FeOS)"
|
- \ref feos3d.h "FeOS3D (libnds videoGL for FeOS)"
|
||||||
- \ref far.h "libfar (FeOS ARchives)"
|
- \ref far.h "libfar (FeOS ARchives)"
|
||||||
@ -67,6 +67,7 @@ extern "C"
|
|||||||
#include <feosuser.h>
|
#include <feosuser.h>
|
||||||
#include <feosmath.h>
|
#include <feosmath.h>
|
||||||
#include <feosdsapi.h>
|
#include <feosdsapi.h>
|
||||||
|
#include <feosthr.h>
|
||||||
#include <feosdsspr.h>
|
#include <feosdsspr.h>
|
||||||
#include <feosdsbg.h>
|
#include <feosdsbg.h>
|
||||||
#else
|
#else
|
||||||
|
@ -401,13 +401,6 @@ static inline void swiWaitForVBlank()
|
|||||||
DSWaitForIRQ(IRQ_VBLANK);
|
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.
|
//! \brief Writes a value into a timer register.
|
||||||
void DSTimerWrite(int, word_t);
|
void DSTimerWrite(int, word_t);
|
||||||
//! \brief Reads a timer's counting value.
|
//! \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.
|
//! \brief Decreases the reference count of the callers' module.
|
||||||
#define LdrEndResidency() LdrUnlockModule(LdrGetSelf())
|
#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.
|
//! \brief Executes the specified argc and argv.
|
||||||
int LdrExecuteArgv(int, const char*[]);
|
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 \
|
DSLoadARM7 \
|
||||||
DSModeShim \
|
DSModeShim \
|
||||||
DSProcessIRQs \
|
DSProcessIRQs \
|
||||||
DSSetIRQWaitFunc \
|
|
||||||
DSSetSuspendMode \
|
DSSetSuspendMode \
|
||||||
DSTimerTick \
|
DSTimerTick \
|
||||||
DSTimerWrite \
|
DSTimerWrite \
|
||||||
|
@ -20,10 +20,6 @@ IoSetStdout \
|
|||||||
KeDiv3232 \
|
KeDiv3232 \
|
||||||
KeDiv6432 \
|
KeDiv6432 \
|
||||||
KeDiv6464 \
|
KeDiv6464 \
|
||||||
KeExecStatusAddRef \
|
|
||||||
KeExecStatusCreate \
|
|
||||||
KeExecStatusRelease \
|
|
||||||
KeGetCurExecStatus \
|
|
||||||
KeGetDiskStats \
|
KeGetDiskStats \
|
||||||
KeGetErrnoPtr \
|
KeGetErrnoPtr \
|
||||||
KeGetMemStats \
|
KeGetMemStats \
|
||||||
@ -33,7 +29,6 @@ KeGetTickCount \
|
|||||||
KeMod3232 \
|
KeMod3232 \
|
||||||
KeMod6432 \
|
KeMod6432 \
|
||||||
KeMod6464 \
|
KeMod6464 \
|
||||||
KeSetCurExecStatus \
|
|
||||||
KeSetExcptHandler \
|
KeSetExcptHandler \
|
||||||
KeSqrt32 \
|
KeSqrt32 \
|
||||||
KeSqrt64 \
|
KeSqrt64 \
|
||||||
@ -48,11 +43,24 @@ LdrGetModuleName \
|
|||||||
LdrLoadModule \
|
LdrLoadModule \
|
||||||
LdrLockModule \
|
LdrLockModule \
|
||||||
LdrResGetSize \
|
LdrResGetSize \
|
||||||
LdrResolveAddr \
|
|
||||||
LdrResRead \
|
LdrResRead \
|
||||||
LdrResSeek \
|
LdrResSeek \
|
||||||
LdrResTell \
|
LdrResTell \
|
||||||
|
LdrResolveAddr \
|
||||||
LdrUnlockModule \
|
LdrUnlockModule \
|
||||||
|
PsCreateFromArgv \
|
||||||
|
PsCreateFromCmdLine \
|
||||||
|
ThrCreate \
|
||||||
|
ThrDetach \
|
||||||
|
ThrGetSelf \
|
||||||
|
ThrExit \
|
||||||
|
ThrFree \
|
||||||
|
ThrGetExitCode \
|
||||||
|
ThrIsActive \
|
||||||
|
ThrJoin \
|
||||||
|
ThrRunInContext \
|
||||||
|
ThrSetPriority \
|
||||||
|
ThrYield \
|
||||||
__aeabi_idiv \
|
__aeabi_idiv \
|
||||||
__aeabi_idivmod \
|
__aeabi_idivmod \
|
||||||
__aeabi_ldivmod \
|
__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