Integrate MultiFeOS into the kernel

This commit is contained in:
fincs 2013-08-10 20:24:29 +02:00
parent a53ba81701
commit f52d938521
20 changed files with 266 additions and 282 deletions

1
.gitignore vendored
View File

@ -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/

View File

@ -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

View File

@ -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),

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

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

View File

@ -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

View File

@ -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
View 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;
}
/** @} */

View File

@ -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
View 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

View File

@ -13,7 +13,6 @@ DSGetSubOAM \
DSLoadARM7 \
DSModeShim \
DSProcessIRQs \
DSSetIRQWaitFunc \
DSSetSuspendMode \
DSTimerTick \
DSTimerWrite \

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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