+ // If this isn't the current thread, we need to lock
+ if( Thread != Proc_GetCurThread() ) {
+ SHORTLOCK( &glThreadListLock );
+ giFreeTickets -= Thread->NumTickets - Num;
+ Thread->NumTickets = Num;
+ #if DEBUG_TRACE_TICKETS
+ Log("Threads_SetTickets: new giFreeTickets = %i", giFreeTickets);
+ #endif
+ SHORTREL( &glThreadListLock );
+ }
+ else
+ Thread->NumTickets = Num;
+}
+
+/**
+ * \fn tThread *Threads_CloneTCB(Uint *Err, Uint Flags)
+ * \brief Clone the TCB of the current thread
+ * \param Err Error pointer
+ * \param Flags Flags for something... (What is this for?)
+ */
+tThread *Threads_CloneTCB(Uint *Err, Uint Flags)
+{
+ tThread *cur, *new;
+ int i;
+ cur = Proc_GetCurThread();
+
+ // Allocate and duplicate
+ new = malloc(sizeof(tThread));
+ if(new == NULL) {
+ *Err = -ENOMEM;
+ return NULL;
+ }
+ memcpy(new, cur, sizeof(tThread));
+
+ new->CurCPU = -1;
+ new->Next = NULL;
+ memset( &new->IsLocked, 0, sizeof(new->IsLocked));
+ new->Status = THREAD_STAT_PREINIT;
+ new->RetStatus = 0;
+
+ // Get Thread ID
+ new->TID = giNextTID++;
+ new->Parent = cur;
+
+ // Clone Name
+ new->ThreadName = strdup(cur->ThreadName);
+
+ // Set Thread Group ID (PID)
+ if(Flags & CLONE_VM)
+ new->TGID = new->TID;
+ else
+ new->TGID = cur->TGID;
+
+ // Messages are not inherited
+ new->Messages = NULL;
+ new->LastMessage = NULL;
+
+ // Set State
+ new->Remaining = new->Quantum = cur->Quantum;
+ new->NumTickets = cur->NumTickets;
+
+ // Set Signal Handlers
+ new->CurFaultNum = 0;
+ new->FaultHandler = cur->FaultHandler;
+
+ for( i = 0; i < NUM_CFG_ENTRIES; i ++ )
+ {
+ switch(cCONFIG_TYPES[i])
+ {
+ default:
+ new->Config[i] = cur->Config[i];
+ break;
+ case CFGT_HEAPSTR:
+ if(cur->Config[i])
+ new->Config[i] = (Uint) strdup( (void*)cur->Config[i] );
+ else
+ new->Config[i] = 0;
+ break;
+ }
+ }
+
+ // Maintain a global list of threads
+ SHORTLOCK( &glThreadListLock );
+ new->GlobalPrev = NULL; // Protect against bugs
+ new->GlobalNext = gAllThreads;
+ gAllThreads = new;
+ SHORTREL( &glThreadListLock );
+
+ return new;
+}
+
+/**
+ * \brief Get a configuration pointer from the Per-Thread data area
+ * \param ID Config slot ID
+ * \return Pointer at ID
+ */
+Uint *Threads_GetCfgPtr(int ID)
+{
+ if(ID < 0 || ID >= NUM_CFG_ENTRIES) {
+ Warning("Threads_GetCfgPtr: Index %i is out of bounds", ID);
+ return NULL;
+ }
+
+ return &Proc_GetCurThread()->Config[ID];