+ // No active threads, just take a nap
+ if(giNumActiveThreads == 0) {
+ #if DEBUG_TRACE_TICKETS
+ Log("No active threads");
+ #endif
+ return NULL;
+ }
+
+ // Lock thread list
+ // - HLT lock (Used because only another CPU can obtain the lock,
+ // but it has a potentially long lock period)
+ // - Well, this CPU can obtain the lock, but that is aliveviated by
+ // the above.
+ TIGHTLOCK( &glThreadListLock );
+
+ // Special case: 1 thread
+ if(giNumActiveThreads == 1) {
+ if( gActiveThreads->CurCPU == -1 )
+ gActiveThreads->CurCPU = CPU;
+ RELEASE( &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 (%s) into the pool (%i tickets in pool)\n",
+ CPU, Last, Last->ThreadName, Last->NumTickets);
+ #endif
+ }
+ #if DEBUG_TRACE_TICKETS
+ else
+ LogF(" %p (%s)->Status = %i\n", Last, Last->ThreadName, Last->Status);
+ #endif
+ Last->CurCPU = -1;
+ }
+
+ #if 1
+ number = 0;
+ for(thread=gActiveThreads;thread;thread=thread->Next) {
+ if(thread->CurCPU >= 0) continue;
+ 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 ) {
+ RELEASE(&glThreadListLock);
+ return NULL;
+ }