+ thread = gDeleteThreads->Next;
+ if( IS_LOCKED(&gDeleteThreads->IsLocked) ) { // Only free if structure is unused
+ // Set to dead
+ gDeleteThreads->Status = THREAD_STAT_DEAD;
+ // Free name
+ if( IsHeap(gDeleteThreads->ThreadName) )
+ free(gDeleteThreads->ThreadName);
+ // Remove from global list
+ if( gDeleteThreads == gAllThreads )
+ gAllThreads = gDeleteThreads->GlobalNext;
+ else
+ gDeleteThreads->GlobalPrev->GlobalNext = gDeleteThreads->GlobalNext;
+ free( gDeleteThreads );
+ }
+ gDeleteThreads = thread;
+ }
+
+ // No active threads, just take a nap
+ if(giNumActiveThreads == 0) {
+ SHORTREL( &glThreadListLock );
+ #if DEBUG_TRACE_TICKETS
+ Log("No active threads");
+ #endif
+ return NULL;
+ }
+
+ // Special case: 1 thread
+ if(giNumActiveThreads == 1) {
+ if( gActiveThreads->CurCPU == -1 )
+ gActiveThreads->CurCPU = CPU;
+
+ SHORTREL( &glThreadListLock );
+
+ if( gActiveThreads->CurCPU == CPU )
+ return gActiveThreads;
+
+ return NULL; // CPU has nothing to do
+ }
+
+ // Allow the old thread to be scheduled again
+ if( Last ) {
+ if( Last->Status == THREAD_STAT_ACTIVE ) {
+ giFreeTickets += Last->NumTickets;
+ #if DEBUG_TRACE_TICKETS
+ LogF(" CPU %i released %p (%i %s) into the pool (%i tickets in pool)\n",
+ CPU, Last, Last->TID, Last->ThreadName, giFreeTickets);
+ #endif
+ }
+ #if DEBUG_TRACE_TICKETS
+ else
+ LogF(" CPU %i released %p (%s)->Status = %i (Released)\n",
+ CPU, Last, Last->ThreadName, Last->Status);
+ #endif
+ Last->CurCPU = -1;
+ }
+
+ #if DEBUG_TRACE_TICKETS
+ //Threads_DumpActive();
+ #endif
+
+ #if 1
+ number = 0;
+ for(thread = gActiveThreads; thread; thread = thread->Next) {
+ if(thread->CurCPU >= 0) continue;
+ if(thread->Status != THREAD_STAT_ACTIVE)
+ Panic("Bookkeeping fail - %p %i(%s) is on the active queue with a status of %i",
+ thread, thread->TID, thread->ThreadName, thread->Status);
+ if(thread->Next == thread) {
+ Panic("Bookkeeping fail - %p %i(%s) loops back on itself",
+ thread, thread->TID, thread->ThreadName, thread->Status);
+ }
+ number += thread->NumTickets;
+ }
+ if(number != giFreeTickets) {
+ Panic("Bookkeeping fail (giFreeTickets(%i) != number(%i)) - CPU%i",
+ giFreeTickets, number, CPU);
+ }
+ #endif
+
+ // No free tickets (all tasks delegated to cores)
+ if( giFreeTickets == 0 ) {
+ SHORTREL(&glThreadListLock);
+ return NULL;