1 /*---------------------------------------------------------------------------*
2   Project:  OS Thread API
3   File:     OSThread.h
4 
5   Copyright (C) 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    20
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     OSExceptionCallback alignExCallback[MAX_SYSTEM_CORES];
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