#define _SIGNAL_H_ // Stop the acess signal.h being used
#define _HEAP_H_ // Stop heap.h being imported (collides with stdlib heap)
#define _VFS_EXT_H // Stop vfs_ext.h being imported (collides with fd_set)
-#undef CLONE_VM // Such a hack
+
+#define off_t _acess_off_t
#include <arch.h>
#undef NULL // Remove acess definition
#include <acess.h>
#include <mutex.h>
#include <semaphore.h>
+#include <rwlock.h>
+#include <events.h>
+#include <threads_int.h>
+
+#undef CLONE_VM // Such a hack
+#undef off_t
+
+// - Native headers
#include <unistd.h>
#include <sys/types.h>
#include <stdint.h>
#include "/usr/include/signal.h"
#include <SDL/SDL.h>
+#define THREAD_EVENT_WAKEUP 0x80000000
+
// === IMPORTS ===
void VFS_CloneHandleList(int PID);
} tState;
#endif
-typedef struct sProcess
-{
- int nThreads;
- int NativePID;
- char *CWD;
- char *Chroot;
- int MaxFD;
-} tProcess;
-
-typedef struct sThread
-{
- struct sThread *GlobalNext;
- struct sThread *Next;
-
- int KernelTID;
-
- tTID TID, PID;
- tUID UID, GID;
-
- struct sThread *Parent;
-
- char *ThreadName;
-
- int State; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
- int ExitStatus;
- int _errno;
-
- // Threads waiting for this thread to exit.
- // Quit logic:
- // - Wait for `WaitingThreads` to be non-null (maybe?)
- // - Wake first in the queue, wait for it to be removed
- // - Repeat
- // - Free thread and quit kernel thread
- struct sThread *WaitingThreads;
- struct sThread *WaitingThreadsEnd;
-
- tProcess *Process;
-
- Uint32 Events, WaitMask;
- SDL_sem *EventSem;
-
-} tThread;
-
// === PROTOTYPES ===
int Threads_Wake(tThread *Thread);
.MaxFD = 100
};
tThread gThreadZero = {
- .State=1,
+ .Status=THREAD_STAT_ACTIVE,
.ThreadName="ThreadZero",
.Process = &gProcessZero
};
Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
}
-tThread *Threads_GetThread(int TID)
+tThread *Threads_GetThread(Uint TID)
{
tThread *thread;
for( thread = gpThreads; thread; thread = thread->GlobalNext )
{
- if( thread->TID == TID )
+ if( thread->TID == TID ) {
return thread;
+ }
}
return NULL;
}
ret->TID = giThreads_NextThreadID ++;
ret->ThreadName = strdup(TemplateThread->ThreadName);
+ ret->EventSem = SDL_CreateSemaphore(0);
+ if( !ret->EventSem ) {
+ Log_Warning("Threads", "Semaphore creation failed - %s", SDL_GetError());
+ }
ret->WaitingThreads = NULL;
ret->WaitingThreadsEnd = NULL;
tTID Threads_GetTID() { return gpCurrentThread->TID; }
tPID Threads_GetPID() { return gpCurrentThread->PID; }
-int Threads_SetUID(int *Errno, tUID NewUID)
+int Threads_SetUID(tUID NewUID)
{
if(Threads_GetUID() != 0) {
- if(Errno) *Errno = -EACCES;
+ errno = EACCES;
return -1;
}
return 0;
}
-int Threads_SetGID(int *Errno, tGID NewGID)
+int Threads_SetGID(tGID NewGID)
{
if(Threads_GetUID() != 0) {
- if(Errno) *Errno = -EACCES;
+ errno = -EACCES;
return -1;
}
char **Threads_GetChroot(void) { return &gpCurrentThread->Process->Chroot; }
int *Threads_GetMaxFD(void) { return &gpCurrentThread->Process->MaxFD; };
-int Threads_WaitTID(int TID, int *Status)
+tTID Threads_WaitTID(int TID, int *Status)
{
// Any Child
if(TID == -1) {
if(!thread) return -1;
us->Next = NULL;
- us->State = 3;
+ us->Status = THREAD_STAT_WAITING;
// TODO: Locking
if(thread->WaitingThreadsEnd)
{
thread->WaitingThreadsEnd = us;
}
- while(thread->State != 0)
- {
- pause();
- Log_Debug("Threads", "Huh?... state = %i", thread->State);
- }
+ Threads_WaitEvents( THREAD_EVENT_WAKEUP );
if(Status) *Status = thread->ExitStatus;
thread->WaitingThreads = thread->WaitingThreads->Next;
int Threads_Wake(tThread *Thread)
{
- Thread->State = 0;
- kill( Thread->KernelTID, SIGUSR1 );
+ Thread->Status = THREAD_STAT_ACTIVE;
+ Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
return 0;
}
return thread->PID;
}
+// --------------------------------------------------------------------
+// Mutexes
+// --------------------------------------------------------------------
int Mutex_Acquire(tMutex *Mutex)
{
if(!Mutex->Protector.IsValid) {
pthread_mutex_unlock( &Mutex->Protector.Mutex );
}
+// --------------------------------------------------------------------
+// Semaphores
+// --------------------------------------------------------------------
void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
{
memset(Sem, 0, sizeof(tSemaphore));
return AmmountToAdd;
}
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
+int RWLock_AcquireRead(tRWLock *Lock)
+{
+ if( !Lock->ReaderWaiting ) {
+ Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+ pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
+ }
+ pthread_rwlock_rdlock( (void*)Lock->ReaderWaiting );
+ return 0;
+}
+int RWLock_AcquireWrite(tRWLock *Lock)
+{
+ if( !Lock->ReaderWaiting ) {
+ Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+ pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
+ }
+ pthread_rwlock_wrlock( (void*)Lock->ReaderWaiting );
+ return 0;
+}
+void RWLock_Release(tRWLock *Lock)
+{
+ pthread_rwlock_unlock( (void*)Lock->ReaderWaiting );
+}
+
+
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
Uint32 Threads_WaitEvents(Uint32 Mask)
{
Uint32 rv;
+
+ Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
+
gpCurrentThread->WaitMask = Mask;
if( !(gpCurrentThread->Events & Mask) )
- SDL_SemWait( gpCurrentThread->EventSem );
+ {
+ do {
+ if( SDL_SemWait( gpCurrentThread->EventSem ) == -1 ) {
+ Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
+ gpCurrentThread, gpCurrentThread->EventSem);
+ break;
+ }
+ } while(SDL_SemValue(gpCurrentThread->EventSem));
+ // NOTE: While loop catches multiple event occurances
+ Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
+ }
rv = gpCurrentThread->Events & Mask;
gpCurrentThread->Events &= ~Mask;
gpCurrentThread->WaitMask = -1;
+
+ Log_Debug("Threads", "- rv = %x", rv);
+
return rv;
}
void Threads_PostEvent(tThread *Thread, Uint32 Events)
{
Thread->Events |= Events;
+ Log_Debug("Threads", "Trigger event %x (->Events = %p)", Events, Thread->Events);
- if( Thread->WaitMask & Events )
- SDL_SemPost( gpCurrentThread->EventSem );
+ if( Thread->WaitMask & Events ) {
+ SDL_SemPost( Thread->EventSem );
+// Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
+ }
+}
+
+void Threads_ClearEvent(Uint32 EventMask)
+{
+ gpCurrentThread->Events &= ~EventMask;
}