1 /*---------------------------------------------------------------------------* 2 Project: OS Thread API 3 File: OSThread.h 4 5 Copyright 1998-2011 Nintendo. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 *---------------------------------------------------------------------------*/ 14 15 #ifndef __OSTHREAD_H__ 16 #define __OSTHREAD_H__ 17 18 // Thread cancel state 19 #define OS_THREAD_CANCEL_ENABLED 0x00000000 20 #define OS_THREAD_CANCEL_DISABLED_USER 0x00000001 21 22 #define OS_THREAD_CANCEL_DISABLED_MUTEX 0x00010000 23 #define OS_THREAD_CANCEL_DISABLED_SPINLOCK 0x00020000 24 #define OS_THREAD_CANCEL_DISABLED_STACK 0x00040000 25 #define OS_THREAD_CANCEL_DISABLED_FASTMUTEX 0x00080000 26 27 #ifndef _ASSEMBLER 28 29 #include <cafe/os/OSContext.h> 30 #include <cafe/os/OSException.h> 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #define OS_THREAD_SPECIFIC_MAX 16 37 38 FORWARD_DECLARE_STRUCT_TYPE(OSThread) 39 typedef struct OSThreadSmallQueue OSThreadSmallQueue; 40 typedef struct OSThreadQueue OSThreadQueue; 41 typedef struct OSThreadLink OSThreadLink; 42 typedef s32 OSPriority; // 0 highest, 31 lowest 43 44 typedef struct OSMutex OSMutex; 45 typedef struct OSMutexQueue OSMutexQueue; 46 typedef struct OSMutexLink OSMutexLink; 47 typedef struct OSCond OSCond; 48 typedef struct OSAlarm OSAlarm; 49 typedef struct OSTLSBlock OSTLSBlock; 50 51 typedef struct OSFastMutex OSFastMutex; 52 typedef struct OSFastMutexQueue OSFastMutexQueue; 53 typedef struct OSFastMutexLink OSFastMutexLink; 54 typedef struct OSFastCond OSFastCond; 55 56 struct OSThreadQueue 57 { 58 OSThread* head; 59 OSThread* tail; 60 void * parent_struct; // For debugging, if OSThreadQueue is embedded inside larger structure 61 u32 os_reserved1; 62 }; 63 64 // SmallQueue is missing the parent_struct and os_reserved fields in order to save space 65 struct OSThreadSmallQueue 66 { 67 OSThread* head; 68 OSThread* tail; 69 }; 70 71 72 struct OSThreadLink 73 { 74 OSThread* next; 75 OSThread* prev; 76 }; 77 78 struct OSMutexQueue 79 { 80 OSMutex* head; 81 OSMutex* tail; 82 void * parent_struct; // For debugging, if OSMutexQueue is embedded inside larger structure 83 u32 os_reserved1; 84 }; 85 86 struct OSMutexLink 87 { 88 OSMutex* next; 89 OSMutex* prev; 90 }; 91 92 struct OSTLSBlock 93 { 94 char* address; // start address of a thread specific copy of an RPL's TLS data 95 int status; // debug agent's status of whether this address has been passed to MULTI 96 }; 97 98 struct OSFastMutexQueue 99 { 100 OSFastMutex * head; 101 OSFastMutex * tail; 102 }; 103 104 struct OSFastMutexLink 105 { 106 OSFastMutex * next; 107 OSFastMutex * prev; 108 }; 109 110 111 #ifndef OSTHREADPROC_DECLARED 112 #define OSTHREADPROC_DECLARED 113 typedef int (*OSThread_Proc)(int intArg, void *ptrArg); 114 #endif 115 116 #if (defined __ghs__ || defined __MAKECORE__) 117 118 #include <time.h> 119 120 typedef struct _crt_overhead 121 { 122 char tmpnam_space[32]; 123 char asctime_buff[30]; 124 char *strtok_saved_pos; 125 struct tm gmtime_temp; 126 void *__eh_globals; 127 void *__eh_mem_manage[9]; 128 void *__eh_store_globals[6]; 129 void *__eh_store_globals_tdeh[76]; 130 // void *__eh_init_block[2048]; 8 kB !!! 131 } __crt_overhead; 132 133 #else 134 135 typedef struct _crt_overhead 136 { 137 int dummy; 138 } __crt_overhead; 139 140 #endif 141 142 typedef enum 143 { 144 OSTHREAD_TYPE_DRVR, // device driver thread 145 OSTHREAD_TYPE_APP_IO, // I/O thread of application 146 OSTHREAD_TYPE_APP // normal thread of application 147 } OSThreadType; 148 149 #define OS_THREAD_ID_APP_IO_START ((s16) 0x5000) 150 #define OS_THREAD_ID_DRV_START ((s16) 0x6000) 151 #define OS_THREAD_ID_NONE ((s16) 0x8000) 152 153 typedef void (*OSThreadCleanupCallback)(void* thread, void* stackEnd); 154 typedef void (*OSThreadDeallocator)(void* thread, void* stackEnd); 155 156 #define OSTHREAD_TXT_TAG 0x74487244 157 #define OSTHREAD_OS_RESERVED_BYTES 32 158 159 SET_STRUCT_ALIGN(8) 160 struct OSThread 161 { 162 OSContext context; // register context 163 164 // *must* be immediately after OSContext. Base of OSContext 165 // and OSThread must be identical for compatibility 166 u32 txtTag; // 'tHrD' 0x74487244 167 168 u8 state; // OS_THREAD_STATE_* 169 u8 attr; // OS_THREAD_ATTR_* 170 s16 threadId; // used by debugger 171 // 0xffff, 0x0000, 0x0001 reserved debugger 172 // 0x0001-0x4fff - APP threads 173 // 0x5000-0x5fff - APP_IO threads 174 // 0x6000-0x6fff - DRVR threads 175 // 0x7000-0x7fff - reserved debugger 176 // 0x8000 - not numbered 177 s32 suspend; // suspended if the count is greater than zero 178 OSPriority priority; // effective scheduling priority 179 OSPriority base; // base scheduling priority 180 int val; // exit value 181 182 OSThreadQueue* runQueue[MAX_SYSTEM_CORES]; 183 OSThreadLink linkRun[MAX_SYSTEM_CORES]; // link for the run queue. 184 185 OSThreadQueue* queue; // queue thread is on 186 OSThreadLink link; // queue link 187 188 OSThreadQueue queueJoin; // list of threads waiting for termination (join) 189 190 OSMutex* mutex; // mutex trying to lock 191 OSMutexQueue queueMutex; // list of mutexes owned 192 193 OSThreadLink linkActive; // link of all threads for debugging 194 195 u8* stackBase; // the thread's designated stack (high address) 196 u32* stackEnd; // last word of stack (low address) 197 198 OSThread_Proc entryPoint; // actual entry point (not per-thread crt startup) 199 __crt_overhead crt; // crt per-thread data 200 201 s32 alarmCancelled; 202 void* specific[OS_THREAD_SPECIFIC_MAX]; // thread specific data 203 OSThreadType type; 204 const char* name; 205 OSAlarm* waitAlarm; 206 207 u32 userStackPointer; // store the user stack pointer. 208 // this indicates user stack pointer 209 // when the stack is switched to non-user stack. 210 // NULL, if the stack is user stack. 211 212 OSThreadCleanupCallback cleanupCallback; 213 OSThreadDeallocator deallocator; 214 215 u32 cancelState; 216 u32 requestFlag; 217 s32 pendingSuspend; 218 s32 suspendResult; 219 OSThreadQueue suspendQueue; 220 221 u64 quantumTicks; // Max quantum is 0xF7F_FF08 ticks (0xF_FFFF microseconds) 222 u64 coretimeSumQuantumStart; // Sum of all "coretime" when thread started running 223 224 u64 wakeCount; // Number of times thread was awakened (averageWake == sumWake / wakeCount) 225 OSTime sumWakeDelta; // time when thread was awoken, used to calculate delta before running 226 OSTime awakenedTime; // awakenedTime is not set if thread has been previously awakened, 227 OSTime minWakeDelta; // but not yet run. COS scheduler will set values before executing new 228 OSTime maxWakeDelta; // awakened thread. Values can be inspected any time. 229 230 // Thread-inherited per-core callbacks for Exception handling 231 // Can be overridden with OSSetExceptionCallback() 232 OSExceptionCallback dsiExCallback[MAX_SYSTEM_CORES]; 233 OSExceptionCallback isiExCallback[MAX_SYSTEM_CORES]; 234 OSExceptionCallback programExCallback[MAX_SYSTEM_CORES]; 235 OSExceptionCallback perfMonExCallback[MAX_SYSTEM_CORES]; 236 237 u32 stackSyncObjAllowed; 238 short numAllocatedTLSImages; // how many elements in the tlsImageAddrs array 239 short tlsStatus; // maintained by debug agent to determine if this thread's TLS addresses need to be resent to MULTI 240 OSTLSBlock* tlsImageAddrs; // array of RPL TLS data areas specific to this thread 241 242 OSFastMutex * waitingFastMutex; // fastMutex we are currently waiting upon 243 OSFastMutexQueue contendedFastMutexes; // Queue of fastmutexes owned by this thread which currently have contention 244 // (other thread(s) waiting) 245 OSFastMutexQueue ownedFastMutexes; // Queue of fastmutexes owned by this thread which currently have contention 246 // (other thread(s) waiting) 247 248 u32 osReserved[OSTHREAD_OS_RESERVED_BYTES / sizeof(u32)]; // Reserved for COS expansion 249 }; 250 SET_STRUCT_ALIGN(1) 251 252 // Thread states 253 enum OS_THREAD_STATE 254 { 255 OS_THREAD_STATE_NONE = 0, 256 OS_THREAD_STATE_READY = 1, 257 OS_THREAD_STATE_RUNNING = 2, 258 OS_THREAD_STATE_WAITING = 4, 259 OS_THREAD_STATE_MORIBUND = 8 260 }; 261 262 // Thread request flag 263 enum OS_THREAD_REQUEST_FLAG 264 { 265 OS_THREAD_REQUEST_NONE = 0x0, 266 OS_THREAD_REQUEST_SUSPEND = 0x1, 267 OS_THREAD_REQUEST_CANCEL = 0x2 268 }; 269 270 // Thread priorities 271 #define OS_APP_IO_PRIORITY_MIN 0 // highest 272 #define OS_APP_IO_PRIORITY_DEFAULT 16 273 #define OS_APP_IO_PRIORITY_MAX 31 // lowest 274 #define OS_APP_IO_PRIORITY_IDLE OS_APP_IO_PRIORITY_MAX 275 276 #define OS_PRIORITY_MIN 0 // highest 277 #define OS_PRIORITY_APP_DEFAULT 16 278 #define OS_PRIORITY_MAX 31 // lowest 279 #define OS_PRIORITY_IDLE OS_PRIORITY_MAX 280 281 // 282 // Thread attributes 283 // 284 // Threads lacking an affinity bit are affinitized to the 285 // core on which they are created 286 // 287 288 #define OS_THREAD_ATTR_AFFINITY_NONE 0x0007u // affinity to run on every core 289 #define OS_THREAD_ATTR_AFFINITY_CORE0 0x0001u // run only on core0 290 #define OS_THREAD_ATTR_AFFINITY_CORE1 0x0002u // run only on core1 291 #define OS_THREAD_ATTR_AFFINITY_CORE2 0x0004u // run only on core2 292 #define OS_THREAD_ATTR_DETACH 0x0008u // detached 293 #define OS_THREAD_ATTR_PINNED_AFFINITY 0x0010u // pinned (affinitized) to a single core 294 #define OS_THREAD_ATTR_CHECK_STACK_USE 0x0040u // check for stack usage 295 #define OS_THREAD_ATTR_NAME_SENT 0x0080u // debugger has seen the name 296 #define OS_THREAD_ATTR_LAST (OS_THREAD_ATTR_DETACH | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_AFFINITY_NONE) 297 298 // Stack magic value 299 #define OS_THREAD_STACK_MAGIC 0xDEADBABE 300 #define OS_THREAD_STACK_USAGE_MAGIC 0xFEFEFEFE 301 302 // Time-slice 303 #define OS_THREAD_QUANTUM_INFINITE 0 // Default for run-to-completion threads 304 #define OS_THREAD_QUANTUM_MIN_MICROSECONDS 10 305 #define OS_THREAD_QUANTUM_MAX_MICROSECONDS 0xFFFFF // (slightly more than 1 second) 306 307 void OSInitThreadQueue ( OSThreadQueue* queue ); 308 void OSInitThreadQueueEx ( OSThreadQueue* queue, void * parent_struct ); 309 OSThread* OSGetCurrentThread ( void ); 310 OSThread* OSGetDefaultThread ( u32 coreIdc); 311 BOOL OSIsThreadSuspended ( OSThread* thread ); 312 BOOL OSIsThreadTerminated( OSThread* thread ); 313 void OSYieldThread ( void ); 314 BOOL OSCreateThread( OSThread* thread, 315 OSThread_Proc entryPoint, 316 int intArg, 317 void* ptrArg, 318 void* stack, 319 u32 stackSize, 320 OSPriority priority, 321 u16 attr ); 322 BOOL OSCreateThreadType( OSThread* thread, 323 OSThread_Proc entryPoint, 324 int intArg, 325 void* ptrArg, 326 void* stack, 327 u32 stackSize, 328 OSPriority priority, 329 u16 attr, 330 OSThreadType type ); 331 void OSExitThread ( int val ); 332 BOOL OSJoinThread ( OSThread* thread, int * val ); 333 void OSCancelThread ( OSThread* thread ); 334 void OSDetachThread ( OSThread* thread ); 335 s32 OSResumeThread ( OSThread* thread ); 336 s32 OSSuspendThread ( OSThread* thread ); 337 BOOL OSSetThreadPriority ( OSThread* thread, OSPriority priority ); 338 OSPriority OSGetThreadPriority ( OSThread* thread ); 339 void OSSleepThread ( OSThreadQueue* queue ); 340 void OSWakeupThread ( OSThreadQueue* queue ); 341 BOOL OSSetThreadAffinity ( OSThread* thread, u16 affinity); 342 u16 OSGetThreadAffinity ( OSThread* thread ); 343 void OSSetThreadName ( OSThread* thread, const char* name); 344 const char* OSGetThreadName ( OSThread const * thread ); 345 void OSTestThreadCancel (void); 346 BOOL OSSetThreadCancelState(BOOL cancelState); 347 void OSContinueThread ( OSThread* thread ); 348 BOOL OSSetThreadRunQuantum(OSThread *thread, u32 quantumMicrosec); 349 350 // Run the specified function on specified thread 351 // Only runs if thread is not already running. 352 // Runs with thread's specified priority. 353 354 BOOL OSRunThread(OSThread* thread, 355 OSThread_Proc func, 356 int intArg, 357 void * ptrArg); 358 359 // Get/Set the data specific to the calling thread 360 void* OSGetThreadSpecific ( s32 index ); 361 void OSSetThreadSpecific ( s32 index, void* ptr ); 362 363 void OSClearStack ( u8 val ); 364 u32 OSGetUserStackPointer(OSThread* thread); 365 366 BOOL OSSetThreadStackUsage(OSThread *thread); 367 void OSClearThreadStackUsage(OSThread *thread); 368 s32 OSCheckThreadStackUsage(OSThread *thread); 369 370 void OSPrintActiveThreads( void ); 371 long OSCheckActiveThreads( void ); 372 373 void OSSleepTicks ( OSTime ticks ); 374 375 void __OSBoostThreadPriority ( OSThread* currentThread ); 376 void __OSDeboostThreadPrioriy ( OSThread* currentThread ); 377 378 BOOL OSIsSchedulerLocked ( void* lockid ); 379 380 OSTime OSGetThreadCoreTime(const OSThread *thread, u16 affinity); 381 #define OSGetThreadTime(thread) OSGetThreadCoreTime(thread, OS_THREAD_ATTR_AFFINITY_NONE) 382 #define OSGetCurrentThreadTime() OSGetThreadCoreTime(OSGetCurrentThread(), OS_THREAD_ATTR_AFFINITY_NONE) 383 384 #define OSSleepSeconds( sec ) OSSleepTicks( OSSecondsToTicks((OSTime)sec) ) 385 #define OSSleepMilliseconds( msec ) OSSleepTicks( OSMillisecondsToTicks((OSTime)msec) ) 386 #define OSSleepMicroseconds( usec ) OSSleepTicks( OSMicrosecondsToTicks((OSTime)usec) ) 387 #define OSSleepNanoseconds( nsec ) OSSleepTicks( OSNanosecondsToTicks((OSTime)nsec) ) 388 389 OSThreadCleanupCallback OSSetThreadCleanupCallback(OSThread* thread, OSThreadCleanupCallback callback); 390 OSThreadDeallocator OSSetThreadDeallocator(OSThread* thread, OSThreadDeallocator deallocator); 391 392 BOOL OSGetActiveThreadLink(OSThread *thread, OSThreadLink *threadLink); 393 394 #define OSPrintCurrentThreadState() \ 395 { \ 396 OSContext context = *OSGetCurrentContext(); \ 397 OSSaveContext(&context); \ 398 OSDumpContext(&context); \ 399 } 400 401 // runtime initialization routines for GHS 402 // set these pointers to the values of __cpp_exception_init and __cpp_exception_cleanup 403 // this avoids a dependency between the RPX and the core libraries 404 extern void (*__cpp_exception_init_ptr)(void **); 405 extern void (*__cpp_exception_cleanup_ptr)(void **); 406 407 #ifdef __cplusplus 408 } 409 #endif 410 #endif // _ASSEMBLER 411 412 #endif // __OSTHREAD_H__ 413 414