From: John Hodge Date: Mon, 23 Jan 2012 04:53:55 +0000 (+0800) Subject: Kernel - Implemented event wait (untested) X-Git-Tag: rel0.15~792^2~20 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=def8ed174653a8e4b4ecbd58561a5bf8c908aa7a;p=tpg%2Facess2.git Kernel - Implemented event wait (untested) --- diff --git a/Kernel/events.c b/Kernel/events.c index 76886e18..4c872bc0 100644 --- a/Kernel/events.c +++ b/Kernel/events.c @@ -12,8 +12,10 @@ // === CODE === void Threads_PostEvent(tThread *Thread, Uint32 EventMask) { - // TODO: Check that only one bit is set? + // Sanity checking + if( !Thread ) return ; if( EventMask == 0 ) return ; + // TODO: Check that only one bit is set? SHORTLOCK( &Thread->IsLocked ); @@ -34,6 +36,9 @@ void Threads_PostEvent(tThread *Thread, Uint32 EventMask) SHORTREL( &Thread->IsLocked ); } +/** + * \brief Wait for an event to occur + */ Uint32 Threads_WaitEvents(Uint32 EventMask) { Uint32 rv; @@ -47,7 +52,7 @@ Uint32 Threads_WaitEvents(Uint32 EventMask) // Check if a wait is needed SHORTLOCK( &us->IsLocked ); - if( !(us->EventState & EventMask) ) + while( !(us->EventState & EventMask) ) { // Wait us->RetStatus = EventMask; // HACK: Store EventMask in RetStatus diff --git a/Kernel/include/events.h b/Kernel/include/events.h index 5ef4681e..9aa941d0 100644 --- a/Kernel/include/events.h +++ b/Kernel/include/events.h @@ -8,6 +8,8 @@ #ifndef _EVENTS_H_ #define _EVENTS_H_ +#include + #define THREAD_EVENT_VFS 0x00000001 #define THREAD_EVENT_IPCMSG 0x00000002 #define THREAD_EVENT_SIGNAL 0x00000004 diff --git a/Kernel/include/threads.h b/Kernel/include/threads.h index d138cf01..3b23d71c 100644 --- a/Kernel/include/threads.h +++ b/Kernel/include/threads.h @@ -1,11 +1,12 @@ /* + * Acess2 Kernel */ #ifndef _THREADS_H_ #define _THREADS_H_ #include #include -#include +//#include enum eFaultNumbers { @@ -19,6 +20,8 @@ enum eFaultNumbers #define GETMSG_IGNORE ((void*)-1) +typedef struct sThread tThread; + // === FUNCTIONS === extern void Threads_SetFaultHandler(Uint Handler); diff --git a/Kernel/include/threads_int.h b/Kernel/include/threads_int.h index 0bc941df..0192e7a2 100644 --- a/Kernel/include/threads_int.h +++ b/Kernel/include/threads_int.h @@ -23,7 +23,7 @@ typedef struct sMessage * \brief Core threading structure * */ -typedef struct sThread +struct sThread { // --- threads.c's /** @@ -72,7 +72,7 @@ typedef struct sThread // --- event.c Uint32 EventState; -} tThread; +}; enum { diff --git a/Kernel/messages.c b/Kernel/messages.c index 1391d991..9870cfbb 100644 --- a/Kernel/messages.c +++ b/Kernel/messages.c @@ -10,6 +10,7 @@ #include #include #include +#include // === CODE === /** @@ -32,6 +33,9 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) LEAVE_RET('i', -1); } + // TODO: Check message length against global/per-thread maximums + // TODO: Restrict queue length + // Get thread thread = Threads_GetThread( Dest ); @@ -64,9 +68,10 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) } SHORTREL(&thread->IsLocked); - + + // Wake the thread LOG("Waking %p (%i %s)", thread, thread->TID, thread->ThreadName); - Threads_Wake( thread ); + Threads_PostEvent( thread, THREAD_EVENT_IPCMSG ); LEAVE_RET('i', 0); } @@ -77,6 +82,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) * \param Err Pointer to \a errno * \param Source Where to put the source TID * \param Buffer Buffer to place the message data (set to NULL to just get message length) + * \return Message length */ int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer) { diff --git a/Kernel/vfs/select.c b/Kernel/vfs/select.c index ed994927..c87e316b 100644 --- a/Kernel/vfs/select.c +++ b/Kernel/vfs/select.c @@ -4,6 +4,9 @@ * * select.c * - Implements the select() system call (and supporting code) + * + * TODO: Implment timeouts (via an alarm event?) + * TODO: Remove malloc for read/write queues */ #define DEBUG 0 #include @@ -11,33 +14,32 @@ #include "vfs_int.h" #include "vfs_ext.h" #include +#include +#include // === CONSTANTS === #define NUM_THREADS_PER_ALLOC 4 +// === IMPORTS === +extern tThread *Proc_GetCurThread(void); + // === TYPES === -typedef struct sVFS_SelectThread tVFS_SelectThread; typedef struct sVFS_SelectListEnt tVFS_SelectListEnt; // === STRUCTURES === struct sVFS_SelectListEnt { tVFS_SelectListEnt *Next; - tVFS_SelectThread *Threads[NUM_THREADS_PER_ALLOC]; + tThread *Threads[NUM_THREADS_PER_ALLOC]; }; +// NOTE: Typedef is in vfs.h struct sVFS_SelectList { tMutex Lock; tVFS_SelectListEnt FirstEnt; }; -struct sVFS_SelectThread -{ - //! \brief Semaphore to atomically put the listener to sleep - tSemaphore SleepHandle; // TODO: Allow timeouts (by setting an alarm?) -}; - // === PROTOTYPES === // int VFS_SelectNode(tVFS_Node *Node, enum eVFS_SelectTypes Type, tTime *Timeout); // int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set *ErrHandles, tTime *Timeout, BOOL IsKernel); @@ -45,10 +47,10 @@ struct sVFS_SelectThread // int VFS_MarkAvaliable(tVFS_Node *Node, BOOL IsDataAvaliable); // int VFS_MarkError(tVFS_Node *Node, BOOL IsErrorState); int VFS_int_Select_GetType(int Type, tVFS_Node *Node, tVFS_SelectList ***List, int **Flag, int *WantedFlag, int *MaxAllowed); - int VFS_int_Select_Register(tVFS_SelectThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel); - int VFS_int_Select_Deregister(tVFS_SelectThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel); - int VFS_int_Select_AddThread(tVFS_SelectList *List, tVFS_SelectThread *Thread, int MaxAllowed); -void VFS_int_Select_RemThread(tVFS_SelectList *List, tVFS_SelectThread *Thread); + int VFS_int_Select_Register(tThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel); + int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel); + int VFS_int_Select_AddThread(tVFS_SelectList *List, tThread *Thread, int MaxAllowed); +void VFS_int_Select_RemThread(tVFS_SelectList *List, tThread *Thread); void VFS_int_Select_SignalAll(tVFS_SelectList *List); // === GLOBALS === @@ -56,16 +58,11 @@ void VFS_int_Select_SignalAll(tVFS_SelectList *List); // === FUNCTIONS === int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *Name) { - tVFS_SelectThread *thread_info; + tThread *thisthread = Proc_GetCurThread(); int ret, type; ENTER("pNode iTypeFlags pTimeout", Node, TypeFlags, Timeout); - thread_info = malloc(sizeof(tVFS_SelectThread)); - if(!thread_info) LEAVE_RET('i', -1); - - Semaphore_Init(&thread_info->SleepHandle, 0, 0, "VFS_SelectNode()", Name); - // Initialise for( type = 0; type < 3; type ++ ) { @@ -73,7 +70,6 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N int *flag, wanted, maxAllowed; if( !(TypeFlags & (1 << type)) ) continue; if( VFS_int_Select_GetType(type, Node, &list, &flag, &wanted, &maxAllowed) ) { - free(thread_info); LEAVE('i', -1); return -1; } @@ -81,11 +77,10 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N // Alloc if needed if( !*list ) *list = calloc(1, sizeof(tVFS_SelectList)); - VFS_int_Select_AddThread(*list, thread_info, maxAllowed); + VFS_int_Select_AddThread(*list, thisthread, maxAllowed); if( *flag == wanted ) { - VFS_int_Select_RemThread(*list, thread_info); - free(thread_info); + VFS_int_Select_RemThread(*list, thisthread); LEAVE('i', 1); return 1; } @@ -99,7 +94,7 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N { LOG("Semaphore_Wait()"); // TODO: Actual timeout - Semaphore_Wait(&thread_info->SleepHandle, 1); + Threads_WaitEvents( THREAD_EVENT_VFS ); } // Get return value @@ -111,30 +106,23 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N if( !(TypeFlags & (1 << type)) ) continue; VFS_int_Select_GetType(type, Node, &list, &flag, &wanted, &maxAllowed); LOG("VFS_int_Select_RemThread()"); - VFS_int_Select_RemThread(*list, thread_info); + VFS_int_Select_RemThread(*list, thisthread); ret = ret || *flag == wanted; } - free(thread_info); - LEAVE('i', ret); return ret; } int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set *ErrHandles, tTime *Timeout, BOOL IsKernel) { - tVFS_SelectThread *thread_info; + tThread *thisthread = Proc_GetCurThread(); int ret; - thread_info = malloc(sizeof(tVFS_SelectThread)); - if(!thread_info) return -1; - ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout bIsKernel", MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, IsKernel); - Semaphore_Init(&thread_info->SleepHandle, 0, 0, "VFS_Select()", ""); - - // Notes: The idea is to make sure we only enter wait (on the semaphore) + // Notes: The idea is to make sure we only enter wait (Threads_WaitEvents) // if we are going to be woken up (either by an event at a later time, // or by an event that happened while or before we were registering). // Hence, register must happen _before_ we check the state flag @@ -142,19 +130,18 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // or the semaphore is incremeneted (or both, but never none) // Register with nodes - ret = VFS_int_Select_Register(thread_info, MaxHandle, ReadHandles, 0, IsKernel); - ret += VFS_int_Select_Register(thread_info, MaxHandle, WriteHandles, 1, IsKernel); - ret += VFS_int_Select_Register(thread_info, MaxHandle, ErrHandles, 2, IsKernel); + ret = VFS_int_Select_Register(thisthread, MaxHandle, ReadHandles, 0, IsKernel); + ret += VFS_int_Select_Register(thisthread, MaxHandle, WriteHandles, 1, IsKernel); + ret += VFS_int_Select_Register(thisthread, MaxHandle, ErrHandles, 2, IsKernel); LOG("Register ret = %i", ret); // If there were events waiting, de-register and return if( ret > 0 ) { - ret = VFS_int_Select_Deregister(thread_info, MaxHandle, ReadHandles, 0, IsKernel); - ret += VFS_int_Select_Deregister(thread_info, MaxHandle, WriteHandles, 1, IsKernel); - ret += VFS_int_Select_Deregister(thread_info, MaxHandle, ErrHandles, 2, IsKernel); - free(thread_info); + ret = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel); + ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel); + ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel); LEAVE('i', ret); return ret; } @@ -165,16 +152,16 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // Wait (only if there is no timeout, or it is greater than zero if( !Timeout || *Timeout > 0 ) { - ret = Semaphore_Wait(&thread_info->SleepHandle, 1); - // TODO: Do something with ret? + // TODO: Timeout + // TODO: Allow extra events to be waited upon + Threads_WaitEvents( THREAD_EVENT_VFS ); } // Fill output (modify *Handles) // - Also, de-register - ret = VFS_int_Select_Deregister(thread_info, MaxHandle, ReadHandles, 0, IsKernel); - ret += VFS_int_Select_Deregister(thread_info, MaxHandle, WriteHandles, 1, IsKernel); - ret += VFS_int_Select_Deregister(thread_info, MaxHandle, ErrHandles, 2, IsKernel); - free(thread_info); + ret = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel); + ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel); + ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel); LEAVE('i', ret); return ret; } @@ -246,7 +233,7 @@ int VFS_int_Select_GetType(int Type, tVFS_Node *Node, tVFS_SelectList ***List, i /** * \return Number of files with an action */ -int VFS_int_Select_Register(tVFS_SelectThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel) +int VFS_int_Select_Register(tThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel) { int i, numFlagged = 0; tVFS_SelectList **list; @@ -308,7 +295,7 @@ int VFS_int_Select_Register(tVFS_SelectThread *Thread, int MaxHandle, fd_set *Ha /** * \return Number of files with an action */ -int VFS_int_Select_Deregister(tVFS_SelectThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel) +int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, int Type, BOOL IsKernel) { int i, numFlagged = 0; tVFS_SelectList **list; @@ -367,7 +354,7 @@ int VFS_int_Select_Deregister(tVFS_SelectThread *Thread, int MaxHandle, fd_set * /** * \return Boolean failure */ -int VFS_int_Select_AddThread(tVFS_SelectList *List, tVFS_SelectThread *Thread, int MaxAllowed) +int VFS_int_Select_AddThread(tVFS_SelectList *List, tThread *Thread, int MaxAllowed) { int i, count = 0; tVFS_SelectListEnt *block, *prev; @@ -428,7 +415,7 @@ int VFS_int_Select_AddThread(tVFS_SelectList *List, tVFS_SelectThread *Thread, i return 0; } -void VFS_int_Select_RemThread(tVFS_SelectList *List, tVFS_SelectThread *Thread) +void VFS_int_Select_RemThread(tVFS_SelectList *List, tThread *Thread) { int i; tVFS_SelectListEnt *block, *prev = NULL; @@ -507,7 +494,7 @@ void VFS_int_Select_SignalAll(tVFS_SelectList *List) if( block->Threads[i] ) { LOG("block(%p)->Threads[%i] = %p", block, i, block->Threads[i]); - Semaphore_Signal( &block->Threads[i]->SleepHandle, 1 ); + Threads_PostEvent( block->Threads[i], THREAD_EVENT_VFS ); } }