/*---------------------------------------------------------------------------* Project: OS Thread API File: OSThread.h Copyright 1998-2011 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. *---------------------------------------------------------------------------*/ #ifndef __OSTHREAD_H__ #define __OSTHREAD_H__ // Thread cancel state #define OS_THREAD_CANCEL_ENABLED 0x00000000 #define OS_THREAD_CANCEL_DISABLED_USER 0x00000001 #define OS_THREAD_CANCEL_DISABLED_MUTEX 0x00010000 #define OS_THREAD_CANCEL_DISABLED_SPINLOCK 0x00020000 #define OS_THREAD_CANCEL_DISABLED_STACK 0x00040000 #define OS_THREAD_CANCEL_DISABLED_FASTMUTEX 0x00080000 #ifndef _ASSEMBLER #include #include #ifdef __cplusplus extern "C" { #endif #define OS_THREAD_SPECIFIC_MAX 16 FORWARD_DECLARE_STRUCT_TYPE(OSThread) typedef struct OSThreadSmallQueue OSThreadSmallQueue; typedef struct OSThreadQueue OSThreadQueue; typedef struct OSThreadLink OSThreadLink; typedef s32 OSPriority; // 0 highest, 31 lowest typedef struct OSMutex OSMutex; typedef struct OSMutexQueue OSMutexQueue; typedef struct OSMutexLink OSMutexLink; typedef struct OSCond OSCond; typedef struct OSAlarm OSAlarm; typedef struct OSTLSBlock OSTLSBlock; typedef struct OSFastMutex OSFastMutex; typedef struct OSFastMutexQueue OSFastMutexQueue; typedef struct OSFastMutexLink OSFastMutexLink; typedef struct OSFastCond OSFastCond; struct OSThreadQueue { OSThread* head; OSThread* tail; void * parent_struct; // For debugging, if OSThreadQueue is embedded inside larger structure u32 os_reserved1; }; // SmallQueue is missing the parent_struct and os_reserved fields in order to save space struct OSThreadSmallQueue { OSThread* head; OSThread* tail; }; struct OSThreadLink { OSThread* next; OSThread* prev; }; struct OSMutexQueue { OSMutex* head; OSMutex* tail; void * parent_struct; // For debugging, if OSMutexQueue is embedded inside larger structure u32 os_reserved1; }; struct OSMutexLink { OSMutex* next; OSMutex* prev; }; struct OSTLSBlock { char* address; // start address of a thread specific copy of an RPL's TLS data int status; // debug agent's status of whether this address has been passed to MULTI }; struct OSFastMutexQueue { OSFastMutex * head; OSFastMutex * tail; }; struct OSFastMutexLink { OSFastMutex * next; OSFastMutex * prev; }; #ifndef OSTHREADPROC_DECLARED #define OSTHREADPROC_DECLARED typedef int (*OSThread_Proc)(int intArg, void *ptrArg); #endif #if (defined __ghs__ || defined __MAKECORE__) #include typedef struct _crt_overhead { char tmpnam_space[32]; char asctime_buff[30]; char *strtok_saved_pos; struct tm gmtime_temp; void *__eh_globals; void *__eh_mem_manage[9]; void *__eh_store_globals[6]; void *__eh_store_globals_tdeh[76]; // void *__eh_init_block[2048]; 8 kB !!! } __crt_overhead; #else typedef struct _crt_overhead { int dummy; } __crt_overhead; #endif typedef enum { OSTHREAD_TYPE_DRVR, // device driver thread OSTHREAD_TYPE_APP_IO, // I/O thread of application OSTHREAD_TYPE_APP // normal thread of application } OSThreadType; #define OS_THREAD_ID_APP_IO_START ((s16) 0x5000) #define OS_THREAD_ID_DRV_START ((s16) 0x6000) #define OS_THREAD_ID_NONE ((s16) 0x8000) typedef void (*OSThreadCleanupCallback)(void* thread, void* stackEnd); typedef void (*OSThreadDeallocator)(void* thread, void* stackEnd); #define OSTHREAD_TXT_TAG 0x74487244 #define OSTHREAD_OS_RESERVED_BYTES 32 SET_STRUCT_ALIGN(8) struct OSThread { OSContext context; // register context // *must* be immediately after OSContext. Base of OSContext // and OSThread must be identical for compatibility u32 txtTag; // 'tHrD' 0x74487244 u8 state; // OS_THREAD_STATE_* u8 attr; // OS_THREAD_ATTR_* s16 threadId; // used by debugger // 0xffff, 0x0000, 0x0001 reserved debugger // 0x0001-0x4fff - APP threads // 0x5000-0x5fff - APP_IO threads // 0x6000-0x6fff - DRVR threads // 0x7000-0x7fff - reserved debugger // 0x8000 - not numbered s32 suspend; // suspended if the count is greater than zero OSPriority priority; // effective scheduling priority OSPriority base; // base scheduling priority int val; // exit value OSThreadQueue* runQueue[MAX_SYSTEM_CORES]; OSThreadLink linkRun[MAX_SYSTEM_CORES]; // link for the run queue. OSThreadQueue* queue; // queue thread is on OSThreadLink link; // queue link OSThreadQueue queueJoin; // list of threads waiting for termination (join) OSMutex* mutex; // mutex trying to lock OSMutexQueue queueMutex; // list of mutexes owned OSThreadLink linkActive; // link of all threads for debugging u8* stackBase; // the thread's designated stack (high address) u32* stackEnd; // last word of stack (low address) OSThread_Proc entryPoint; // actual entry point (not per-thread crt startup) __crt_overhead crt; // crt per-thread data s32 alarmCancelled; void* specific[OS_THREAD_SPECIFIC_MAX]; // thread specific data OSThreadType type; const char* name; OSAlarm* waitAlarm; u32 userStackPointer; // store the user stack pointer. // this indicates user stack pointer // when the stack is switched to non-user stack. // NULL, if the stack is user stack. OSThreadCleanupCallback cleanupCallback; OSThreadDeallocator deallocator; u32 cancelState; u32 requestFlag; s32 pendingSuspend; s32 suspendResult; OSThreadQueue suspendQueue; u64 quantumTicks; // Max quantum is 0xF7F_FF08 ticks (0xF_FFFF microseconds) u64 coretimeSumQuantumStart; // Sum of all "coretime" when thread started running u64 wakeCount; // Number of times thread was awakened (averageWake == sumWake / wakeCount) OSTime sumWakeDelta; // time when thread was awoken, used to calculate delta before running OSTime awakenedTime; // awakenedTime is not set if thread has been previously awakened, OSTime minWakeDelta; // but not yet run. COS scheduler will set values before executing new OSTime maxWakeDelta; // awakened thread. Values can be inspected any time. // Thread-inherited per-core callbacks for Exception handling // Can be overridden with OSSetExceptionCallback() OSExceptionCallback dsiExCallback[MAX_SYSTEM_CORES]; OSExceptionCallback isiExCallback[MAX_SYSTEM_CORES]; OSExceptionCallback programExCallback[MAX_SYSTEM_CORES]; OSExceptionCallback perfMonExCallback[MAX_SYSTEM_CORES]; u32 stackSyncObjAllowed; short numAllocatedTLSImages; // how many elements in the tlsImageAddrs array short tlsStatus; // maintained by debug agent to determine if this thread's TLS addresses need to be resent to MULTI OSTLSBlock* tlsImageAddrs; // array of RPL TLS data areas specific to this thread OSFastMutex * waitingFastMutex; // fastMutex we are currently waiting upon OSFastMutexQueue contendedFastMutexes; // Queue of fastmutexes owned by this thread which currently have contention // (other thread(s) waiting) OSFastMutexQueue ownedFastMutexes; // Queue of fastmutexes owned by this thread which currently have contention // (other thread(s) waiting) u32 osReserved[OSTHREAD_OS_RESERVED_BYTES / sizeof(u32)]; // Reserved for COS expansion }; SET_STRUCT_ALIGN(1) // Thread states enum OS_THREAD_STATE { OS_THREAD_STATE_NONE = 0, OS_THREAD_STATE_READY = 1, OS_THREAD_STATE_RUNNING = 2, OS_THREAD_STATE_WAITING = 4, OS_THREAD_STATE_MORIBUND = 8 }; // Thread request flag enum OS_THREAD_REQUEST_FLAG { OS_THREAD_REQUEST_NONE = 0x0, OS_THREAD_REQUEST_SUSPEND = 0x1, OS_THREAD_REQUEST_CANCEL = 0x2 }; // Thread priorities #define OS_APP_IO_PRIORITY_MIN 0 // highest #define OS_APP_IO_PRIORITY_DEFAULT 16 #define OS_APP_IO_PRIORITY_MAX 31 // lowest #define OS_APP_IO_PRIORITY_IDLE OS_APP_IO_PRIORITY_MAX #define OS_PRIORITY_MIN 0 // highest #define OS_PRIORITY_APP_DEFAULT 16 #define OS_PRIORITY_MAX 31 // lowest #define OS_PRIORITY_IDLE OS_PRIORITY_MAX // // Thread attributes // // Threads lacking an affinity bit are affinitized to the // core on which they are created // #define OS_THREAD_ATTR_AFFINITY_NONE 0x0007u // affinity to run on every core #define OS_THREAD_ATTR_AFFINITY_CORE0 0x0001u // run only on core0 #define OS_THREAD_ATTR_AFFINITY_CORE1 0x0002u // run only on core1 #define OS_THREAD_ATTR_AFFINITY_CORE2 0x0004u // run only on core2 #define OS_THREAD_ATTR_DETACH 0x0008u // detached #define OS_THREAD_ATTR_PINNED_AFFINITY 0x0010u // pinned (affinitized) to a single core #define OS_THREAD_ATTR_CHECK_STACK_USE 0x0040u // check for stack usage #define OS_THREAD_ATTR_NAME_SENT 0x0080u // debugger has seen the name #define OS_THREAD_ATTR_LAST (OS_THREAD_ATTR_DETACH | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_AFFINITY_NONE) // Stack magic value #define OS_THREAD_STACK_MAGIC 0xDEADBABE #define OS_THREAD_STACK_USAGE_MAGIC 0xFEFEFEFE // Time-slice #define OS_THREAD_QUANTUM_INFINITE 0 // Default for run-to-completion threads #define OS_THREAD_QUANTUM_MIN_MICROSECONDS 10 #define OS_THREAD_QUANTUM_MAX_MICROSECONDS 0xFFFFF // (slightly more than 1 second) void OSInitThreadQueue ( OSThreadQueue* queue ); void OSInitThreadQueueEx ( OSThreadQueue* queue, void * parent_struct ); OSThread* OSGetCurrentThread ( void ); OSThread* OSGetDefaultThread ( u32 coreIdc); BOOL OSIsThreadSuspended ( OSThread* thread ); BOOL OSIsThreadTerminated( OSThread* thread ); void OSYieldThread ( void ); BOOL OSCreateThread( OSThread* thread, OSThread_Proc entryPoint, int intArg, void* ptrArg, void* stack, u32 stackSize, OSPriority priority, u16 attr ); BOOL OSCreateThreadType( OSThread* thread, OSThread_Proc entryPoint, int intArg, void* ptrArg, void* stack, u32 stackSize, OSPriority priority, u16 attr, OSThreadType type ); void OSExitThread ( int val ); BOOL OSJoinThread ( OSThread* thread, int * val ); void OSCancelThread ( OSThread* thread ); void OSDetachThread ( OSThread* thread ); s32 OSResumeThread ( OSThread* thread ); s32 OSSuspendThread ( OSThread* thread ); BOOL OSSetThreadPriority ( OSThread* thread, OSPriority priority ); OSPriority OSGetThreadPriority ( OSThread* thread ); void OSSleepThread ( OSThreadQueue* queue ); void OSWakeupThread ( OSThreadQueue* queue ); BOOL OSSetThreadAffinity ( OSThread* thread, u16 affinity); u16 OSGetThreadAffinity ( OSThread* thread ); void OSSetThreadName ( OSThread* thread, const char* name); const char* OSGetThreadName ( OSThread const * thread ); void OSTestThreadCancel (void); BOOL OSSetThreadCancelState(BOOL cancelState); void OSContinueThread ( OSThread* thread ); BOOL OSSetThreadRunQuantum(OSThread *thread, u32 quantumMicrosec); // Run the specified function on specified thread // Only runs if thread is not already running. // Runs with thread's specified priority. BOOL OSRunThread(OSThread* thread, OSThread_Proc func, int intArg, void * ptrArg); // Get/Set the data specific to the calling thread void* OSGetThreadSpecific ( s32 index ); void OSSetThreadSpecific ( s32 index, void* ptr ); void OSClearStack ( u8 val ); u32 OSGetUserStackPointer(OSThread* thread); BOOL OSSetThreadStackUsage(OSThread *thread); void OSClearThreadStackUsage(OSThread *thread); s32 OSCheckThreadStackUsage(OSThread *thread); void OSPrintActiveThreads( void ); long OSCheckActiveThreads( void ); void OSSleepTicks ( OSTime ticks ); void __OSBoostThreadPriority ( OSThread* currentThread ); void __OSDeboostThreadPrioriy ( OSThread* currentThread ); BOOL OSIsSchedulerLocked ( void* lockid ); OSTime OSGetThreadCoreTime(const OSThread *thread, u16 affinity); #define OSGetThreadTime(thread) OSGetThreadCoreTime(thread, OS_THREAD_ATTR_AFFINITY_NONE) #define OSGetCurrentThreadTime() OSGetThreadCoreTime(OSGetCurrentThread(), OS_THREAD_ATTR_AFFINITY_NONE) #define OSSleepSeconds( sec ) OSSleepTicks( OSSecondsToTicks((OSTime)sec) ) #define OSSleepMilliseconds( msec ) OSSleepTicks( OSMillisecondsToTicks((OSTime)msec) ) #define OSSleepMicroseconds( usec ) OSSleepTicks( OSMicrosecondsToTicks((OSTime)usec) ) #define OSSleepNanoseconds( nsec ) OSSleepTicks( OSNanosecondsToTicks((OSTime)nsec) ) OSThreadCleanupCallback OSSetThreadCleanupCallback(OSThread* thread, OSThreadCleanupCallback callback); OSThreadDeallocator OSSetThreadDeallocator(OSThread* thread, OSThreadDeallocator deallocator); BOOL OSGetActiveThreadLink(OSThread *thread, OSThreadLink *threadLink); #define OSPrintCurrentThreadState() \ { \ OSContext context = *OSGetCurrentContext(); \ OSSaveContext(&context); \ OSDumpContext(&context); \ } // runtime initialization routines for GHS // set these pointers to the values of __cpp_exception_init and __cpp_exception_cleanup // this avoids a dependency between the RPX and the core libraries extern void (*__cpp_exception_init_ptr)(void **); extern void (*__cpp_exception_cleanup_ptr)(void **); #ifdef __cplusplus } #endif #endif // _ASSEMBLER #endif // __OSTHREAD_H__