mirror of
https://github.com/rvtr/ctr_firmware.git
synced 2025-10-31 07:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_firmware@118 b871894f-2f95-9b40-918c-086798483c85
2078 lines
58 KiB
C
2078 lines
58 KiB
C
/*---------------------------------------------------------------------------*
|
||
Project: CtrBrom - libraries - OS
|
||
File: os_init.c
|
||
|
||
Copyright 2008 Nintendo. All rights reserved.
|
||
|
||
These coded instructions, statements, and computer programs contain
|
||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||
Company Ltd., and are protected by Federal copyright law. They may
|
||
not be disclosed to third parties or copied or duplicated in any form,
|
||
in whole or in part, without the prior written consent of Nintendo.
|
||
|
||
$Date:: $
|
||
$Rev$
|
||
$Author$
|
||
*---------------------------------------------------------------------------*/
|
||
#include <brom/os.h>
|
||
|
||
#define osPrintf(...) ((void)0)
|
||
#define osTPrintf(...) ((void)0)
|
||
#define i_osPanic(...) ((void)0)
|
||
|
||
//---------------------------------------------------------------------------
|
||
|
||
extern unsigned long SDK_SYS_STACKSIZE[];
|
||
extern unsigned long SDK_IRQ_STACKSIZE[];
|
||
#define OSi_SYS_STACKSIZE ((s32)SDK_SYS_STACKSIZE)
|
||
#define OSi_IRQ_STACKSIZE ((s32)SDK_IRQ_STACKSIZE)
|
||
|
||
//---- Stack CheckNumber
|
||
#ifdef SDK_ARM9
|
||
# define OSi_STACK_CHECKNUM_BOTTOM 0xfddb597dUL
|
||
# define OSi_STACK_CHECKNUM_TOP 0x7bf9dd5bUL
|
||
# define OSi_STACK_CHECKNUM_WARN 0x597dfbd9UL
|
||
#else // SDK_ARM11
|
||
# define OSi_STACK_CHECKNUM_BOTTOM 0xd73bfdf7UL
|
||
# define OSi_STACK_CHECKNUM_TOP 0xfbdd37bbUL
|
||
# define OSi_STACK_CHECKNUM_WARN 0xbdf7db3dUL
|
||
#endif
|
||
|
||
//---- defs for launcher thread stack
|
||
#ifdef SDK_ARM9
|
||
extern void *Load$$DTCM$$Base;
|
||
# define OSi_LAUNCHER_STACK_LO_DEFAULT (Load$$DTCM$$Base)
|
||
#else // SDK_ARM11
|
||
# define OSi_LAUNCHER_STACK_LO_DEFAULT HW_AXI_WRAM
|
||
#endif
|
||
# define OSi_LAUNCHER_STACK_HI_MAX (HW_BROM_SVC_STACK - OSi_IRQ_STACKSIZE)
|
||
# define OSi_LAUNCHER_STACK_BOTTOM (HW_BROM_SVC_STACK - OSi_IRQ_STACKSIZE)
|
||
|
||
//---- defs for idle thread
|
||
// for checkNumber and SVC stack (if defined)
|
||
#ifdef SDK_CONTEXT_HAS_SP_SVC
|
||
#define OSi_IDLE_CHECKNUM_SIZE ( sizeof(u32)*2 + HW_BROM_SVC_STACK_SIZE )
|
||
#else
|
||
#define OSi_IDLE_CHECKNUM_SIZE ( sizeof(u32)*2 )
|
||
#endif
|
||
// for SVC to stack out registers
|
||
#ifdef SDK_ARM9
|
||
#define OSi_IDLE_SVC_SIZE ( sizeof(u32)*32 ) // arm9 svc stacks 14 words and makes in 8byte-alignment
|
||
#else // SDK_ARM11
|
||
#define OSi_IDLE_SVC_SIZE ( sizeof(u32)*16 ) // arm7 svc stacks 14 words
|
||
#endif
|
||
// stack size of idle thread
|
||
#define OSi_IDLE_THREAD_STACK_SIZE ( OSi_IDLE_CHECKNUM_SIZE + OSi_IDLE_SVC_SIZE )
|
||
|
||
#if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
|
||
#include <brom/itcm_begin.h>
|
||
#endif
|
||
//---- threads
|
||
OSThread i_osLauncherThread;
|
||
OSThread i_osIdleThread;
|
||
|
||
//---- thread information
|
||
OSThreadInfo i_osThreadInfo;
|
||
|
||
//---- current thread pointer (for quick reference)
|
||
OSThread **i_osCurrentThreadPtr;
|
||
#define i_osGetCurrentThread() (*i_osCurrentThreadPtr)
|
||
|
||
//---- thread initialization flag
|
||
BOOL i_osIsThreadInitialized = FALSE;
|
||
|
||
//---- idle thread stack
|
||
u32 i_osIdleThreadStack[OSi_IDLE_THREAD_STACK_SIZE / sizeof(u32)];
|
||
|
||
//---- system callback in switch thread ( maybe for profile )
|
||
void *i_osSystemCallbackInSwitchThread = NULL;
|
||
|
||
//---- reschedule counter. if value>=0, do not reschedule.
|
||
u32 i_osRescheduleCount = 0;
|
||
#if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
|
||
#include <brom/itcm_end.h>
|
||
#endif
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
//---- thread id count
|
||
static int i_osThreadIdCount = 0;
|
||
#endif
|
||
|
||
void *i_osStackForDestructor = NULL;
|
||
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
static int i_osSearchFreeEntry(void);
|
||
#endif
|
||
static void i_osCancelThreadAlarmForSleep(OSThread *thread);
|
||
static void i_osInsertThreadToList(OSThread *thread);
|
||
static void i_osRemoveThreadFromList(OSThread *thread);
|
||
static void i_osSleepAlarmCallback(void *arg);
|
||
static void i_osIdleThreadProc(void *);
|
||
void i_osSetSystemCallbackInSwitchThread(void *callback);
|
||
|
||
static void i_osExitThread_ArgSpecified(OSThread *thread, void *arg);
|
||
static void i_osExitThread(void *arg);
|
||
static void i_osExitThread_Destroy(void);
|
||
|
||
#if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
|
||
#include <brom/itcm_begin.h>
|
||
#endif
|
||
static void i_osRescheduleThread(void);
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osGetUnusedThreadId
|
||
|
||
Description: get unused thread id
|
||
|
||
Arguments: None
|
||
|
||
Returns: thread id (0-0x7fffffff) which is never used.
|
||
*---------------------------------------------------------------------------*/
|
||
static int i_osGetUnusedThreadId(void)
|
||
{
|
||
++i_osThreadIdCount;
|
||
SDK_ASSERT(i_osThreadIdCount > 0); // overflow check
|
||
return i_osThreadIdCount;
|
||
}
|
||
#endif /* ; */
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osInsertLinkToQueue
|
||
|
||
Description: insert thread to thread queue
|
||
|
||
Arguments: queue : thread queue
|
||
thread : thread to insert
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osInsertLinkToQueue(OSThreadQueue *queue, OSThread *thread)
|
||
{
|
||
OSThread *next = queue->head;
|
||
|
||
while (next && next->priority <= thread->priority)
|
||
{
|
||
if (next == thread)
|
||
{
|
||
return;
|
||
}
|
||
next = next->link.next;
|
||
}
|
||
|
||
if (!next)
|
||
{
|
||
OSThread *prev = queue->tail;
|
||
|
||
if (!prev)
|
||
{
|
||
queue->head = thread;
|
||
}
|
||
else
|
||
{
|
||
prev->link.next = thread;
|
||
}
|
||
|
||
thread->link.prev = prev;
|
||
thread->link.next = NULL;
|
||
queue->tail = thread;
|
||
}
|
||
else
|
||
{
|
||
OSThread *prev = next->link.prev;
|
||
|
||
if (!prev)
|
||
{
|
||
queue->head = thread;
|
||
}
|
||
else
|
||
{
|
||
prev->link.next = thread;
|
||
}
|
||
|
||
thread->link.prev = prev;
|
||
thread->link.next = next;
|
||
next->link.prev = thread;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osRemoveLinkFromQueue
|
||
|
||
Description: remove head thread from thread queue
|
||
|
||
Arguments: queue : thread queue
|
||
|
||
Returns: thread pointer which is removed
|
||
*---------------------------------------------------------------------------*/
|
||
static OSThread *i_osRemoveLinkFromQueue(OSThreadQueue *queue)
|
||
{
|
||
OSThread *t = queue->head;
|
||
|
||
if (t)
|
||
{
|
||
OSThread *next = t->link.next;
|
||
|
||
queue->head = next;
|
||
|
||
if (next)
|
||
{
|
||
next->link.prev = NULL;
|
||
}
|
||
else
|
||
{
|
||
queue->tail = NULL;
|
||
t->queue = NULL;
|
||
}
|
||
}
|
||
|
||
return t;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osRemoveSpecifiedLinkFromQueue
|
||
|
||
Description: remove specified thread from thread queue
|
||
|
||
Arguments: queue : thread queue
|
||
|
||
Returns: thread pointer which is removed
|
||
*---------------------------------------------------------------------------*/
|
||
static OSThread *i_osRemoveSpecifiedLinkFromQueue(OSThreadQueue *queue, OSThread *thread)
|
||
{
|
||
OSThread *t = queue->head;
|
||
OSThread *next;
|
||
OSThread *prev;
|
||
|
||
while (t)
|
||
{
|
||
next = t->link.next;
|
||
|
||
if (t == thread)
|
||
{
|
||
prev = t->link.prev;
|
||
|
||
//---- whether if head link
|
||
if (queue->head == t)
|
||
{
|
||
queue->head = next;
|
||
}
|
||
else
|
||
{
|
||
prev->link.next = next;
|
||
}
|
||
|
||
//---- whether if tail link
|
||
if (queue->tail == t)
|
||
{
|
||
queue->tail = prev;
|
||
}
|
||
else
|
||
{
|
||
next->link.prev = prev;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
t = next;
|
||
}
|
||
|
||
return t;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osRemoveMutexLinkFromQueue
|
||
|
||
Description: remove mutex from mutex queue
|
||
|
||
Arguments: queue : mutex queue
|
||
|
||
Returns: mutex pointer which is removed
|
||
*---------------------------------------------------------------------------*/
|
||
OSMutex *i_osRemoveMutexLinkFromQueue(OSMutexQueue * queue)
|
||
{
|
||
OSMutex *t = queue->head;
|
||
|
||
if (t)
|
||
{
|
||
OSMutex *next = t->link.next;
|
||
|
||
queue->head = next;
|
||
|
||
if (next)
|
||
{
|
||
next->link.prev = NULL;
|
||
}
|
||
else
|
||
{
|
||
queue->tail = NULL;
|
||
}
|
||
}
|
||
|
||
return t;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osSetSystemCallbackInSwitchThread
|
||
|
||
Description: set system callback in switching thread
|
||
|
||
Arguments: callback
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void i_osSetSystemCallbackInSwitchThread(void *callback)
|
||
{
|
||
i_osSystemCallbackInSwitchThread = callback;
|
||
}
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osSearchFreeEntry
|
||
|
||
Description: search free thread entry area
|
||
|
||
Arguments: None
|
||
|
||
Returns: 0 - OS_THREAD_MAX_NUM-1 ... entry index
|
||
-1 ... not found
|
||
*---------------------------------------------------------------------------*/
|
||
static int i_osSearchFreeEntry(void)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < OS_THREAD_MAX_NUM; i++)
|
||
{
|
||
if (!i_osThreadInfo.entry[i])
|
||
{
|
||
return i;
|
||
}
|
||
}
|
||
return -1; // not found
|
||
}
|
||
#endif
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osInsertThreadToList
|
||
|
||
Description: insert thread to thread list which is arranged by priority
|
||
|
||
Arguments: pointer of thread
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osInsertThreadToList(OSThread *thread)
|
||
{
|
||
OSThread *t = i_osThreadInfo.list;
|
||
OSThread *pre = NULL;
|
||
|
||
while (t && t->priority < thread->priority)
|
||
{
|
||
pre = t;
|
||
t = t->next;
|
||
}
|
||
|
||
if (!pre)
|
||
{
|
||
thread->next = i_osThreadInfo.list;
|
||
i_osThreadInfo.list = thread;
|
||
}
|
||
else
|
||
{
|
||
thread->next = pre->next;
|
||
pre->next = thread;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osRemoveThreadFromList
|
||
|
||
Description: remove thread from thread list
|
||
|
||
Arguments: pointer of thread
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osRemoveThreadFromList(OSThread *thread)
|
||
{
|
||
OSThread *t = i_osThreadInfo.list;
|
||
OSThread *pre = NULL;
|
||
|
||
while (t && t != thread)
|
||
{
|
||
pre = t;
|
||
t = t->next;
|
||
}
|
||
|
||
SDK_ASSERTMSG(t, "Cannot remove thread from list.");
|
||
|
||
if (!pre)
|
||
{
|
||
i_osThreadInfo.list = thread->next;
|
||
}
|
||
else
|
||
{
|
||
pre->next = thread->next;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osRescheduleThread
|
||
|
||
Description: Switch to the runnable thread highest priority
|
||
without interrupts disabled.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None or Never return
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osRescheduleThread(void)
|
||
{
|
||
//---- if scheduler is set to be disabled, do nothing.
|
||
if (i_osRescheduleCount <= 0)
|
||
{
|
||
OSThreadInfo *info = &i_osThreadInfo;
|
||
if (info->irqDepth > 0 || osGetProcMode() == OS_PROCMODE_IRQ)
|
||
{
|
||
// If in IRQ, do rescheduling at end of IRQ handler
|
||
info->isNeedRescheduling = TRUE;
|
||
}
|
||
else
|
||
{
|
||
OSThread *currentThread, *nextThread;
|
||
currentThread = i_osGetCurrentThread();
|
||
nextThread = osSelectThread();
|
||
|
||
if (currentThread == nextThread || !nextThread) // maybe nextThread != NULL
|
||
{
|
||
return; // Don't have to switch the current context
|
||
}
|
||
|
||
if (currentThread->state != OS_THREAD_STATE_TERMINATED
|
||
&& osSaveContext(¤tThread->context))
|
||
{
|
||
return; // Return if go back via osLoadContext
|
||
}
|
||
|
||
//---- call thread switch callback for system
|
||
if (i_osSystemCallbackInSwitchThread)
|
||
{
|
||
((OSSwitchThreadCallback)i_osSystemCallbackInSwitchThread) (currentThread,
|
||
nextThread);
|
||
}
|
||
|
||
//---- call thread switch callback for user
|
||
if (info->switchCallback)
|
||
{
|
||
((OSSwitchThreadCallback)info->switchCallback) (currentThread, nextThread);
|
||
}
|
||
|
||
osSetCurrentThread(nextThread);
|
||
|
||
osLoadContext(&nextThread->context);
|
||
// Never reached
|
||
}
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osInitThread
|
||
|
||
Description: Initialize thread system
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osInitThread(void)
|
||
{
|
||
void *stackLo;
|
||
#ifndef SDK_THREAD_INFINITY
|
||
int i;
|
||
#endif
|
||
|
||
if (i_osIsThreadInitialized)
|
||
{
|
||
return;
|
||
}
|
||
i_osIsThreadInitialized = TRUE;
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
//---- Set thread info
|
||
for (i = 0; i < OS_THREAD_MAX_NUM; i++)
|
||
{
|
||
i_osThreadInfo.entry[i] = NULL;
|
||
}
|
||
#endif
|
||
|
||
//---- set pointer to current thread buffer
|
||
// (for quick reference)
|
||
i_osCurrentThreadPtr = &(i_osThreadInfo.current);
|
||
|
||
//---- Setup launcher thread
|
||
i_osLauncherThread.priority = OS_THREAD_LAUNCHER_PRIORITY;
|
||
i_osLauncherThread.id = 0;
|
||
i_osLauncherThread.state = OS_THREAD_STATE_READY;
|
||
i_osLauncherThread.next = NULL;
|
||
|
||
//---- clear profile pointer
|
||
i_osLauncherThread.profiler = NULL;
|
||
|
||
//---- clear thread entry and listPtr
|
||
#ifndef SDK_THREAD_INFINITY
|
||
i_osThreadInfo.entry[0] = &i_osLauncherThread;
|
||
#endif
|
||
i_osThreadInfo.list = &i_osLauncherThread;
|
||
|
||
//---- let launch thread be current
|
||
osSetCurrentThread(&i_osLauncherThread);
|
||
|
||
//---- StackLo
|
||
stackLo = (OSi_SYS_STACKSIZE <= 0) ?
|
||
(void *)((u32)OSi_LAUNCHER_STACK_LO_DEFAULT - OSi_SYS_STACKSIZE) :
|
||
(void *)((u32)OSi_LAUNCHER_STACK_HI_MAX - OSi_SYS_STACKSIZE);
|
||
SDK_ASSERT((u32)OSi_LAUNCHER_STACK_LO_DEFAULT <= (u32)stackLo
|
||
&& (u32)stackLo <= (u32)OSi_LAUNCHER_STACK_HI_MAX);
|
||
|
||
//---- set Stack Bottom & Top
|
||
i_osLauncherThread.stackBottom = (u32)OSi_LAUNCHER_STACK_BOTTOM;
|
||
i_osLauncherThread.stackTop = (u32)stackLo;
|
||
i_osLauncherThread.stackWarningOffset = 0;
|
||
|
||
//---- Set Stack CheckNumber
|
||
*(u32 *)(i_osLauncherThread.stackBottom - sizeof(u32)*2) = OSi_STACK_CHECKNUM_BOTTOM;
|
||
*(u32 *)i_osLauncherThread.stackTop = OSi_STACK_CHECKNUM_TOP;
|
||
|
||
//---- clear join queue
|
||
osInitThreadQueue(&i_osLauncherThread.joinQueue);
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
//---- max number of thread
|
||
i_osThreadInfo.max_entry = OS_THREAD_MAX_NUM;
|
||
#endif
|
||
|
||
//---- around IRQ
|
||
i_osThreadInfo.isNeedRescheduling = FALSE;
|
||
i_osThreadInfo.irqDepth = 0;
|
||
SDK_ASSERTMSG(OSi_IRQ_STACKSIZE > 0, "IRQ STACKSIZE must be >0");
|
||
|
||
//---- store thread info pointer
|
||
#if 0 // for ISD
|
||
#ifdef SDK_ARM9
|
||
osGetSystemWork()->threadinfo_mainp = &i_osThreadInfo;
|
||
#else
|
||
osGetSystemWork()->threadinfo_subp = &i_osThreadInfo;
|
||
#endif
|
||
#endif
|
||
|
||
//---- set thread switch callback
|
||
(void)osSetSwitchThreadCallback(NULL);
|
||
|
||
//---- idle thread
|
||
osCreateThread(&i_osIdleThread,
|
||
i_osIdleThreadProc,
|
||
(void *)NULL,
|
||
i_osIdleThreadStack + OSi_IDLE_THREAD_STACK_SIZE / sizeof(u32),
|
||
OSi_IDLE_THREAD_STACK_SIZE,
|
||
OS_THREAD_PRIORITY_MAX /*pseudo. change at next line. */ );
|
||
i_osIdleThread.priority = OS_THREAD_PRIORITY_MAX + 1; // lower priority than the lowest (=OS_THREAD_PRIORITY_MAX)
|
||
i_osIdleThread.state = OS_THREAD_STATE_READY;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osIsThreadAvailable
|
||
|
||
Description: check if thread system is available
|
||
|
||
Arguments: None
|
||
|
||
Returns: TRUE if available, FALSE if not
|
||
*---------------------------------------------------------------------------*/
|
||
#include <brom/code32.h>
|
||
asm BOOL osIsThreadAvailable( void )
|
||
{
|
||
INASM_EXTERN( i_osIsThreadInitialized )
|
||
|
||
ldr r0, =i_osIsThreadInitialized
|
||
ldr r0, [r0, #0]
|
||
bx lr
|
||
}
|
||
#include <brom/codereset.h>
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osCreateThread
|
||
|
||
Description: Creates a new thread
|
||
|
||
Arguments: thread pointer of thread structure
|
||
func function to start thread
|
||
arg argument for func
|
||
stack stack bottom address
|
||
stackSize stack size (byte. must be aligned by 4)
|
||
prio thread priority
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osCreateThread(OSThread *thread,
|
||
void (*func) (void *), void *arg, void *stack, u32 stackSize, u32 prio)
|
||
{
|
||
#define STACK_ALIGN 4
|
||
|
||
OSIntrMode enable;
|
||
int index;
|
||
|
||
SDK_ASSERTMSG(i_osGetCurrentThread(), "thread system were not initialized");
|
||
SDK_ASSERTMSG(OS_THREAD_PRIORITY_MIN <= prio
|
||
&& prio <= OS_THREAD_PRIORITY_MAX, "invalid priority");
|
||
SDK_ASSERTMSG(stackSize % STACK_ALIGN == 0, "stack size must be aligned by %d", STACK_ALIGN);
|
||
SDK_ASSERTMSG((u32)stack % STACK_ALIGN == 0, "stack must be aligned by %d", STACK_ALIGN);
|
||
|
||
enable = osDisableInterrupts();
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
//---- search free entry
|
||
if ((index = i_osSearchFreeEntry()) < 0)
|
||
{
|
||
SDK_ASSERTMSG(index >= 0, "osCreateThread: thread entry not allocated");
|
||
(void)osRestoreInterrupts(enable);
|
||
return;
|
||
}
|
||
#else
|
||
index = i_osGetUnusedThreadId();
|
||
#endif
|
||
|
||
//---- setup thread
|
||
thread->priority = prio;
|
||
thread->id = (u32)index;
|
||
thread->state = OS_THREAD_STATE_WAITING;
|
||
|
||
//---- clear profile pointer
|
||
thread->profiler = NULL;
|
||
|
||
//---- set thread entry and listPtr
|
||
#ifndef SDK_THREAD_INFINITY
|
||
i_osThreadInfo.entry[index] = thread;
|
||
#endif
|
||
i_osInsertThreadToList(thread);
|
||
|
||
//---- set Stack Bottom & Top
|
||
thread->stackBottom = (u32)stack;
|
||
thread->stackTop = (u32)stack - stackSize;
|
||
thread->stackWarningOffset = 0;
|
||
|
||
//---- Set Stack CheckNumber
|
||
*(u32 *)(thread->stackBottom - sizeof(u32)*2) = OSi_STACK_CHECKNUM_BOTTOM; // minus for stack CheckNumber and padding
|
||
*(u32 *)thread->stackTop = OSi_STACK_CHECKNUM_TOP;
|
||
|
||
//---- clear join queue
|
||
osInitThreadQueue(&thread->joinQueue);
|
||
|
||
//---- Init context
|
||
osInitContext(&thread->context, (u32)func, (u32)stack - sizeof(u32)*2); // minus for stack CheckNumber and padding
|
||
|
||
thread->context.r[0] = (u32)arg; // argument for func
|
||
thread->context.lr = (u32)osExitThread;
|
||
|
||
//---- clear Stack (except check code (=sizeof(u32)*2) and padding(sizeof(u32))
|
||
miCpuClear32((void *)((u32)stack - stackSize + sizeof(u32)), stackSize - sizeof(u32) * 2 - sizeof(u32) );
|
||
|
||
//---- clear mutex
|
||
thread->mutex = NULL;
|
||
#ifndef SDK_THREAD_INFINITY
|
||
thread->mutexQueueHead = NULL;
|
||
thread->mutexQueueTail = NULL;
|
||
#else
|
||
thread->mutexQueue.head = NULL;
|
||
thread->mutexQueue.tail = NULL;
|
||
#endif
|
||
|
||
//---- clear destructor
|
||
#ifdef SDK_THREAD_INFINITY
|
||
osSetThreadDestructor(thread, NULL);
|
||
#endif
|
||
|
||
//---- clear queue
|
||
#ifdef SDK_THREAD_INFINITY
|
||
thread->queue = NULL;
|
||
thread->link.prev = thread->link.next = NULL;
|
||
|
||
//---- clear specific member
|
||
miCpuClear32(&thread->specific[0], sizeof(void *) * OS_THREAD_SPECIFIC_MAX);
|
||
#endif
|
||
|
||
//---- clear alarm pointer for sleep
|
||
thread->alarmForSleep = NULL;
|
||
|
||
(void)osRestoreInterrupts(enable);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osExitThread
|
||
|
||
Description: Terminates the current thread
|
||
|
||
Arguments: none
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
void osExitThread(void)
|
||
{
|
||
(void)osDisableInterrupts();
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
i_osExitThread_ArgSpecified(osGetCurrentThread(), 0);
|
||
#else
|
||
i_osExitThread_Destroy();
|
||
#endif
|
||
}
|
||
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
// <20>f<EFBFBD>X<EFBFBD>g<EFBFBD><67><EFBFBD>N<EFBFBD>^<5E>X<EFBFBD>^<5E>b<EFBFBD>N<EFBFBD><4E><EFBFBD>l<EFBFBD><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD> i_osExitThread
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>֎~<7E><><EFBFBD>ԂŌĂяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
static void i_osExitThread_ArgSpecified(OSThread *thread, void *arg)
|
||
{
|
||
if (i_osStackForDestructor)
|
||
{
|
||
osInitContext(&thread->context, (u32)i_osExitThread, (u32)i_osStackForDestructor);
|
||
thread->context.r[0] = (u32)arg;
|
||
thread->context.cpsr |= HW_PSR_IRQ_DISABLE;
|
||
thread->state = OS_THREAD_STATE_READY;
|
||
osLoadContext(&thread->context);
|
||
// Never Returns
|
||
}
|
||
else
|
||
{
|
||
i_osExitThread(arg);
|
||
// Never Returns
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
// osKillThread <20>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>ĎQ<C48E>Ƃ<EFBFBD><C682><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><52><EFBFBD>e<EFBFBD>L<EFBFBD>X<EFBFBD>g<EFBFBD>X<EFBFBD>C<EFBFBD>b<EFBFBD>`<60><>
|
||
// <20><><EFBFBD>荞<EFBFBD>֎~<7E><><EFBFBD>ԂŌĂяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
static void i_osExitThread(void *arg)
|
||
{
|
||
OSThread *currentThread = i_osGetCurrentThread();
|
||
OSThreadDestructor destructor;
|
||
|
||
SDK_ASSERT(currentThread);
|
||
|
||
// <20>f<EFBFBD>X<EFBFBD>g<EFBFBD><67><EFBFBD>N<EFBFBD>^<5E>̏<EFBFBD><CC8F><EFBFBD>
|
||
destructor = currentThread->destructor;
|
||
if (destructor)
|
||
{
|
||
currentThread->destructor = NULL;
|
||
destructor(arg);
|
||
(void)osDisableInterrupts(); // <20>Ăъ<C482><D18A>荞<EFBFBD>֎~<7E><>
|
||
}
|
||
|
||
i_osExitThread_Destroy(); // Never return
|
||
}
|
||
#endif
|
||
|
||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
// osDestroyThread <20><><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD><68> destroy <20><><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>ɌĂяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// <20><><EFBFBD>荞<EFBFBD>֎~<7E><><EFBFBD>ԂŌĂяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
static void i_osExitThread_Destroy(void)
|
||
{
|
||
OSThread *currentThread = i_osGetCurrentThread();
|
||
SDK_ASSERT(currentThread);
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
(void)osDisableScheduler();
|
||
#endif
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
//---- current thread check
|
||
SDK_ASSERT(i_osThreadInfo.entry[currentThread->id] == currentThread);
|
||
#endif
|
||
|
||
//---- Release all the locked mutexes by current thread
|
||
i_osUnlockAllMutex(currentThread);
|
||
|
||
|
||
//---- remove from thread queue list
|
||
if (currentThread->queue)
|
||
{
|
||
(void)i_osRemoveSpecifiedLinkFromQueue(currentThread->queue, currentThread);
|
||
}
|
||
|
||
//---- remove from thread list
|
||
i_osRemoveThreadFromList(currentThread);
|
||
|
||
//---- delete this thread
|
||
#ifndef SDK_THREAD_INFINITY
|
||
i_osThreadInfo.entry[currentThread->id] = NULL;
|
||
#endif
|
||
currentThread->state = OS_THREAD_STATE_TERMINATED;
|
||
|
||
//---- wakeup thread waiting currentThread terminated
|
||
#ifndef SDK_THREAD_INFINITY
|
||
osWakeupThread(¤tThread->joinQueue); // possible to never return
|
||
#else
|
||
osWakeupThread(¤tThread->joinQueue);
|
||
#endif
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
(void)osEnableScheduler();
|
||
#endif
|
||
|
||
osRescheduleThread(); // never return
|
||
|
||
osTerminate();
|
||
}
|
||
|
||
// TEST ---------------------------------------------------------------------
|
||
#ifdef NITRO_UTEST_H__
|
||
static vu32 exitThreadStatus = 0;
|
||
|
||
static void exitThreadFunc(void *arg)
|
||
{
|
||
exitThreadStatus = 1;
|
||
(void)arg;
|
||
}
|
||
|
||
void UTEST_osExitThread(void);
|
||
void UTEST_osExitThread(void)
|
||
{
|
||
OSThread thread;
|
||
u32 stack[1024];
|
||
|
||
osInit();
|
||
osInitThread();
|
||
|
||
osCreateThread(&thread,
|
||
exitThreadFunc,
|
||
NULL,
|
||
stack + 1024, sizeof(stack), osGetThreadPriority(osGetCurrentThread()) - 1);
|
||
osWakeupThreadDirect(&thread);
|
||
osJoinThread(&thread);
|
||
UT_AssertEq(exitThreadStatus, 1);
|
||
}
|
||
#endif // ifdef NITRO_UTEST_H__
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osDestroyThread
|
||
|
||
Description: destroy specified thread.
|
||
|
||
Arguments: thread: thread to be destroyed
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osDestroyThread(OSThread *thread)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
|
||
SDK_ASSERT(thread);
|
||
|
||
//---- check current thread
|
||
if (osGetCurrentThread() == thread)
|
||
{
|
||
i_osExitThread_Destroy();
|
||
// not reached
|
||
}
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
(void)osDisableScheduler();
|
||
#endif
|
||
|
||
//---- Release all the locked mutexed by specified thread
|
||
i_osUnlockAllMutex(thread);
|
||
|
||
//---- cancel alarm for sleep
|
||
i_osCancelThreadAlarmForSleep(thread);
|
||
|
||
//---- remove from thread queue list
|
||
if (thread->queue)
|
||
{
|
||
(void)i_osRemoveSpecifiedLinkFromQueue(thread->queue, thread);
|
||
}
|
||
|
||
//---- remove from thread list
|
||
i_osRemoveThreadFromList(thread);
|
||
|
||
//---- delete thread
|
||
#ifndef SDK_THREAD_INFINITY
|
||
i_osThreadInfo.entry[thread->id] = NULL;
|
||
#endif
|
||
thread->state = OS_THREAD_STATE_TERMINATED;
|
||
|
||
//---- wakeup thread waiting this thread terminated
|
||
osWakeupThread(&thread->joinQueue);
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
(void)osEnableScheduler();
|
||
#endif
|
||
(void)osRestoreInterrupts(enabled);
|
||
|
||
osRescheduleThread();
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osKillThread
|
||
|
||
Description: switch PC to thread destructor to finalize thread
|
||
|
||
Arguments: thread : thread to wait to finish
|
||
flag : argument for destructor
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
#ifdef SDK_THREAD_INFINITY
|
||
// TESTEE
|
||
static inline void i_osKillThreadWithPriority(OSThread *thread, void *arg, u32 prio);
|
||
static inline void i_osKillThreadWithPriority(OSThread *thread, void *arg, u32 prio)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
|
||
{
|
||
u32 stack = (i_osStackForDestructor) ? (u32)i_osStackForDestructor : thread->stackBottom - sizeof(u32)*2; // minus for stack CheckNumber and padding
|
||
|
||
osInitContext(&thread->context, (u32)i_osExitThread, stack);
|
||
}
|
||
thread->context.r[0] = (u32)arg;
|
||
thread->context.cpsr |= HW_PSR_IRQ_DISABLE; // <20>f<EFBFBD>X<EFBFBD>g<EFBFBD><67><EFBFBD>N<EFBFBD>^<5E><><EFBFBD>ł<EFBFBD> IRQ <20><><EFBFBD>荞<EFBFBD>݂<EFBFBD><DD82>֎~<7E><><EFBFBD><EFBFBD>
|
||
|
||
thread->state = OS_THREAD_STATE_READY;
|
||
|
||
(void)osDisableScheduler();
|
||
(void)osSetThreadPriority(thread, prio);
|
||
(void)osEnableScheduler();
|
||
}
|
||
|
||
// BODY
|
||
void osKillThread(OSThread *thread, void *arg)
|
||
{
|
||
osKillThreadWithPriority(thread, arg, osGetThreadPriority(thread));
|
||
}
|
||
|
||
void osKillThreadWithPriority(OSThread *thread, void *arg, u32 prio)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
|
||
if (thread == osGetCurrentThread())
|
||
{
|
||
i_osExitThread_ArgSpecified(thread, arg);
|
||
// Never returns
|
||
}
|
||
|
||
//---- cancel alarm for sleep
|
||
i_osCancelThreadAlarmForSleep(thread);
|
||
|
||
i_osKillThreadWithPriority(thread, arg, prio);
|
||
|
||
i_osRescheduleThread();
|
||
(void)osRestoreInterrupts(enabled);
|
||
}
|
||
|
||
// TEST ---------------------------------------------------------------------
|
||
#ifdef NITRO_UTEST_H__
|
||
// test1
|
||
void UTEST_osKillThread_1(void);
|
||
void UTEST_osKillThread_1(void)
|
||
{
|
||
OSThread thread;
|
||
OSThread *t = &thread;
|
||
u32 flag;
|
||
|
||
osInit();
|
||
osInitThread();
|
||
|
||
t->stackBottom = 0x6789abcd;
|
||
t->state = OS_THREAD_STATE_TERMINATED;
|
||
i_osKillThreadWithPriority(t, (void *)0x12345678, 16);
|
||
|
||
// <20>R<EFBFBD><52><EFBFBD>e<EFBFBD>N<EFBFBD>X<EFBFBD>g<EFBFBD><67><EFBFBD>̎<EFBFBD><CC8E>v<EFBFBD><76><EFBFBD>W<EFBFBD>X<EFBFBD>^<5E>`<60>F<EFBFBD>b<EFBFBD>N
|
||
UT_AssertEq(t->context.pc_plus4, (u32)i_osExitThread + 4); // osExitThread
|
||
UT_AssertEq(t->context.r[0], (u32)0x12345678); // arg
|
||
flag = ((u32)osExitThread & 1) ? (u32)HW_PSR_THUMB_STATE : (u32)HW_PSR_ARM_STATE;
|
||
UT_AssertEq(t->context.cpsr, (u32)HW_PSR_IRQ_DISABLE | HW_PSR_SYS_MODE | flag);
|
||
UT_AssertEq(t->context.sp, (u32)0x6789abcd - HW_SVC_STACK_SIZE);
|
||
|
||
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD>`<60>F<EFBFBD>b<EFBFBD>N
|
||
UT_AssertEq(t->state, OS_THREAD_STATE_READY);
|
||
UT_AssertAsserted(i_osKillThreadWithPriority(0, 0, 16));
|
||
}
|
||
|
||
// test2
|
||
static vu32 killThreadStatus = 0;
|
||
|
||
static void killThreadDtor(void *arg)
|
||
{
|
||
killThreadStatus = 666;
|
||
(void)arg;
|
||
}
|
||
|
||
static void killThreadFunc(void *arg)
|
||
{
|
||
osSetThreadDestructor(osGetCurrentThread(), killThreadDtor);
|
||
|
||
killThreadStatus = 1;
|
||
while (1)
|
||
{
|
||
osSleepThread(NULL);
|
||
killThreadStatus++;
|
||
}
|
||
(void)arg;
|
||
}
|
||
|
||
void UTEST_osKillThread_2(void);
|
||
void UTEST_osKillThread_2(void)
|
||
{
|
||
OSThread thread;
|
||
u32 stack[1024];
|
||
|
||
osInit();
|
||
osInitThread();
|
||
|
||
osCreateThread(&thread,
|
||
killThreadFunc,
|
||
NULL,
|
||
stack + 1024, sizeof(stack), osGetThreadPriority(osGetCurrentThread()) - 1);
|
||
UT_AssertEq(killThreadStatus, 0);
|
||
|
||
osWakeupThreadDirect(&thread);
|
||
UT_AssertEq(killThreadStatus, 1);
|
||
UT_AssertEq(thread.destructor, killThreadDtor);
|
||
|
||
osWakeupThreadDirect(&thread);
|
||
UT_AssertEq(killThreadStatus, 2);
|
||
|
||
osKillThread(&thread, 0);
|
||
osJoinThread(&thread);
|
||
UT_AssertEq(killThreadStatus, 666);
|
||
}
|
||
#endif // ifdef NITRO_UTEST_H__
|
||
#endif // ifdef SDK_THREAD_INFINITY
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osCancelThreadAlarmForSleep
|
||
|
||
Description: Cancel alarm used to sleep thread.
|
||
If sleeping alarm is not set, do nothing.
|
||
|
||
Arguments: thread : thread to calcel alarm
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osCancelThreadAlarmForSleep(OSThread *thread)
|
||
{
|
||
OSAlarm *alarm = thread->alarmForSleep;
|
||
|
||
if (alarm)
|
||
{
|
||
osCancelAlarm(alarm);
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osJoinThread
|
||
|
||
Description: wait for specified thread to terminated
|
||
|
||
Arguments: thread : thread to wait to finish
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osJoinThread(OSThread *thread)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
|
||
SDK_ASSERT(thread);
|
||
|
||
//---- skip if thread is terminated already
|
||
while(thread->state != OS_THREAD_STATE_TERMINATED)
|
||
{
|
||
osSleepThread(&thread->joinQueue);
|
||
}
|
||
|
||
(void)osRestoreInterrupts(enabled);
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osIsThreadTerminated
|
||
|
||
Description: check thread status whether it's terminated
|
||
|
||
Arguments: thread : pointer to thread to be examined
|
||
|
||
Returns: TRUE if the thread is terminated. FALSE if not
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL osIsThreadTerminated(const OSThread *thread)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
return (thread->state == OS_THREAD_STATE_TERMINATED) ? TRUE : FALSE;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThreadStatus
|
||
|
||
Description: get thread status
|
||
|
||
Arguments: thread : pointer to thread
|
||
|
||
Returns:
|
||
*---------------------------------------------------------------------------*/
|
||
OSThreadState osGetThreadStatus(const OSThread *thread)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
return thread->state;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSleepThreadDirect
|
||
|
||
Description: Gets the thread into sleep status directly
|
||
|
||
Arguments: thread thread to sleep
|
||
queue waiting list queue (or NULL)
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
void osSleepThreadDirect(OSThread *thread, OSThreadQueue *queue)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
SDK_ASSERT(thread->state != OS_THREAD_STATE_TERMINATED);
|
||
|
||
{
|
||
OSIntrMode bak_intr = osDisableInterrupts();
|
||
|
||
if ( thread->state == OS_THREAD_STATE_READY )
|
||
{
|
||
if (queue)
|
||
{
|
||
#ifndef SDK_THREAD_INFINITY
|
||
*queue |= (OSThreadQueue)(1UL << thread->id);
|
||
#else
|
||
thread->queue = queue;
|
||
i_osInsertLinkToQueue(queue, thread);
|
||
#endif
|
||
}
|
||
thread->state = OS_THREAD_STATE_WAITING;
|
||
i_osRescheduleThread();
|
||
}
|
||
(void)osRestoreInterrupts(bak_intr);
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSleepThread
|
||
|
||
Description: Gets the current thread into sleep status
|
||
|
||
Arguments: waiting list queue
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
void osSleepThread(OSThreadQueue *queue)
|
||
{
|
||
OSIntrMode enable;
|
||
OSThread *currentThread;
|
||
|
||
enable = osDisableInterrupts();
|
||
#ifndef SDK_THREAD_INFINITY
|
||
{
|
||
currentThread = i_osGetCurrentThread();
|
||
SDK_ASSERT(currentThread);
|
||
|
||
if (queue)
|
||
{
|
||
*queue |= (OSThreadQueue)(1UL << currentThread->id);
|
||
}
|
||
|
||
currentThread->state = OS_THREAD_STATE_WAITING;
|
||
i_osRescheduleThread();
|
||
}
|
||
#else
|
||
{
|
||
currentThread = i_osGetCurrentThread();
|
||
SDK_ASSERT(currentThread);
|
||
|
||
if (queue)
|
||
{
|
||
currentThread->queue = queue;
|
||
i_osInsertLinkToQueue(queue, currentThread);
|
||
}
|
||
|
||
currentThread->state = OS_THREAD_STATE_WAITING;
|
||
i_osRescheduleThread();
|
||
}
|
||
#endif
|
||
(void)osRestoreInterrupts(enable);
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osWakeupThread
|
||
|
||
Description: Gets the threads out of sleep status
|
||
|
||
Arguments: none
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
void osWakeupThread(OSThreadQueue *queue)
|
||
{
|
||
OSIntrMode enable;
|
||
#ifndef SDK_THREAD_INFINITY
|
||
u32 mask;
|
||
#else
|
||
BOOL isNeedRescheduling = FALSE;
|
||
#endif
|
||
SDK_ASSERT(queue);
|
||
enable = osDisableInterrupts();
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
mask = (u32)*queue;
|
||
if (mask)
|
||
{
|
||
//---- wakeup threads
|
||
OSThread *t = i_osThreadInfo.list;
|
||
while (t)
|
||
{
|
||
if (mask & (1UL << t->id))
|
||
{
|
||
t->state = OS_THREAD_STATE_READY;
|
||
}
|
||
|
||
t = t->next;
|
||
}
|
||
|
||
osInitThreadQueue(queue);
|
||
i_osRescheduleThread();
|
||
}
|
||
#else
|
||
if (queue->head)
|
||
{
|
||
while (queue->head)
|
||
{
|
||
OSThread *thread = i_osRemoveLinkFromQueue(queue);
|
||
|
||
thread->state = OS_THREAD_STATE_READY;
|
||
thread->queue = NULL;
|
||
thread->link.prev = thread->link.next = NULL;
|
||
}
|
||
|
||
osInitThreadQueue(queue);
|
||
i_osRescheduleThread();
|
||
}
|
||
#endif
|
||
|
||
(void)osRestoreInterrupts(enable);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osWakeupThreadDirect
|
||
|
||
Description: Gets the threads out of sleep status directly
|
||
|
||
Arguments: none
|
||
|
||
Returns: none
|
||
*---------------------------------------------------------------------------*/
|
||
void osWakeupThreadDirect(OSThread *thread)
|
||
{
|
||
OSIntrMode enable;
|
||
|
||
SDK_ASSERT(thread);
|
||
SDK_ASSERT(thread->state != OS_THREAD_STATE_TERMINATED);
|
||
enable = osDisableInterrupts();
|
||
{
|
||
thread->state = OS_THREAD_STATE_READY;
|
||
i_osRescheduleThread();
|
||
|
||
}
|
||
(void)osRestoreInterrupts(enable);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSelectThread
|
||
|
||
Description: Select the runnable thread highest priority
|
||
|
||
Arguments: None
|
||
|
||
Returns: Pointer to thread must run
|
||
NULL if no thread candidate to run
|
||
*---------------------------------------------------------------------------*/
|
||
OSThread *osSelectThread(void)
|
||
{
|
||
OSThread *t = i_osThreadInfo.list;
|
||
|
||
while (t && !osIsThreadRunnable(t))
|
||
{
|
||
t = t->next;
|
||
}
|
||
|
||
return t;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osRescheduleThread
|
||
|
||
Description: Switch to the runnable thread highest priority
|
||
|
||
Arguments: None
|
||
|
||
Returns: None or Never return
|
||
*---------------------------------------------------------------------------*/
|
||
void osRescheduleThread(void)
|
||
{
|
||
OSIntrMode bak_intr = osDisableInterrupts();
|
||
i_osRescheduleThread();
|
||
(void)osRestoreInterrupts(bak_intr);
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osYieldThread
|
||
|
||
Description: do thread rescheduling. current thread relinquish CPU
|
||
to give chance of running to other threads which has same
|
||
priority.
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osYieldThread(void)
|
||
{
|
||
OSThread *current = osGetCurrentThread();
|
||
OSThread *pre = NULL;
|
||
OSThread *lastThread = NULL;
|
||
int samePriorityThread = 0;
|
||
OSIntrMode enable = osDisableInterrupts();
|
||
|
||
{
|
||
OSThread *t = i_osThreadInfo.list;
|
||
OSThread *tPre = NULL;
|
||
|
||
while (t)
|
||
{
|
||
if (t == current)
|
||
{
|
||
pre = tPre;
|
||
}
|
||
|
||
if (current->priority == t->priority)
|
||
{
|
||
lastThread = t;
|
||
samePriorityThread++;
|
||
}
|
||
|
||
tPre = t;
|
||
t = t->next;
|
||
}
|
||
}
|
||
|
||
//---- no thread of same priority with current or needless to arrange list
|
||
if (samePriorityThread <= 1 || lastThread == current)
|
||
{
|
||
(void)osRestoreInterrupts(enable);
|
||
return;
|
||
}
|
||
|
||
//---- remove thread from list
|
||
if (!pre)
|
||
{
|
||
i_osThreadInfo.list = current->next;
|
||
}
|
||
else
|
||
{
|
||
pre->next = current->next;
|
||
}
|
||
|
||
//---- insert thread after 'lastThread'
|
||
current->next = lastThread->next;
|
||
lastThread->next = current;
|
||
|
||
//---- re-schedule
|
||
i_osRescheduleThread();
|
||
|
||
(void)osRestoreInterrupts(enable);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osDumpThreadList
|
||
|
||
Description: Dump thread list
|
||
|
||
Arguments: None
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osDumpThreadList(void)
|
||
{
|
||
#ifndef SDK_FINALROM
|
||
#ifndef SDK_THREAD_INFINITY
|
||
int i;
|
||
#endif
|
||
|
||
osPrintf("thread list top %08x\n", i_osThreadInfo.list);
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
osPrintf("No: address prio next\n");
|
||
for (i = 0; i < OS_THREAD_MAX_NUM; i++)
|
||
{
|
||
OSThread *thread = i_osThreadInfo.entry[i];
|
||
osPrintf("%02d: %08x %5d %08x\n", i, thread, (thread) ? thread->priority : 0,
|
||
(thread) ? thread->next : 0);
|
||
}
|
||
#else
|
||
// osPrintf("Id: address prio next\n");
|
||
osPrintf("Id: address prio next st queue.h queue.t link.p link.n\n");
|
||
{
|
||
OSThread *thread = i_osThreadInfo.list;
|
||
while (thread)
|
||
{
|
||
// osPrintf("%02d: %08x %5d %08x\n", thread->id, thread, thread->priority, thread->next );
|
||
osPrintf("%02d: %08x %5d %08x %d %8x %8x %8x %8x\n", thread->id, thread,
|
||
thread->priority, thread->next, thread->state,
|
||
(thread->queue) ? thread->queue->head : (OSThread *)1,
|
||
(thread->queue) ? thread->queue->tail : (OSThread *)1, thread->link.prev,
|
||
thread->link.next);
|
||
thread = thread->next;
|
||
|
||
}
|
||
}
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetNumberOfThread
|
||
|
||
Description: get number of thread whch exists in system
|
||
|
||
Arguments: None
|
||
|
||
Returns: number of thread which exists in system
|
||
*---------------------------------------------------------------------------*/
|
||
int osGetNumberOfThread(void)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
int threads = 0;
|
||
|
||
#ifndef SDK_THREAD_INFINITY
|
||
int i;
|
||
|
||
for (i = 0; i < OS_THREAD_MAX_NUM; i++)
|
||
{
|
||
if (i_osThreadInfo.entry[i])
|
||
{
|
||
threads++;
|
||
}
|
||
}
|
||
#else
|
||
OSThread *thread = i_osThreadInfo.list;
|
||
while (thread)
|
||
{
|
||
threads++;
|
||
thread = thread->next;
|
||
}
|
||
#endif
|
||
|
||
(void)osRestoreInterrupts(enabled);
|
||
return threads;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetStackStatus
|
||
|
||
Description: check thread stack. check each CheckNUM.
|
||
return result.
|
||
|
||
Arguments: thread thread checked
|
||
|
||
Returns: 0 (OS_STACK_NO_ERROR) no error
|
||
OS_STACK_OVERFLOW overflow
|
||
OS_STACK_ABOUT_TO_OVERFLOW about to overflow
|
||
OS_STACK_UNDERFLOW underflow
|
||
*---------------------------------------------------------------------------*/
|
||
OSStackStatus osGetStackStatus(const OSThread *thread)
|
||
{
|
||
//---- Check if overflow
|
||
if (*(u32 *)(thread->stackTop) != OSi_STACK_CHECKNUM_TOP)
|
||
{
|
||
return OS_STACK_OVERFLOW;
|
||
}
|
||
//---- Check if about to overflow
|
||
else if (thread->stackWarningOffset
|
||
&& *(u32 *)(thread->stackTop + thread->stackWarningOffset) != OSi_STACK_CHECKNUM_WARN)
|
||
{
|
||
return OS_STACK_ABOUT_TO_OVERFLOW;
|
||
}
|
||
//---- Check if underFlow
|
||
else if (*(u32 *)(thread->stackBottom - sizeof(u32)*2) != OSi_STACK_CHECKNUM_BOTTOM)
|
||
{
|
||
return OS_STACK_UNDERFLOW;
|
||
}
|
||
//---- No Error, return.
|
||
else
|
||
{
|
||
return OS_STACK_NO_ERROR;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osCheckStack
|
||
|
||
Description: check thread stack. check each CheckNUM.
|
||
if changed, display warning and halt.
|
||
|
||
Arguments: file file name displayed when stack overflow
|
||
line line number displayed when stack overflow
|
||
thread thread checked
|
||
|
||
Returns: None
|
||
( if error occurred, never return )
|
||
*---------------------------------------------------------------------------*/
|
||
static char *i_osCheckStack_mesg[] = {
|
||
"overflow", "about to overflow", "underflow"
|
||
};
|
||
|
||
#ifndef SDK_FINALROM
|
||
#ifndef SDK_NO_MESSAGE
|
||
void i_osCheckStack(const char *file, int line, const OSThread *thread)
|
||
{
|
||
OSStackStatus st = osGetStackStatus(thread);
|
||
|
||
if (st == OS_STACK_NO_ERROR)
|
||
{
|
||
return;
|
||
}
|
||
|
||
i_osPanic(file, line, " stack %x(id:%d) %s.\nstack area: %08x-%08x, warning offset: %x",
|
||
thread,
|
||
thread->id,
|
||
i_osCheckStack_mesg[(int)st - 1],
|
||
thread->stackTop, thread->stackBottom, thread->stackWarningOffset);
|
||
// Never return
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osGetSystemStackPointer
|
||
|
||
Description: Get system mode stack pointer at svc/irq mode
|
||
|
||
Arguments: None
|
||
|
||
Returns: Stack Pointer
|
||
*---------------------------------------------------------------------------*/
|
||
static u32 i_osSystemStackBuffer;
|
||
|
||
#include <brom/code32.h>
|
||
asm u32 i_osGetSystemStackPointer( void )
|
||
{
|
||
INASM_EXTERN( i_osSystemStackBuffer )
|
||
|
||
ldr r0, =i_osSystemStackBuffer
|
||
stmia r0, { sp }^
|
||
ldr r0, [ r0 ]
|
||
bx lr
|
||
}
|
||
#include <brom/codereset.h>
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osGetCurrentStackPointer
|
||
|
||
Description: Get current mode stack pointer
|
||
|
||
Arguments: None
|
||
|
||
Returns: Stack Pointer
|
||
*---------------------------------------------------------------------------*/
|
||
asm u32 i_osGetCurrentStackPointer( void )
|
||
{
|
||
mov r0, sp
|
||
bx lr
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetThreadStackWarningOffset
|
||
|
||
Description: Set warning level for stack checker
|
||
|
||
Arguments: thread thread to set
|
||
offset offset from stack top. must be multiple of 4
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osSetThreadStackWarningOffset(OSThread *thread, u32 offset)
|
||
{
|
||
SDK_ASSERTMSG((offset & 3) == 0, "Offset must be aligned by 4");
|
||
SDK_ASSERTMSG(osGetThreadContext(thread)->sp > thread->stackTop + offset,
|
||
"Cannot set warning level below current sp.");
|
||
|
||
//---- remember warning offset
|
||
thread->stackWarningOffset = offset;
|
||
|
||
//---- set Stack CheckNum
|
||
if (offset != 0)
|
||
{
|
||
*(u32 *)(thread->stackTop + offset) = OSi_STACK_CHECKNUM_WARN;
|
||
}
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetThreadPriority
|
||
|
||
Description: change priority of thread
|
||
|
||
Arguments: thread thread to set priority
|
||
prio new priority to be set
|
||
|
||
Returns: TRUE if success
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL osSetThreadPriority(OSThread *thread, u32 prio)
|
||
{
|
||
OSThread *t = i_osThreadInfo.list;
|
||
OSThread *pre = NULL;
|
||
OSIntrMode enable;
|
||
|
||
SDK_ASSERTMSG(OS_THREAD_PRIORITY_MIN <= prio
|
||
&& prio <= OS_THREAD_PRIORITY_MAX, "invalid priority");
|
||
SDK_ASSERTMSG(thread != &i_osIdleThread, "cannot change idle thread priority.");
|
||
|
||
enable = osDisableInterrupts();
|
||
|
||
while (t && t != thread)
|
||
{
|
||
pre = t;
|
||
t = t->next;
|
||
}
|
||
|
||
//---- thread not found or thread is idle
|
||
if (!t || t == &i_osIdleThread)
|
||
{
|
||
(void)osRestoreInterrupts(enable);
|
||
return FALSE;
|
||
}
|
||
|
||
if (t->priority != prio)
|
||
{
|
||
//---- remove thread from list
|
||
if (!pre)
|
||
{
|
||
i_osThreadInfo.list = thread->next;
|
||
}
|
||
else
|
||
{
|
||
pre->next = thread->next;
|
||
}
|
||
|
||
//---- set priority and insert proper position
|
||
thread->priority = prio;
|
||
i_osInsertThreadToList(thread);
|
||
|
||
//---- re-schedule
|
||
i_osRescheduleThread();
|
||
}
|
||
|
||
(void)osRestoreInterrupts(enable);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThreadPriority
|
||
|
||
Description: get priority of thread
|
||
|
||
Arguments: thread thread to get priority
|
||
|
||
Returns: priority
|
||
*---------------------------------------------------------------------------*/
|
||
u32 osGetThreadPriority(const OSThread *thread)
|
||
{
|
||
SDK_ASSERTMSG(thread, "osGetThreadPriority: bad thread");
|
||
|
||
return thread->priority;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSleep
|
||
|
||
Description: sleep specified period
|
||
|
||
Arguments: msec sleeping period. ( milliseconds )
|
||
|
||
Returns: None.
|
||
*---------------------------------------------------------------------------*/
|
||
void osSleep(u32 msec)
|
||
{
|
||
OSAlarm alarm;
|
||
|
||
SDK_ASSERTMSG(osIsTickAvailable()
|
||
&& osIsAlarmAvailable(), "osSleep: need to start Tick and Alarm beforehand.");
|
||
SDK_ASSERTMSG(i_osIsThreadInitialized, "osSleep: thread system not initialized.");
|
||
|
||
osCreateAlarm(&alarm);
|
||
{
|
||
OSThread *volatile p_thread = i_osGetCurrentThread();
|
||
OSIntrMode bak_cpsr = osDisableInterrupts();
|
||
|
||
// ---- remember alarm
|
||
p_thread->alarmForSleep = &alarm;
|
||
|
||
osSetAlarm(&alarm, OS_MSEC_TO_TICK(msec), &i_osSleepAlarmCallback,
|
||
(void *)&p_thread);
|
||
while (p_thread != NULL)
|
||
{
|
||
osSleepThread(NULL);
|
||
}
|
||
(void)osRestoreInterrupts(bak_cpsr);
|
||
}
|
||
}
|
||
|
||
//---------------- callback to wakeup sleeping thread
|
||
static void i_osSleepAlarmCallback(void *arg)
|
||
{
|
||
OSThread **pp_thread = (OSThread **)arg;
|
||
OSThread *p_thread = *pp_thread;
|
||
*pp_thread = NULL;
|
||
|
||
//---- clear remembrance of alarm
|
||
p_thread->alarmForSleep = NULL;
|
||
|
||
osWakeupThreadDirect(p_thread);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetSwitchThreadCallback
|
||
|
||
Description: set callback called at switching thread
|
||
|
||
Arguments: callback callback function
|
||
|
||
Returns: previous callback function before set callback now
|
||
*---------------------------------------------------------------------------*/
|
||
OSSwitchThreadCallback osSetSwitchThreadCallback(OSSwitchThreadCallback callback)
|
||
{
|
||
OSSwitchThreadCallback prev;
|
||
OSIntrMode enabled;
|
||
|
||
enabled = osDisableInterrupts();
|
||
prev = (OSSwitchThreadCallback)i_osThreadInfo.switchCallback;
|
||
i_osThreadInfo.switchCallback = (void*)callback;
|
||
|
||
(void)osRestoreInterrupts(enabled);
|
||
return prev;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osIdleThreadProc
|
||
|
||
Description: procedure of idle thread which system creates
|
||
|
||
Arguments: None
|
||
|
||
Returns: None (never return)
|
||
*---------------------------------------------------------------------------*/
|
||
static void i_osIdleThreadProc(void *arg)
|
||
{
|
||
(void)osEnableInterrupts();
|
||
while (1)
|
||
{
|
||
osHalt();
|
||
}
|
||
// never return
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osGetIdleThread
|
||
|
||
Description: get pointer to idle thread structure
|
||
|
||
Arguments: None
|
||
|
||
Returns: pointer to idle thread structure
|
||
*---------------------------------------------------------------------------*/
|
||
OSThread *i_osGetIdleThread(void)
|
||
{
|
||
OSThread *t = NULL;
|
||
if (i_osIsThreadInitialized)
|
||
{
|
||
t = &i_osIdleThread;
|
||
}
|
||
return t;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osDisableScheduler
|
||
|
||
Description: disable scheduler
|
||
|
||
Arguments: None
|
||
|
||
Returns: Previous scheduler suspend count.
|
||
Suspended if value >= 0.
|
||
*---------------------------------------------------------------------------*/
|
||
u32 osDisableScheduler(void)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
u32 count = 0;
|
||
|
||
if (i_osRescheduleCount < (u32)(0 - 1) /* u32 max value -1 */ )
|
||
{
|
||
count = i_osRescheduleCount++;
|
||
}
|
||
(void)osRestoreInterrupts(enabled);
|
||
|
||
return count;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osEnableScheduler
|
||
|
||
Description: enable scheduler
|
||
|
||
Arguments: None
|
||
|
||
Returns: Previous scheduler suspend count.
|
||
Suspended if value >= 0.
|
||
*---------------------------------------------------------------------------*/
|
||
u32 osEnableScheduler(void)
|
||
{
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
u32 count = 0;
|
||
|
||
if (i_osRescheduleCount > 0)
|
||
{
|
||
count = i_osRescheduleCount--;
|
||
}
|
||
(void)osRestoreInterrupts(enabled);
|
||
|
||
return count;
|
||
}
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThread
|
||
|
||
Description: Gets pointer to thread which id is specified
|
||
|
||
Arguments: id : thread id to get thread
|
||
|
||
Returns: pointer to thread which id is specified
|
||
*---------------------------------------------------------------------------*/
|
||
OSThread *osGetThread(u32 id)
|
||
{
|
||
OSThread *retval = NULL;
|
||
OSThread *t = i_osThreadInfo.list;
|
||
|
||
while (t)
|
||
{
|
||
if (t->id == id)
|
||
{
|
||
retval = t;
|
||
break;
|
||
}
|
||
|
||
t = t->next;
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef SDK_THREAD_INFINITY
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetThreadDestructor
|
||
|
||
Description: set thread destructor, which is called when that thread exits.
|
||
|
||
Arguments: thread : thread pointer
|
||
dtor : destructor function
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osSetThreadDestructor(OSThread *thread, OSThreadDestructor dtor)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
thread->destructor = dtor;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThreadDestructor
|
||
|
||
Description: get thread destructor which is set
|
||
|
||
Arguments: thread : thread pointer
|
||
|
||
Returns: destructor function
|
||
*---------------------------------------------------------------------------*/
|
||
OSThreadDestructor osGetThreadDestructor(const OSThread *thread)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
return thread->destructor;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetThreadParameter
|
||
|
||
Description: set user parameter which is allowed to use freely.
|
||
|
||
Arguments: thread : thread pointer
|
||
parameter : user parameter
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osSetThreadParameter(OSThread *thread, void *parameter)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
thread->userParameter = parameter;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThreadParameter
|
||
|
||
Description: get user parameter which is set
|
||
|
||
Arguments: thread : thread pointer
|
||
|
||
Returns: user parameter which is set
|
||
*---------------------------------------------------------------------------*/
|
||
void *osGetThreadParameter(const OSThread *thread)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
return thread->userParameter;
|
||
}
|
||
|
||
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osSetSystemErrno
|
||
|
||
Description: set system error number.
|
||
|
||
Arguments: thread : thread to set error number
|
||
errno : error number to set
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void i_osSetSystemErrno(OSThread *thread, int errno)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
thread->systemErrno = errno;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: i_osGetSystemErrno
|
||
|
||
Description: get system error number.
|
||
|
||
Arguments: thread : thread to set error number
|
||
|
||
Returns: error number
|
||
*---------------------------------------------------------------------------*/
|
||
int i_osGetSystemErrno(const OSThread *thread)
|
||
{
|
||
SDK_ASSERT(thread);
|
||
return thread->systemErrno;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetErrno
|
||
|
||
Description: get system error number.
|
||
|
||
Arguments: None.
|
||
|
||
Returns: error number
|
||
*---------------------------------------------------------------------------*/
|
||
int osGetErrno(void)
|
||
{
|
||
OSThread *thread = i_osGetCurrentThread();
|
||
return i_osGetSystemErrno(thread);
|
||
}
|
||
#endif
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osIsThreadInList
|
||
|
||
Description: check if the specified thread is in the thread list
|
||
|
||
Arguments: thread : thread
|
||
|
||
Returns: TRUE if thread is in the thread list
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL osIsThreadInList(const OSThread *thread)
|
||
{
|
||
BOOL r = FALSE;
|
||
OSThread *t = i_osThreadInfo.list;
|
||
OSIntrMode enabled = osDisableInterrupts();
|
||
|
||
while (t)
|
||
{
|
||
if (t == thread)
|
||
{
|
||
r = TRUE;
|
||
break;
|
||
}
|
||
|
||
t = t->next;
|
||
}
|
||
|
||
(void)osRestoreInterrupts(enabled);
|
||
return r;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osSetThreadDestructorStack
|
||
|
||
Description: specify stack area to call thread destructor
|
||
|
||
Arguments: stack stack bottom address
|
||
stackSize stack size (byte. must be aligned by 4)
|
||
|
||
Returns: None
|
||
*---------------------------------------------------------------------------*/
|
||
void osSetThreadDestructorStack(void *stack)
|
||
{
|
||
SDK_ASSERT(stack);
|
||
SDK_ASSERT((u32)stack % STACK_ALIGN == 0);
|
||
|
||
i_osStackForDestructor = stack;
|
||
}
|
||
|
||
//================================================================================
|
||
// for DEBUG
|
||
//================================================================================
|
||
/*---------------------------------------------------------------------------*
|
||
Name: osGetThreadResource
|
||
|
||
Description: store resources of thread to specified pointer
|
||
|
||
Arguments: resource pointer to store thread resources
|
||
|
||
Returns: TRUE ... success (always return this now)
|
||
FALSE ... fail
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL osGetThreadResource(OSThreadResource *resource)
|
||
{
|
||
resource->num = osGetNumberOfThread();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
#if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
|
||
#include <brom/itcm_end.h>
|
||
#endif
|