// // Generated By: dol2asm // Translation Unit: OSThread // #include "global.h" #include "dolphin/os/OSThread.h" #include "dolphin/os/OS.h" OSThread* __OSCurrentThread AT_ADDRESS(OS_BASE_CACHED + 0x00E4); OSThreadQueue __OSActiveThreadQueue AT_ADDRESS(OS_BASE_CACHED + 0x00DC); volatile OSContext __OSCurrentContext AT_ADDRESS(OS_BASE_CACHED + 0x00D4); volatile OSContext* __OSFPUContext AT_ADDRESS(OS_BASE_CACHED + 0x00D8); #define AddTail(queue, thread, link) \ do { \ OSThread* prev; \ \ prev = (queue)->tail; \ if (prev == NULL) \ (queue)->head = (thread); \ else \ prev->link.next = (thread); \ (thread)->link.prev = prev; \ (thread)->link.next = NULL; \ (queue)->tail = (thread); \ } while (0) #define AddPrio(queue, thread, link) \ do { \ OSThread *prev, *next; \ \ for (next = (queue)->head; next && next->effective_priority <= thread->effective_priority; \ next = next->link.next) \ ; \ if (next == NULL) \ AddTail(queue, thread, link); \ else { \ (thread)->link.next = next; \ prev = next->link.prev; \ next->link.prev = (thread); \ (thread)->link.prev = prev; \ if (prev == NULL) \ (queue)->head = (thread); \ else \ prev->link.next = (thread); \ } \ } while (0) #define RemoveItem(queue, thread, link) \ do { \ OSThread *next, *prev; \ next = (thread)->link.next; \ prev = (thread)->link.prev; \ if (next == NULL) \ (queue)->tail = prev; \ else \ next->link.prev = prev; \ if (prev == NULL) \ (queue)->head = next; \ else \ prev->link.next = next; \ } while (0) #define RemoveHead(queue, thread, link) \ do { \ OSThread* __next; \ (thread) = (queue)->head; \ __next = (thread)->link.next; \ if (__next == NULL) \ (queue)->tail = NULL; \ else \ __next->link.prev = NULL; \ (queue)->head = __next; \ } while (0) // // External References: // extern OSErrorHandler __OSErrorTable[EXCEPTION_MAX]; extern u32 __OSFpscrEnableBits; void _epilog(); // // Declarations: // static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to) {} static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback; OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback func) { BOOL enable = OSDisableInterrupts(); OSSwitchThreadCallback prev = SwitchThreadCallback; OSSwitchThreadCallback temp; if (func) { temp = func; } else { temp = DefaultSwitchThreadCallback; } SwitchThreadCallback = temp; OSRestoreInterrupts(enable); if (prev == DefaultSwitchThreadCallback) { return NULL; } return prev; } static OSThreadQueue RunQueue[32]; #pragma push #pragma force_active on static OSThread IdleThread; #pragma pop #pragma push #pragma force_active on static OSThread DefaultThread; #pragma pop #pragma push #pragma force_active on static OSContext IdleContext; #pragma pop static vu32 RunQueueBits; static volatile BOOL RunQueueHint; static volatile s32 Reschedule; extern u8 _stack_end[]; extern u8 _stack_addr[]; static inline void OSInitMutexQueue(OSMutexQueue* queue) { queue->head = queue->tail = NULL; } static inline void OSSetCurrentThread(OSThread* thread) { SwitchThreadCallback(__OSCurrentThread, thread); __OSCurrentThread = thread; } void __OSThreadInit() { OSThread* thread = &DefaultThread; int prio; thread->state = OS_THREAD_STATE_RUNNING; thread->attributes = OS_THREAD_ATTR_DETACH; thread->effective_priority = thread->base_priority = 16; thread->suspend_count = 0; thread->exit_value = (void*)-1; thread->mutex = NULL; OSInitThreadQueue(&thread->join_queue); OSInitMutexQueue(&thread->owned_mutexes); __OSFPUContext = &thread->context; OSClearContext(&thread->context); OSSetCurrentContext(&thread->context); thread->stack_base = (void*)_stack_addr; thread->stack_end = (void*)_stack_end; *(thread->stack_end) = OS_THREAD_STACK_MAGIC; OSSetCurrentThread(thread); OSClearStack(0); RunQueueBits = 0; RunQueueHint = FALSE; for (prio = OS_PRIORITY_MIN; prio <= OS_PRIORITY_MAX; ++prio) { OSInitThreadQueue(&RunQueue[prio]); } OSInitThreadQueue(&__OSActiveThreadQueue); AddTail(&__OSActiveThreadQueue, thread, active_threads_link); OSClearContext(&IdleContext); Reschedule = 0; } void OSInitThreadQueue(OSThreadQueue* queue) { queue->tail = NULL; queue->head = NULL; } OSThread* OSGetCurrentThread(void) { return OS_CURRENT_THREAD; } BOOL OSIsThreadTerminated(OSThread* thread) { return thread->state == OS_THREAD_STATE_DEAD || thread->state == OS_THREAD_STATE_UNINITIALIZED ? TRUE : FALSE; } static BOOL __OSIsThreadActive(OSThread* thread) { OSThread* active; if (thread->state == 0) { return FALSE; } for (active = __OSActiveThreadQueue.head; active; active = active->active_threads_link.next) { if (thread == active) { return TRUE; } } return FALSE; } s32 OSDisableScheduler(void) { BOOL intr = OSDisableInterrupts(); s32 ret = Reschedule++; OSRestoreInterrupts(intr); return ret; } s32 OSEnableScheduler(void) { BOOL intr = OSDisableInterrupts(); s32 ret = Reschedule--; OSRestoreInterrupts(intr); return ret; } static inline void SetRun(OSThread* thread) { thread->queue = &RunQueue[thread->effective_priority]; AddTail(thread->queue, thread, link); RunQueueBits |= 1u << (OS_PRIORITY_MAX - thread->effective_priority); RunQueueHint = TRUE; } #pragma dont_inline on static void UnsetRun(OSThread* thread) { OSThreadQueue* queue; OSThread* next; OSThread* prev; prev = thread->link.next; queue = thread->queue; next = thread->link.prev; if (prev == NULL) { queue->tail = next; } else { prev->link.prev = next; } if (next == NULL) { queue->head = prev; } else { next->link.next = prev; } if (queue->head == NULL) { RunQueueBits &= ~(1 << (31 - thread->effective_priority)); } thread->queue = NULL; } #pragma dont_inline reset s32 __OSGetEffectivePriority(OSThread* thread) { s32 prio = thread->base_priority; OSMutex* mutex; for (mutex = thread->owned_mutexes.head; mutex != NULL; mutex = mutex->link.next) { OSThread* mutexThread = mutex->queue.head; if (mutexThread != NULL && mutexThread->effective_priority < prio) { prio = mutexThread->effective_priority; } } return prio; } static OSThread* SetEffectivePriority(OSThread* thread, s32 priority) { switch (thread->state) { case OS_THREAD_STATE_READY: UnsetRun(thread); thread->effective_priority = priority; SetRun(thread); break; case OS_THREAD_STATE_WAITING: RemoveItem(thread->queue, thread, link); thread->effective_priority = priority; AddPrio(thread->queue, thread, link); if (thread->mutex) { return thread->mutex->thread; } break; case OS_THREAD_STATE_RUNNING: RunQueueHint = TRUE; thread->effective_priority = priority; break; } return NULL; } static void UpdatePriority(OSThread* thread) { OSPriority priority; do { if (0 < thread->suspend_count) { break; } priority = __OSGetEffectivePriority(thread); if (thread->effective_priority == priority) { break; } thread = SetEffectivePriority(thread, priority); } while (thread); } void __OSPromoteThread(OSThread* thread, s32 priority) { do { if (thread->suspend_count > 0 || thread->effective_priority <= priority) { break; } thread = SetEffectivePriority(thread, priority); } while (thread != NULL); } static inline void __OSSwitchThread(OSThread* nextThread) { OSSetCurrentThread(nextThread); OSSetCurrentContext(&nextThread->context); OSLoadContext(&nextThread->context); } static OSThread* SelectThread(BOOL yield) { OSContext* currentContext; OSThread* currentThread; OSThread* nextThread; OSPriority priority; OSThreadQueue* queue; if (0 < Reschedule) { return 0; } currentContext = OSGetCurrentContext(); currentThread = OSGetCurrentThread(); if (currentContext != ¤tThread->context) { return 0; } if (currentThread) { if (currentThread->state == OS_THREAD_STATE_RUNNING) { if (!yield) { priority = __cntlzw(RunQueueBits); if (currentThread->effective_priority <= priority) { return 0; } } currentThread->state = OS_THREAD_STATE_READY; SetRun(currentThread); } if (!(currentThread->context.state & OS_CONTEXT_STATE_EXC) && OSSaveContext(¤tThread->context)) { return 0; } } OSSetCurrentThread(NULL); if (RunQueueBits == 0) { OSSetCurrentContext(&IdleContext); do { OSEnableInterrupts(); while (RunQueueBits == 0) ; OSDisableInterrupts(); } while (RunQueueBits == 0); OSClearContext(&IdleContext); } RunQueueHint = FALSE; priority = __cntlzw(RunQueueBits); queue = &RunQueue[priority]; RemoveHead(queue, nextThread, link); if (queue->head == 0) { RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - priority)); } nextThread->queue = NULL; nextThread->state = OS_THREAD_STATE_RUNNING; __OSSwitchThread(nextThread); return nextThread; } void __OSReschedule(void) { if (!RunQueueHint) { return; } SelectThread(FALSE); } void OSYieldThread(void) { BOOL enabled; enabled = OSDisableInterrupts(); SelectThread(TRUE); OSRestoreInterrupts(enabled); } BOOL OSCreateThread(OSThread* thread_, void* func, void* param, void* stackBase, u32 stackSize, s32 priority, u16 attribute) { BOOL enabled; u32 i; u32* stack; OSThread* thread; u32 stack1, stack2; if (priority < 0 || priority > 31) { return FALSE; } thread = thread_; thread->state = OS_THREAD_STATE_READY; thread->attributes = attribute & 1; thread->base_priority = priority; thread->effective_priority = priority; thread->suspend_count = 1; thread->exit_value = (void*)-1; thread->mutex = NULL; thread->join_queue.tail = NULL; thread->join_queue.head = NULL; thread->owned_mutexes.tail = NULL; thread->owned_mutexes.head = NULL; stack = (u32*)((u32)stackBase & 0xfffffff8); stack[-2] = 0; stack[-1] = 0; OSInitContext(&thread->context, (u32)func, (u32)stack - 8); thread->context.lr = (u32)OSExitThread; thread->context.gpr[3] = (u32)param; thread->stack_base = (u8*)stackBase; thread->stack_end = (void*)((u32)stackBase - stackSize); *(u32*)thread->stack_end = OS_THREAD_STACK_MAGIC; thread->error_code = NULL; thread->data[0] = NULL; thread->data[1] = NULL; enabled = OSDisableInterrupts(); if (__OSErrorTable[16]) { thread->context.srr1 |= 0x900; thread->context.state |= 1; thread->context.fpscr = (__OSFpscrEnableBits & 0xf8) | 4; for (i = 0; i < 32; ++i) { *(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL; *(u64*)&thread->context.ps[i] = (u64)0xffffffffffffffffLL; } } AddTail(&OS_THREAD_QUEUE, thread, active_threads_link); OSRestoreInterrupts(enabled); return TRUE; } void OSExitThread(void* exitValue) { OSThread* currentThread; BOOL enabled; enabled = OSDisableInterrupts(); currentThread = OS_CURRENT_THREAD; OSClearContext(¤tThread->context); if (currentThread->attributes & OS_THREAD_ATTR_DETACH) { RemoveItem(&OS_THREAD_QUEUE, currentThread, active_threads_link); currentThread->state = OS_THREAD_STATE_UNINITIALIZED; } else { currentThread->state = OS_THREAD_STATE_DEAD; currentThread->exit_value = exitValue; } __OSUnlockAllMutex(currentThread); OSWakeupThread(¤tThread->join_queue); RunQueueHint = TRUE; if (RunQueueHint) { SelectThread(FALSE); } OSRestoreInterrupts(enabled); } void OSCancelThread(OSThread* thread) { BOOL enabled; enabled = OSDisableInterrupts(); switch (thread->state) { case OS_THREAD_STATE_READY: if (!(0 < thread->suspend_count)) { UnsetRun(thread); } break; case OS_THREAD_STATE_RUNNING: RunQueueHint = TRUE; break; case OS_THREAD_STATE_WAITING: RemoveItem(thread->queue, thread, link); thread->queue = NULL; if (!(0 < thread->suspend_count) && thread->mutex) { UpdatePriority(thread->mutex->thread); } break; default: OSRestoreInterrupts(enabled); return; } OSClearContext(&thread->context); if (thread->attributes & OS_THREAD_ATTR_DETACH) { RemoveItem(&__OSActiveThreadQueue, thread, active_threads_link); thread->state = 0; } else { thread->state = OS_THREAD_STATE_DEAD; } __OSUnlockAllMutex(thread); OSWakeupThread(&thread->join_queue); __OSReschedule(); OSRestoreInterrupts(enabled); } BOOL OSJoinThread(struct OSThread * thread, void * val) { int enabled = OSDisableInterrupts(); if (!(thread->attributes & 1) && (thread->state != 8) && (thread->join_queue.head == NULL)) { OSSleepThread(&thread->join_queue); if (__OSIsThreadActive(thread) == 0) { OSRestoreInterrupts(enabled); return 0; } } if (thread->state == 8) { if (val) { *(s32*)val = (s32)thread->exit_value; } RemoveItem(&__OSActiveThreadQueue, thread, active_threads_link); thread->state = 0; OSRestoreInterrupts(enabled); return 1; } OSRestoreInterrupts(enabled); return 0; } void OSDetachThread(OSThread* thread) { BOOL enabled; enabled = OSDisableInterrupts(); thread->attributes |= OS_THREAD_ATTR_DETACH; if (thread->state == OS_THREAD_STATE_DEAD) { RemoveItem(&__OSActiveThreadQueue, thread, active_threads_link); thread->state = OS_THREAD_STATE_UNINITIALIZED; } OSWakeupThread(&thread->join_queue); OSRestoreInterrupts(enabled); } s32 OSResumeThread(OSThread* thread) { BOOL enabled; s32 suspendCount; enabled = OSDisableInterrupts(); suspendCount = thread->suspend_count--; if (thread->suspend_count < 0) { thread->suspend_count = 0; } else if (thread->suspend_count == 0) { switch (thread->state) { case OS_THREAD_STATE_READY: thread->effective_priority = __OSGetEffectivePriority(thread); SetRun(thread); break; case OS_THREAD_STATE_WAITING: RemoveItem(thread->queue, thread, link); thread->effective_priority = __OSGetEffectivePriority(thread); AddPrio(thread->queue, thread, link); if (thread->mutex) { UpdatePriority(thread->mutex->thread); } break; } __OSReschedule(); } OSRestoreInterrupts(enabled); return suspendCount; } s32 OSSuspendThread(OSThread* thread) { BOOL enabled; s32 suspendCount; enabled = OSDisableInterrupts(); suspendCount = thread->suspend_count++; if (suspendCount == 0) { switch (thread->state) { case OS_THREAD_STATE_RUNNING: RunQueueHint = TRUE; thread->state = OS_THREAD_STATE_READY; break; case OS_THREAD_STATE_READY: UnsetRun(thread); break; case OS_THREAD_STATE_WAITING: RemoveItem(thread->queue, thread, link); thread->effective_priority = 32; AddTail(thread->queue, thread, link); if (thread->mutex) { UpdatePriority(thread->mutex->thread); } break; } __OSReschedule(); } OSRestoreInterrupts(enabled); return suspendCount; } void OSSleepThread(OSThreadQueue* queue) { BOOL enabled; OSThread* currentThread; enabled = OSDisableInterrupts(); currentThread = OSGetCurrentThread(); currentThread->state = OS_THREAD_STATE_WAITING; currentThread->queue = queue; AddPrio(queue, currentThread, link); RunQueueHint = TRUE; __OSReschedule(); OSRestoreInterrupts(enabled); } void OSWakeupThread(OSThreadQueue* queue) { BOOL enabled; OSThread* thread; enabled = OSDisableInterrupts(); while (queue->head) { RemoveHead(queue, thread, link); thread->state = OS_THREAD_STATE_READY; if (!(0 < thread->suspend_count)) { SetRun(thread); } } __OSReschedule(); OSRestoreInterrupts(enabled); } s32 OSSetThreadPriority(OSThread* thread, s32 priority) { BOOL enabled; if (priority < 0 || priority > 31) { return FALSE; } enabled = OSDisableInterrupts(); if ((s32)thread->base_priority != priority) { thread->base_priority = priority; UpdatePriority(thread); __OSReschedule(); } OSRestoreInterrupts(enabled); return TRUE; } s32 OSGetThreadPriority(OSThread* thread) { return thread->base_priority; } s32 CheckThreadQueue(OSThreadQueue* thread) { OSThread* current; if (thread->head && thread->head->link.prev) { return 0; } if (thread->tail && thread->tail->link.next) { return 0; } current = thread->head; while (current) { if (current->link.next && current != current->link.next->link.prev) { return 0; } if (current->link.prev && current != current->link.prev->link.next) { return 0; } current = current->link.next; } return 1; } static BOOL isMember(OSThreadQueue* queue, OSThread* thread) { OSThread* current = queue->head; while (current != NULL) { if (thread == current) { return TRUE; } current = current->link.next; } return FALSE; } s32 OSCheckActiveThreads(void) { s32 i; OSThread* thread; s32 rv = 0; BOOL enabled; enabled = OSDisableInterrupts(); for (i = 0; i <= 31; i++) { if (RunQueueBits & (1 << (31 - i))) { if (RunQueue[i].head == NULL || RunQueue[i].tail == NULL) { OSReport("OSCheckActiveThreads: Failed RunQueue[prio].head != NULL && " "RunQueue[prio].tail != NULL in %d\n", 0x5be); OSPanic(__FILE__, 0x5be, ""); } } else { if (RunQueue[i].head != NULL || RunQueue[i].tail != NULL) { OSReport("OSCheckActiveThreads: Failed RunQueue[prio].head == NULL && " "RunQueue[prio].tail == NULL in %d\n", 0x5c3); OSPanic(__FILE__, 0x5c3, ""); } } if (CheckThreadQueue(&RunQueue[i]) == 0) { OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(&RunQueue[prio]) in %d\n", 0x5c5); OSPanic(__FILE__, 0x5c5, ""); } } if (OS_THREAD_QUEUE.head != NULL && OS_THREAD_QUEUE.head->active_threads_link.prev != NULL) { OSReport("OSCheckActiveThreads: Failed __OSActiveThreadQueue.head == NULL || " "__OSActiveThreadQueue.head->linkActive.prev == NULL in %d\n", 0x5ca); OSPanic(__FILE__, 0x5ca, ""); } if (OS_THREAD_QUEUE.tail != NULL && OS_THREAD_QUEUE.tail->active_threads_link.next != NULL) { OSReport("OSCheckActiveThreads: Failed __OSActiveThreadQueue.tail == NULL || " "__OSActiveThreadQueue.tail->linkActive.next == NULL in %d\n", 0x5cc); OSPanic(__FILE__, 0x5cc, ""); } thread = OS_THREAD_QUEUE.head; while (thread != NULL) { rv++; if (thread->active_threads_link.next != NULL && thread != thread->active_threads_link.next->active_threads_link.prev) { OSReport("OSCheckActiveThreads: Failed thread->linkActive.next == NULL || thread == " "thread->linkActive.next->linkActive.prev in %d\n", 0x5d4); OSPanic(__FILE__, 0x5d4, ""); } if (thread->active_threads_link.prev != NULL && thread != thread->active_threads_link.prev->active_threads_link.next) { OSReport("OSCheckActiveThreads: Failed thread->linkActive.prev == NULL || thread == " "thread->linkActive.prev->linkActive.next in %d\n", 0x5d6); OSPanic(__FILE__, 0x5d6, ""); } if (*(u32*)thread->stack_end != OS_THREAD_STACK_MAGIC) { OSReport( "OSCheckActiveThreads: Failed *(thread->stackEnd) == OS_THREAD_STACK_MAGIC in %d\n", 0x5d9); OSPanic(__FILE__, 0x5d9, ""); } if (OS_PRIORITY_MIN > thread->effective_priority || thread->effective_priority > OS_PRIORITY_MAX + 1) { OSReport("OSCheckActiveThreads: Failed OS_PRIORITY_MIN <= thread->priority && " "thread->priority <= OS_PRIORITY_MAX+1 in %d\n", 0x5dc); OSPanic(__FILE__, 0x5dc, ""); } if (thread->suspend_count < 0) { OSReport("OSCheckActiveThreads: Failed 0 <= thread->suspend in %d\n", 0x5dd); OSPanic(__FILE__, 0x5dd, ""); } if (!CheckThreadQueue(&thread->join_queue)) { OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(&thread->queueJoin) in %d\n", 0x5de); OSPanic(__FILE__, 0x5de, ""); } switch (thread->state) { case OS_THREAD_STATE_READY: if (thread->suspend_count <= 0) { if (thread->queue != &RunQueue[thread->effective_priority]) { OSReport("OSCheckActiveThreads: Failed thread->queue == " "&RunQueue[thread->priority] in %d\n", 0x5e4); OSPanic(__FILE__, 0x5e4, ""); } if (!isMember(&RunQueue[thread->effective_priority], thread)) { OSReport("OSCheckActiveThreads: Failed IsMember(&RunQueue[thread->priority], " "thread) in %d\n", 0x5e5); OSPanic(__FILE__, 0x5e5, ""); } if (thread->effective_priority != __OSGetEffectivePriority(thread)) { OSReport("OSCheckActiveThreads: Failed thread->priority == " "__OSGetEffectivePriority(thread) in %d\n", 0x5e6); OSPanic(__FILE__, 0x5e6, ""); } } break; case OS_THREAD_STATE_RUNNING: if (thread->suspend_count > 0) { OSReport("OSCheckActiveThreads: Failed !IsSuspended(thread->suspend) in %d\n", 0x5ea); OSPanic(__FILE__, 0x5ea, ""); } if (thread->queue != NULL) { OSReport("OSCheckActiveThreads: Failed thread->queue == NULL in %d\n", 0x5eb); OSPanic(__FILE__, 0x5eb, ""); } if (thread->effective_priority != __OSGetEffectivePriority(thread)) { OSReport("OSCheckActiveThreads: Failed thread->priority == " "__OSGetEffectivePriority(thread) in %d\n", 0x5ec); OSPanic(__FILE__, 0x5ec, ""); } break; case OS_THREAD_STATE_WAITING: if (thread->queue == NULL) { OSReport("OSCheckActiveThreads: Failed thread->queue != NULL in %d\n", 0x5ef); OSPanic(__FILE__, 0x5ef, ""); } if (CheckThreadQueue(thread->queue) == 0) { OSReport("OSCheckActiveThreads: Failed CheckThreadQueue(thread->queue) in %d\n", 0x5f0); OSPanic(__FILE__, 0x5f0, ""); } if (!isMember(thread->queue, thread)) { OSReport("OSCheckActiveThreads: Failed IsMember(thread->queue, thread) in %d\n", 0x5f1); OSPanic(__FILE__, 0x5f1, ""); } if (thread->suspend_count <= 0) { if (thread->effective_priority != __OSGetEffectivePriority(thread)) { OSReport("OSCheckActiveThreads: Failed thread->priority == " "__OSGetEffectivePriority(thread) in %d\n", 0x5f4); OSPanic(__FILE__, 0x5f4, ""); } } else if (thread->effective_priority != 32) { OSReport("OSCheckActiveThreads: Failed thread->priority == 32 in %d\n", 0x5f8); OSPanic(__FILE__, 0x5f8, ""); } if (__OSCheckDeadLock(thread)) { OSReport("OSCheckActiveThreads: Failed !__OSCheckDeadLock(thread) in %d\n", 0x5fa); OSPanic(__FILE__, 0x5fa, ""); } break; case OS_THREAD_STATE_DEAD: if (thread->owned_mutexes.head != NULL || thread->owned_mutexes.tail != NULL) { OSReport("OSCheckActiveThreads: Failed thread->queueMutex.head == NULL && " "thread->queueMutex.tail == NULL in %d\n", 0x5fe); OSPanic(__FILE__, 0x5fe, ""); } break; default: OSReport("OSCheckActiveThreads: Failed. unkown thread state (%d) of thread %p\n", thread->state, thread); OSPanic(__FILE__, 0x604, ""); break; } if (!__OSCheckMutexes(thread)) { OSReport("OSCheckActiveThreads: Failed __OSCheckMutexes(thread) in %d\n", 0x609); OSPanic(__FILE__, 0x609, ""); } thread = thread->active_threads_link.next; } OSRestoreInterrupts(enabled); return rv; } void OSClearStack(u8 val) { u32* sp; u32* p; u32 pattern; pattern = ((u32)val << 24) | ((u32)val << 16) | ((u32)val << 8) | (u32)val; sp = (u32*)OSGetStackPointer(); for (p = ((u32*)__OSCurrentThread->stack_end) + 1; p < sp; ++p) { *p = pattern; } }