X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fselect.c;h=a18b91c58dce0fe1a65d7b376f969ca201426403;hb=9c4eedf4893f851bd1ba60ce541c8d098a9ef7f7;hp=439afc022fbcae21b1fc5390873ff6ae09a06129;hpb=51ab5f489bc356940c95cc936fd0508e8f07ea97;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/select.c b/KernelLand/Kernel/vfs/select.c index 439afc02..a18b91c5 100644 --- a/KernelLand/Kernel/vfs/select.c +++ b/KernelLand/Kernel/vfs/select.c @@ -5,7 +5,6 @@ * 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 @@ -16,13 +15,11 @@ #include #include #include +#include // === CONSTANTS === #define NUM_THREADS_PER_ALLOC 4 -// === IMPORTS === -extern tThread *Proc_GetCurThread(void); - // === TYPES === typedef struct sVFS_SelectListEnt tVFS_SelectListEnt; @@ -58,13 +55,14 @@ void VFS_int_Select_SignalAll(tVFS_SelectList *List); // === FUNCTIONS === int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *Name) { - tThread *thisthread = Proc_GetCurThread(); - int ret, type; + tThread * const thisthread = Proc_GetCurThread(); + int ret; ENTER("pNode iTypeFlags pTimeout sName", Node, TypeFlags, Timeout, Name); // Initialise - for( type = 0; type < 3; type ++ ) + ret = 0; + for( int type = 0; type < 3; type ++ ) { tVFS_SelectList **list; int *flag, wanted, maxAllowed; @@ -80,35 +78,49 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N VFS_int_Select_AddThread(*list, thisthread, maxAllowed); if( *flag == wanted ) { - VFS_int_Select_RemThread(*list, thisthread); - LEAVE('i', 1); - return 1; + ret |= (1 << type); } } - // - Fast return for polling - if( Timeout && *Timeout == 0 ) return 0; - // Wait for things - if( !Timeout || *Timeout > 0 ) + if( ret ) + { + // Skip wait, conditions already met + LOG("ret = %i, skipping wait", ret); + } + else if( !Timeout ) { LOG("Semaphore_Wait()"); - // TODO: Actual timeout - Threads_WaitEvents( THREAD_EVENT_VFS ); + Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_SIGNAL ); + } + else if( *Timeout > 0 ) + { + tTimer *t = Time_AllocateTimer(NULL, NULL); + // Clear timer event + Threads_ClearEvent( THREAD_EVENT_TIMER ); + LOG("Timeout %lli ms", *Timeout); + Time_ScheduleTimer( t, *Timeout ); + // Wait for the timer or a VFS event + Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER|THREAD_EVENT_SIGNAL ); + Time_FreeTimer(t); } // Get return value ret = 0; - for( type = 0; type < 3; type ++ ) + for( int type = 0; type < 3; type ++ ) { tVFS_SelectList **list; int *flag, wanted, maxAllowed; if( !(TypeFlags & (1 << type)) ) continue; VFS_int_Select_GetType(type, Node, &list, &flag, &wanted, &maxAllowed); - LOG("VFS_int_Select_RemThread()"); + LOG("VFS_int_Select_RemThread() for %i", type); + ASSERT(*list); VFS_int_Select_RemThread(*list, thisthread); ret = ret || *flag == wanted; } + + Threads_ClearEvent( THREAD_EVENT_VFS ); + Threads_ClearEvent( THREAD_EVENT_TIMER ); LEAVE('i', ret); return ret; @@ -119,8 +131,8 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set tThread *thisthread = Proc_GetCurThread(); int ret; - ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout bIsKernel", - MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, IsKernel); + ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout xExtraEvents bIsKernel", + MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, ExtraEvents, IsKernel); // 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, @@ -130,6 +142,8 @@ 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 + if( ReadHandles ) + LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]); 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); @@ -139,29 +153,44 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // If there were events waiting, de-register and return if( ret > 0 ) { + LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]); 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); + LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]); LEAVE('i', ret); return ret; } - - // TODO: Implement timeout - LOG("Timeout = %p", Timeout); - - // Wait (only if there is no timeout, or it is greater than zero - if( !Timeout || *Timeout > 0 ) + + // Wait for things + if( !Timeout ) { - // TODO: Timeout - // TODO: Allow extra events to be waited upon - Threads_WaitEvents( THREAD_EVENT_VFS|ExtraEvents ); + LOG("Waiting for VFS/SIGNAL events (Plus 0x%x)", ExtraEvents); + // TODO: Actual timeout + Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_SIGNAL|ExtraEvents ); + } + else if( *Timeout > 0 ) + { + tTimer *t = Time_AllocateTimer(NULL, NULL); + // Clear timer event + Threads_ClearEvent( THREAD_EVENT_TIMER ); + // TODO: Convert *Timeout? + LOG("Timeout %lli ms", *Timeout); + Time_ScheduleTimer( t, *Timeout ); + // Wait for the timer or a VFS event + Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_TIMER|ExtraEvents ); + Time_FreeTimer(t); } - // Fill output (modify *Handles) + LOG("De-registering"); // - Also, de-register 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); + + Threads_ClearEvent( THREAD_EVENT_VFS ); + Threads_ClearEvent( THREAD_EVENT_TIMER ); + LEAVE('i', ret); return ret; } @@ -169,6 +198,7 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // Mark a node as having data ready for reading int VFS_MarkAvaliable(tVFS_Node *Node, BOOL IsDataAvaliable) { + ASSERTR(Node, 1); ENTER("pNode bIsDataAvaliable", Node, IsDataAvaliable); Node->DataAvaliable = !!IsDataAvaliable; if( Node->DataAvaliable ) @@ -180,6 +210,7 @@ int VFS_MarkAvaliable(tVFS_Node *Node, BOOL IsDataAvaliable) // Mark a node as having a full buffer int VFS_MarkFull(tVFS_Node *Node, BOOL IsBufferFull) { + ASSERTR(Node, 1); ENTER("pNode bIsBufferFull", Node, IsBufferFull); Node->BufferFull = !!IsBufferFull; if( !Node->BufferFull ) @@ -191,6 +222,7 @@ int VFS_MarkFull(tVFS_Node *Node, BOOL IsBufferFull) // Mark a node as errored int VFS_MarkError(tVFS_Node *Node, BOOL IsErrorState) { + ASSERTR(Node, 1); ENTER("pNode bIsErrorState", Node, IsErrorState); Node->ErrorOccurred = !!IsErrorState; if( Node->ErrorOccurred ) @@ -284,8 +316,10 @@ int VFS_int_Select_Register(tThread *Thread, int MaxHandle, fd_set *Handles, int } // Check for the flag - if( !!*flag == !!wantedFlagValue ) + if( !!*flag == !!wantedFlagValue ) { + LOG(" %i == want %i", !!*flag, !!wantedFlagValue); numFlagged ++; + } } LEAVE('i', numFlagged); @@ -326,8 +360,6 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i continue; } - // Get the type of the listen - // Get the type of the listen if( VFS_int_Select_GetType(Type, handle->Node, &list, &flag, &wantedFlagValue, NULL) ) { LEAVE('i', 0); @@ -340,6 +372,8 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i // Check for the flag if( !!*flag == !!wantedFlagValue ) { numFlagged ++; + LOG(" %i == want %i", !!*flag, !!wantedFlagValue); + FD_SET(i, Handles); } else { FD_CLR(i, Handles); @@ -380,6 +414,7 @@ int VFS_int_Select_AddThread(tVFS_SelectList *List, tThread *Thread, int MaxAllo } count ++; if( MaxAllowed && count >= MaxAllowed ) { + Mutex_Release(&List->Lock); LEAVE('i', 1); return 1; } @@ -417,7 +452,6 @@ int VFS_int_Select_AddThread(tVFS_SelectList *List, tThread *Thread, int MaxAllo void VFS_int_Select_RemThread(tVFS_SelectList *List, tThread *Thread) { - int i; tVFS_SelectListEnt *block, *prev = NULL; ENTER("pList pThread", List, Thread); @@ -430,7 +464,7 @@ void VFS_int_Select_RemThread(tVFS_SelectList *List, tThread *Thread) // Look for the thread do { - for( i = 0; i < NUM_THREADS_PER_ALLOC; i ++ ) + for( int i = 0; i < NUM_THREADS_PER_ALLOC; i ++ ) { if( block->Threads[i] == Thread ) {