argenvBuf = malloc(argenvBytes);
if(argenvBuf == NULL) {
Log_Error("BIN", "Proc_Execve - What the hell? The kernel is out of heap space");
+ LEAVE('i', 0);
return 0;
}
strBuf = argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
if(bases[0] == 0)
{
Log_Warning("BIN", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1));
+ LEAVE('-');
Threads_Exit(0, 0);
for(;;);
}
/**
* \fn Uint Binary_Load(char *file, Uint *entryPoint)
+ * \brief Load a binary into the current address space
+ * \param file Path to binary to load
+ * \param entryPoint Pointer for exectuable entry point
*/
Uint Binary_Load(char *file, Uint *entryPoint)
{
tBinary *pBinary;
Uint base = -1;
- ENTER("sfile", file);
+ ENTER("sfile pentryPoint", file, entryPoint);
// Sanity Check Argument
if(file == NULL) {
// Get True File Path
sTruePath = VFS_GetTruePath(file);
+ LOG("sTruePath = %p", sTruePath);
if(sTruePath == NULL) {
Log_Warning("BIN", "'%s' does not exist.", file);
}
LOG("sTruePath = '%s'", sTruePath);
+
+ // TODO: Also get modifcation time
// Check if the binary has already been loaded
if( !(pBinary = Binary_GetInfo(sTruePath)) )
int Threads_WaitTID(int TID, int *status);
tThread *Threads_GetThread(Uint TID);
void Threads_AddToDelete(tThread *Thread);
-tThread *Threads_int_GetPrev(tThread **List, tThread *Thread);
+tThread *Threads_int_DelFromQueue(tThread **List, tThread *Thread);
void Threads_Exit(int TID, int Status);
void Threads_Kill(tThread *Thread, int Status);
void Threads_Yield(void);
tGID Threads_GetGID(void);
int Threads_SetGID(Uint *Errno, tUID ID);
void Threads_Dump(void);
+void Threads_DumpActive(void);
void Mutex_Acquire(tMutex *Mutex);
void Mutex_Release(tMutex *Mutex);
int Mutex_IsLocked(tMutex *Mutex);
}
/**
- * \brief Gets the previous entry in a thead linked list
+ * \brief Deletes an entry from a list
* \param List Pointer to the list head
* \param Thread Thread to find
- * \return Thread before \a Thread on \a List
- * \note This uses a massive hack of assuming that the first field in the
- * structure is the .Next pointer. By doing this, we can return \a List
- * as a (tThread*) and simplify other code.
+ * \return \a Thread
*/
-tThread *Threads_int_GetPrev(tThread **List, tThread *Thread)
+tThread *Threads_int_DelFromQueue(tThread **List, tThread *Thread)
{
- tThread *ret;
- // First Entry
- if(*List == Thread) {
- return (tThread*)List;
+ tThread *ret, *prev = NULL;
+
+ for(ret = *List;
+ ret && ret != Thread;
+ prev = ret, ret = ret->Next
+ );
+
+ // Is the thread on the list
+ if(!ret) {
+ //LogF("%p(%s) is not on list %p\n", Thread, Thread->ThreadName, List);
+ return NULL;
+ }
+
+ if( !prev ) {
+ *List = Thread->Next;
+ //LogF("%p(%s) removed from head of %p\n", Thread, Thread->ThreadName, List);
}
- // Or not
else {
- for(ret = *List;
- ret->Next && ret->Next != Thread;
- ret = ret->Next
- );
- // Error if the thread is not on the list
- if(!ret->Next || ret->Next != Thread) {
- return NULL;
- }
+ prev->Next = Thread->Next;
+ //LogF("%p(%s) removed from %p (prev=%p)\n", Thread, Thread->ThreadName, List, prev);
}
- return ret;
+
+ return Thread;
}
/**
*/
void Threads_Kill(tThread *Thread, int Status)
{
- tThread *prev;
tMsg *msg;
// TODO: Kill all children
// Lock thread list
SHORTLOCK( &glThreadListLock );
- // Get previous thread on list
- prev = Threads_int_GetPrev( &gActiveThreads, Thread );
- if(!prev) {
+ // Delete from active list
+ if( !Threads_int_DelFromQueue( &gActiveThreads, Thread ) )
+ {
Warning("Proc_Exit - Current thread is not on the active queue");
SHORTREL( &glThreadListLock );
SHORTREL( &Thread->IsLocked );
// Ensure that we are not rescheduled
Thread->Remaining = 0; // Clear Remaining Quantum
Thread->Quantum = 0; // Clear Quantum to indicate dead thread
- prev->Next = Thread->Next; // Remove from active
// Update bookkeeping
giNumActiveThreads --;
*/
int Threads_Wake(tThread *Thread)
{
- tThread *prev;
-
if(!Thread)
return -EINVAL;
case THREAD_STAT_SLEEPING:
SHORTLOCK( &glThreadListLock );
// Remove from sleeping queue
- prev = Threads_int_GetPrev(&gSleepingThreads, Thread);
- prev->Next = Thread->Next;
+ Threads_int_DelFromQueue(&gSleepingThreads, Thread);
Threads_AddActive( Thread );
}
#endif
- // Add to active list
- Thread->Next = gActiveThreads;
- gActiveThreads = Thread;
// Set state
Thread->Status = THREAD_STAT_ACTIVE;
Thread->CurCPU = -1;
+ // Add to active list
+ Thread->Next = gActiveThreads;
+ gActiveThreads = Thread;
// Update bookkeeping
giNumActiveThreads ++;
tThread *Threads_RemActive(void)
{
tThread *ret = Proc_GetCurThread();
- tThread *prev;
SHORTLOCK( &glThreadListLock );
- prev = Threads_int_GetPrev(&gActiveThreads, ret);
- if(!prev) {
+ // Delete from active queue
+ if( !Threads_int_DelFromQueue(&gActiveThreads, ret) ) {
SHORTREL( &glThreadListLock );
return NULL;
}
ret->Remaining = 0;
ret->CurCPU = -1;
- prev->Next = ret->Next;
giNumActiveThreads --;
// no need to decrement tickets, scheduler did it for us
if( CPU_HAS_LOCK( &glThreadListLock ) )
return Last;
- // Same if the current CPU has any lock
+ // Don't change threads if the current CPU has switches disabled
if( gaThreads_NoTaskSwitch[CPU] )
return Last;
}
#if DEBUG_TRACE_TICKETS
else
- LogF(" CPU %i released %p (%s)->Status = %i (Released)\n",
- CPU, Last, Last->ThreadName, Last->Status);
+ LogF(" CPU %i released %p (%i %s)->Status = %i (Released)\n",
+ CPU, Last, Last->TID, Last->ThreadName, Last->Status);
#endif
Last->CurCPU = -1;
}
if( Mutex->Owner ) {
SHORTLOCK( &glThreadListLock );
// - Remove from active list
- Threads_RemActive();
+ us = Threads_RemActive();
// - Mark as sleeping
us->Status = THREAD_STAT_OFFSLEEP;
if( Mutex->Waiting ) {
Mutex->Owner = Mutex->Waiting; // Set owner
Mutex->Waiting = Mutex->Waiting->Next; // Next!
+ // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
+ if( Mutex->LastWaiting == Mutex->Owner )
+ Mutex->LastWaiting = NULL;
// Wake new owner
SHORTLOCK( &glThreadListLock );
// === EXPORTS ===
EXPORT(Threads_GetUID);
+EXPORT(Threads_GetGID);
EXPORT(Mutex_Acquire);
EXPORT(Mutex_Release);
EXPORT(Mutex_IsLocked);