AcessNative - Rework of thread handling
authorJohn Hodge <[email protected]>
Wed, 6 Nov 2013 04:28:43 +0000 (12:28 +0800)
committerJohn Hodge <[email protected]>
Wed, 6 Nov 2013 04:28:43 +0000 (12:28 +0800)
AcessNative/acesskernel_src/Makefile
AcessNative/acesskernel_src/include/arch.h
AcessNative/acesskernel_src/include/threads_glue.h
AcessNative/acesskernel_src/include/threads_int.h
AcessNative/acesskernel_src/server.c
AcessNative/acesskernel_src/syscalls.c
AcessNative/acesskernel_src/threads.c
AcessNative/acesskernel_src/threads_glue.c
AcessNative/acesskernel_src/vfs_handle.c

index ad47c25..f90b18b 100644 (file)
@@ -15,6 +15,7 @@ KERNEL_SRC = ../../KernelLand/Kernel/
 LDACESS_SRC = ../../Usermode/Libraries/ld-acess.so_src/\r
 \r
 KERNEL_OBJ := logging.o adt.o lib.o debug.o messages.o drvutil_disk.o drvutil_video.o\r
+KERNEL_OBJ += mutex.o semaphore.o rwlock.o workqueue.o events.o\r
 #KERNEL_OBJ += libc.o\r
 KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o\r
 KERNEL_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o vfs/select.o\r
@@ -62,7 +63,7 @@ clean:
 \r
 $(BIN): $(OBJ) $(N_OBJ) $(K_OBJ) $(BUILDINFO_OBJ)\r
        @echo [LINK] -o $@\r
-       @$(CC) -o $@ $(N_OBJ) $(K_OBJ) $(OBJ) $(BUILDINFO_OBJ) $(LDFLAGS)\r
+       @$(CC) -o $@ $(N_OBJ) $(LDFLAGS) $(K_OBJ) $(OBJ) $(BUILDINFO_OBJ)\r
        @echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum\r
 \r
 $(OBJ): obj-$(PLATFORM)/%.o: %.c\r
index e99948c..1e2be70 100644 (file)
@@ -28,6 +28,8 @@ typedef intptr_t      tPAddr;
 
 typedef        int     BOOL;
 
+#define HALT_CPU()     exit(1)
+
 #include <stddef.h>
 #undef offsetof
 
@@ -36,8 +38,11 @@ struct sShortSpinlock
        void    *Mutex;
 };
 
-#define SHORTLOCK(...)
-#define SHORTREL(...)
+extern void    Threads_int_ShortLock(void **Ptr);
+extern void    Threads_int_ShortRel(void **Ptr);
+
+#define SHORTLOCK(l)   Threads_int_ShortLock(&(l)->Mutex)
+#define SHORTREL(l)    Threads_int_ShortRel(&(l)->Mutex)
 #define CPU_HAS_LOCK(...)      0
 
 //#define      NUM_CFG_ENTRIES 10
index 61346bd..7e09443 100644 (file)
@@ -10,6 +10,7 @@ extern void   Threads_Glue_ReleaseMutex(void **Lock);
 extern void    Threads_Glue_SemInit(void **Ptr, int Val);
 extern int     Threads_Glue_SemWait(void *Ptr, int Max);
 extern int     Threads_Glue_SemSignal( void *Ptr, int AmmountToAdd );
+extern void    Threads_Glue_SemDestroy( void *Ptr );
 
 #endif
 
index 8061f1e..479d70e 100644 (file)
@@ -1,6 +1,39 @@
 #ifndef _THREADS_INT_H_
 #define _THREADS_INT_H_
 
+#include <threads.h>
+
+enum eThreadStatus {
+       THREAD_STAT_NULL,       // Invalid process
+       THREAD_STAT_ACTIVE,     // Running and schedulable process
+       THREAD_STAT_SLEEPING,   // Message Sleep
+       THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
+       THREAD_STAT_SEMAPHORESLEEP,     // Semaphore Sleep
+       THREAD_STAT_QUEUESLEEP, // Queue
+       THREAD_STAT_EVENTSLEEP, // Event sleep
+       THREAD_STAT_RWLOCKSLEEP,
+       THREAD_STAT_WAITING,    // ??? (Waiting for a thread)
+       THREAD_STAT_PREINIT,    // Being created
+       THREAD_STAT_ZOMBIE,     // Died/Killed, but parent not informed
+       THREAD_STAT_DEAD,       // Awaiting burial (free)
+       THREAD_STAT_BURIED      // If it's still on the list here, something's wrong
+};
+static const char * const casTHREAD_STAT[] = {
+       "THREAD_STAT_NULL",     // Invalid process
+       "THREAD_STAT_ACTIVE",   // Running and schedulable process
+       "THREAD_STAT_SLEEPING", // Message Sleep
+       "THREAD_STAT_MUTEXSLEEP",       // Mutex Sleep
+       "THREAD_STAT_SEMAPHORESLEEP",   // Semaphore Sleep
+       "THREAD_STAT_QUEUESLEEP",       // Queue
+       "THREAD_STAT_EVENTSLEEP",       // Event sleep
+       "THREAD_STAT_RWLOCKSLEEP",
+       "THREAD_STAT_WAITING",  // ??? (Waiting for a thread)
+       "THREAD_STAT_PREINIT",  // Being created
+       "THREAD_STAT_ZOMBIE",   // Died/Killed, but parent not informed
+       "THREAD_STAT_DEAD",     // Awaiting burial (free)
+       "THREAD_STAT_BURIED"    // If it's still on the list here, something's wrong
+};
+
 /**
  * \brief IPC Message
  */
@@ -14,11 +47,14 @@ typedef struct sMessage
 
 typedef struct sProcess
 {
+       tTID    PID;
         int    nThreads;
         int    NativePID;
        char    *CWD;
        char    *Chroot;
         int    MaxFD;
+
+       tUID    UID, GID;
 } tProcess;
 
 struct sThread
@@ -27,16 +63,16 @@ struct sThread
        struct sThread  *Next;
 
         int    KernelTID;
+       tProcess        *Process;       
 
-       tTID    TID, PID;
-       tUID    UID, GID;
+       tTID    TID;
 
        struct sThread  *Parent;
-
        char    *ThreadName;
+        int    bInstrTrace;
 
-        int    Status; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
-        int    ExitStatus;
+       enum eThreadStatus      Status; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
+        int    RetStatus;
         int    _errno;
 
        // Threads waiting for this thread to exit.
@@ -48,31 +84,25 @@ struct sThread
        struct sThread  *WaitingThreads;
        struct sThread  *WaitingThreadsEnd;
 
-       tProcess        *Process;       
+
+       tShortSpinlock  IsLocked;
+
+       void    *WaitPointer;
 
        Uint32  EventState, WaitMask;
        void    *EventSem;      // Should be SDL_sem, but I don't want SDL in this header
 
+       void    *ClientPtr;
+
        // Message queue
        tMsg * volatile Messages;       //!< Message Queue
        tMsg    *LastMessage;   //!< Last Message (speeds up insertion)
 };
 
-enum {
-       THREAD_STAT_NULL,       // Invalid process
-       THREAD_STAT_ACTIVE,     // Running and schedulable process
-       THREAD_STAT_SLEEPING,   // Message Sleep
-       THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
-       THREAD_STAT_SEMAPHORESLEEP,     // Semaphore Sleep
-       THREAD_STAT_QUEUESLEEP, // Queue
-       THREAD_STAT_EVENTSLEEP, // Event sleep
-       THREAD_STAT_WAITING,    // ??? (Waiting for a thread)
-       THREAD_STAT_PREINIT,    // Being created
-       THREAD_STAT_ZOMBIE,     // Died/Killed, but parent not informed
-       THREAD_STAT_DEAD,       // Awaiting burial (free)
-       THREAD_STAT_BURIED      // If it's still on the list here, something's wrong
-};
 extern struct sThread  *Threads_GetThread(Uint TID);
+extern void    Threads_int_WaitForStatusEnd(enum eThreadStatus Status);
+extern int     Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+extern void    Threads_AddActive(tThread *Thread);
 
 #endif
 
index 45806e2..f3826db 100644 (file)
@@ -33,22 +33,24 @@ typedef int socklen_t;
 typedef struct {
         int    ClientID;
        SDL_Thread      *WorkerThread;
+       tRequestHeader  *CurrentRequest;
+       SDL_cond        *WaitFlag;
+       SDL_mutex       *Mutex;
        #if USE_TCP
         int    Socket;
        #else
-       tRequestHeader  *CurrentRequest;
        struct sockaddr_in      ClientAddr;
-       SDL_cond        *WaitFlag;
-       SDL_mutex       *Mutex;
        #endif
 }      tClient;
 
 // === IMPORTS ===
-extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
+// TODO: Move these to headers
+extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, size_t *ReturnLength);
 extern int     Threads_CreateRootProcess(void);
-extern void    Threads_SetThread(int TID);
+extern void    Threads_SetThread(int TID, void *ClientPtr);
 extern void    *Threads_GetThread(int TID);
 extern void    Threads_PostEvent(void *Thread, uint32_t Event);
+extern void    Threads_int_Terminate(void *Thread);
 
 // === PROTOTYPES ===
 tClient        *Server_GetClient(int ClientID);
@@ -70,10 +72,9 @@ SDL_Thread   *gpServer_ListenThread;
 // === CODE ===
 int Server_GetClientID(void)
 {
-        int    i;
        Uint32  thisId = SDL_ThreadID();
        
-       for( i = 0; i < MAX_CLIENTS; i ++ )
+       for( int i = 0; i < MAX_CLIENTS; i ++ )
        {
                if( SDL_GetThreadID(gaServer_Clients[i].WorkerThread) == thisId )
                        return gaServer_Clients[i].ClientID;
@@ -87,13 +88,12 @@ int Server_GetClientID(void)
 tClient *Server_GetClient(int ClientID)
 {
        tClient *ret = NULL;
-        int    i;
        
        // Allocate an ID if needed
        if(ClientID == 0)
                ClientID = Threads_CreateRootProcess();
        
-       for( i = 0; i < MAX_CLIENTS; i ++ )
+       for( int i = 0; i < MAX_CLIENTS; i ++ )
        {
                if( gaServer_Clients[i].ClientID == ClientID ) {
                        return &gaServer_Clients[i];
@@ -104,25 +104,23 @@ tClient *Server_GetClient(int ClientID)
        
        // Uh oh, no free slots
        // TODO: Dynamic allocation
-       if( !ret )
+       if( !ret ) {
+               Log_Error("Server", "Ran out of static client slots (%i)", MAX_CLIENTS);
                return NULL;
+       }
        
        // Allocate a thread for the process
        ret->ClientID = ClientID;
+       ret->CurrentRequest = NULL;
        #if USE_TCP
        ret->Socket = 0;
-       #else
-       ret->CurrentRequest = NULL;
        #endif
                
        if( !ret->WorkerThread ) {
-               #if USE_TCP
-               #else
+               Log_Debug("Server", "Creating worker for %p", ret);
                ret->WaitFlag = SDL_CreateCond();
                ret->Mutex = SDL_CreateMutex();
                SDL_mutexP( ret->Mutex );
-               #endif
-               Log_Debug("Server", "Creating worker for %p", ret);
                ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
        }
        
@@ -133,135 +131,12 @@ int Server_WorkerThread(void *ClientPtr)
 {
        tClient *Client = ClientPtr;
 
-       Log_Debug("Server", "Worker %p", ClientPtr);    
-
-       #if USE_TCP
-       while( *((volatile typeof(Client->Socket)*)&Client->Socket) == 0 )
-               ;
-       Threads_SetThread( Client->ClientID );
-       
-       while( Client->ClientID != -1 )
-       {
-               fd_set  fds;
-                int    nfd = Client->Socket+1;
-               FD_ZERO(&fds);
-               FD_SET(Client->Socket, &fds);
-               
-               int rv = select(nfd, &fds, NULL, NULL, NULL);   // TODO: Timeouts?
-               if(rv < 0) {
-                       perror("select");
-                       continue ;
-               }
-//             Log_Debug("Server", "%p: rv=%i", Client, rv);           
-
-               if( FD_ISSET(Client->Socket, &fds) )
-               {
-                       const int       ciMaxParamCount = 6;
-                       char    lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
-                       tRequestHeader  *hdr = (void*)lbuf;
-                       size_t  len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
-//                     Log_Debug("Server", "%i bytes of header", len);
-                       if( len == 0 ) {
-                               Log_Notice("Server", "Zero RX on %i (worker %p)", Client->Socket, Client);
-                               break;
-                       }
-                       if( len == -1 ) {
-                               perror("recv header");
-//                             Log_Warning("Server", "recv() error - %s", strerror(errno));
-                               break;
-                       }
-                       if( len != sizeof(*hdr) ) {
-                               // Oops?
-                               Log_Warning("Server", "FD%i bad sized (%i != exp %i)",
-                                       Client->Socket, len, sizeof(*hdr));
-                               continue ;
-                       }
-
-                       if( hdr->NParams > ciMaxParamCount ) {
-                               // Oops.
-                               Log_Warning("Server", "FD%i too many params (%i > max %i)",
-                                       Client->Socket, hdr->NParams, ciMaxParamCount);
-                               break ;
-                       }
-
-                       if( hdr->NParams > 0 )
-                       {
-                               len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
-//                             Log_Debug("Server", "%i bytes of params", len);
-                               if( len != hdr->NParams*sizeof(tRequestValue) ) {
-                                       // Oops.
-                                       perror("recv params");
-                                       Log_Warning("Sever", "Recieving params failed");
-                                       break ;
-                               }
-                       }
-                       else
-                       {
-//                             Log_Debug("Server", "No params?");
-                       }
-
-                       // Get buffer size
-                       size_t  hdrsize = sizeof(tRequestHeader) + hdr->NParams*sizeof(tRequestValue);
-                       size_t  bufsize = hdrsize;
-                        int    i;
-                       for( i = 0; i < hdr->NParams; i ++ )
-                       {
-                               if( hdr->Params[i].Flags & ARG_FLAG_ZEROED )
-                                       ;
-                               else {
-                                       bufsize += hdr->Params[i].Length;
-                               }
-                       }
-
-                       // Allocate full buffer
-                       hdr = malloc(bufsize);
-                       memcpy(hdr, lbuf, hdrsize);
-                       if( bufsize > hdrsize )
-                       {
-                               size_t  rem = bufsize - hdrsize;
-                               char    *ptr = (void*)( hdr->Params + hdr->NParams );
-                               while( rem )
-                               {
-                                       len = recv(Client->Socket, ptr, rem, 0);
-//                                     Log_Debug("Server", "%i bytes of data", len);
-                                       if( len == -1 ) {
-                                               // Oops?
-                                               perror("recv data");
-                                               Log_Warning("Sever", "Recieving data failed");
-                                               break ;
-                                       }
-                                       rem -= len;
-                                       ptr += len;
-                               }
-                               if( rem ) {
-                                       break;
-                               }
-                       }
-//                     else
-//                             Log_Debug("Server", "no data");
+       Log_Debug("Server", "Worker %p active", ClientPtr);     
 
-                        int    retlen;
-                       tRequestHeader  *retHeader;
-                       retHeader = SyscallRecieve(hdr, &retlen);
-                       if( !retHeader ) {
-                               // Some sort of error
-                               Log_Warning("Server", "SyscallRecieve failed?");
-                               continue ;
-                       }
-                       
-                       send(Client->Socket, (void*)retHeader, retlen, 0); 
-
-                       // Clean up
-                       free(hdr);
-               }
-       }
-       #else
-       tRequestHeader  *retHeader;
        tRequestHeader  errorHeader;
-        int    retSize = 0;
-        int    sentSize;
+       size_t  retSize = 0;
         int    cur_client_id = 0;
-       while( Client->ClientID != -1 )
+       while( Client->ClientID != 0 )
        {
                // Wait for something to do
                if( Client->CurrentRequest == NULL )
@@ -269,26 +144,13 @@ int Server_WorkerThread(void *ClientPtr)
                if( Client->CurrentRequest == NULL )
                        continue ;
                
-//             Log_Debug("AcessSrv", "Worker got message %p", Client->CurrentRequest);
-               
                if(Client->ClientID != cur_client_id) {
-//                     Log_Debug("AcessSrv", "Client thread ID changed from %i to %i",
-//                             cur_client_id, Client->ClientID);
-                       Threads_SetThread( Client->ClientID );
+                       Threads_SetThread( Client->ClientID, Client );
                        cur_client_id = Client->ClientID;
                }
                
-               // Debug
-               {
-                       int     callid = Client->CurrentRequest->CallID;
-                       Log_Debug("AcessSrv", "Client %i request %i %s",
-                               Client->ClientID, callid,
-                               callid < N_SYSCALLS ? casSYSCALL_NAMES[callid] : "UNK"
-                               );
-               }
-               
                // Get the response
-               retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
+               tRequestHeader  *retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
 
                if( !retHeader ) {
                        // Return an error to the client
@@ -305,26 +167,27 @@ int Server_WorkerThread(void *ClientPtr)
                // Mark the thread as ready for another job
                free(Client->CurrentRequest);
                Client->CurrentRequest = 0;
-               
-//             Log_Debug("AcessSrv", "Sending %i to %x:%i (Client %i)",
-//                     retSize, ntohl(Client->ClientAddr.sin_addr.s_addr),
-//                     ntohs(Client->ClientAddr.sin_port),
-//                     Client->ClientID
-//                     );
-               
-               // Return the data
-               sentSize = sendto(gSocket, retHeader, retSize, 0,
-                       (struct sockaddr*)&Client->ClientAddr, sizeof(Client->ClientAddr)
-                       );
-               if( sentSize != retSize ) {
-                       perror("Server_WorkerThread - send");
+
+               // If the thread is being terminated, don't send reply
+               if( Client->ClientID > 0 )
+               {
+                       // Return the data
+                       #if USE_TCP
+                       size_t sentSize = send(Client->Socket, retHeader, retSize, 0); 
+                       #else
+                       size_t sentSize = sendto(gSocket, retHeader, retSize, 0,
+                               (struct sockaddr*)&Client->ClientAddr, sizeof(Client->ClientAddr)
+                               );
+                       #endif
+                       if( sentSize != retSize ) {
+                               perror("Server_WorkerThread - send");
+                       }
                }
                
                // Free allocated header
                if( retHeader != &errorHeader )
                        free( retHeader );
        }
-       #endif
        Log_Notice("Server", "Terminated Worker %p", ClientPtr);        
        return 0;
 }
@@ -405,83 +268,243 @@ int Server_Shutdown(void)
        return 0;
 }
 
+#if USE_TCP
+int Server_int_HandleRx(tClient *Client)
+{
+       const int       ciMaxParamCount = 6;
+       char    lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
+       tRequestHeader  *hdr = (void*)lbuf;
+       size_t  len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
+       if( len == 0 ) {
+               Log_Notice("Server", "Zero RX on %i (worker %p)", Client->Socket, Client);
+               return 1;
+       }
+       if( len == -1 ) {
+               perror("recv header");
+               return 2;
+       }
+       if( len != sizeof(*hdr) ) {
+               // Oops?
+               Log_Warning("Server", "FD%i bad sized (%i != exp %i)",
+                       Client->Socket, len, sizeof(*hdr));
+               return 0;
+       }
+
+       if( hdr->NParams > ciMaxParamCount ) {
+               // Oops.
+               Log_Warning("Server", "FD%i too many params (%i > max %i)",
+                       Client->Socket, hdr->NParams, ciMaxParamCount);
+               return 0;
+       }
+
+       if( hdr->NParams > 0 )
+       {
+               len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
+               if( len != hdr->NParams*sizeof(tRequestValue) ) {
+                       // Oops.
+                       perror("recv params");
+                       Log_Warning("Sever", "Recieving params failed");
+                       return 0;
+               }
+       }
+       else
+       {
+               //Log_Debug("Server", "No params?");
+       }
+
+       // Get buffer size
+       size_t  hdrsize = sizeof(tRequestHeader) + hdr->NParams*sizeof(tRequestValue);
+       size_t  bufsize = hdrsize;
+       for( int i = 0; i < hdr->NParams; i ++ )
+       {
+               if( hdr->Params[i].Flags & ARG_FLAG_ZEROED )
+                       ;
+               else {
+                       bufsize += hdr->Params[i].Length;
+               }
+       }
+
+       // Allocate full buffer
+       hdr = malloc(bufsize);
+       memcpy(hdr, lbuf, hdrsize);
+       if( bufsize > hdrsize )
+       {
+               size_t  rem = bufsize - hdrsize;
+               char    *ptr = (void*)( hdr->Params + hdr->NParams );
+               while( rem )
+               {
+                       len = recv(Client->Socket, ptr, rem, 0);
+                       if( len == -1 ) {
+                               // Oops?
+                               perror("recv data");
+                               Log_Warning("Sever", "Recieving data failed");
+                               return 2;
+                       }
+                       rem -= len;
+                       ptr += len;
+               }
+               if( rem ) {
+                       // Extra data?
+                       return 0;
+               }
+       }
+       else {
+               //Log_Debug("Server", "no data");
+       }
+       
+       // Dispatch to worker
+       if( Client->CurrentRequest ) {
+               printf("Worker thread for client ID %i is busy\n", Client->ClientID);
+               return 1;
+       }
+
+       // Give to worker
+       Log_Debug("Server", "Message from Client %i (%p)", Client->ClientID, Client);
+       Client->CurrentRequest = hdr;
+       SDL_CondSignal(Client->WaitFlag);
+
+       return 0;
+}
+
+int Server_int_HandshakeClient(int Socket, struct sockaddr_in *addr, socklen_t addr_size)
+{
+       ENTER("iSocket paddr iaddr_size",
+               Socket, addr, addr_size);
+       unsigned short  port = ntohs(addr->sin_port);
+       char    addrstr[4*8+8+1];
+       getnameinfo((struct sockaddr*)addr, addr_size, addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+       Log_Debug("Server", "Client connection %s:%i", addrstr, port);
+       
+       // Perform handshake
+       tRequestAuthHdr authhdr;
+       size_t  len  = recv(Socket, &authhdr, sizeof(authhdr), 0);
+       if( len != sizeof(authhdr) ) {
+               // Some form of error?
+               Log_Warning("Server", "Client auth block bad size (%i != exp %i)",
+                       len, sizeof(authhdr));
+               LEAVE('i', 1);
+               return 1;
+       }
+       
+       LOG("authhdr.pid = %i", authhdr.pid);
+       tClient *client = Server_GetClient(authhdr.pid);
+       if( authhdr.pid == 0 ) {
+               // Allocate PID and client structure/thread
+               client->Socket = Socket;
+               authhdr.pid = client->ClientID;
+       }
+       else {
+               Log_Debug("Server", "Client assumed PID %i", authhdr.pid);
+               
+               // Get client structure and make sure it's unused
+               // - Auth token / verifcation?
+               if( !client ) {
+                       Log_Warning("Server", "Can't allocate a client struct for %s:%i",
+                               addrstr, port);
+                       LEAVE('i', 1);
+                       return 1;
+               }
+               if( client->Socket != 0 ) {
+                       Log_Warning("Server", "Client (%i)%p owned by FD%i but %s:%i tried to use it",
+                               authhdr.pid, client, addrstr, port);
+                       LEAVE('i', 1);
+                       return 1;
+               }
+               
+               client->Socket = Socket;
+       }
+
+       LOG("Sending auth reply");      
+       len = send(Socket, (void*)&authhdr, sizeof(authhdr), 0);
+       if( len != sizeof(authhdr) ) {
+               // Ok, this is an error
+               perror("Sending auth reply");
+               LEAVE('i', 1);
+               return 1;
+       }
+
+       // All done, client thread should be watching now               
+       
+       LEAVE('i', 0);
+       return 0;
+}
+
+void Server_int_RemoveClient(tClient *Client)
+{
+       // Trigger the thread to kill itself
+       Threads_int_Terminate( Threads_GetThread(Client->ClientID) );
+       Client->ClientID = 0;
+       close(Client->Socket);
+}
+
+#endif
+
 int Server_ListenThread(void *Unused)
 {      
        // Wait for something to do :)
        for( ;; )
        {
                #if USE_TCP
-               struct sockaddr_in      clientaddr;
-               socklen_t       clientSize = sizeof(clientaddr);
-                int    clientSock = accept(gSocket, (struct sockaddr*)&clientaddr, &clientSize);
-               if( clientSock < 0 ) {
-                       perror("SyscallServer - accept");
-                       break ;
-               }
+               fd_set  fds;
+                int    maxfd = gSocket;
+               FD_ZERO(&fds);
+               FD_SET(gSocket, &fds);
 
-               char    addrstr[4*8+8+1];
-               getnameinfo((struct sockaddr*)&clientaddr, sizeof(clientaddr),
-                       addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
-               Log_Debug("Server", "Client connection %s:%i", addrstr, ntohs(clientaddr.sin_port));
-               
-               // Perform auth
-               size_t  len;
-               tRequestAuthHdr authhdr;
-               len = recv(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
-               if( len != sizeof(authhdr) ) {
-                       // Some form of error?
-                       Log_Warning("Server", "Client auth block bad size (%i != exp %i)",
-                               len, sizeof(authhdr));
-                       close(clientSock);
-                       continue ;
+               for( int i = 0; i < MAX_CLIENTS; i ++ ) {
+                       tClient *client = &gaServer_Clients[i];
+                       if( client->ClientID == 0 )
+                               continue ;
+                       FD_SET(client->Socket, &fds);
+                       if(client->Socket > maxfd)
+                               maxfd = client->Socket;
                }
                
-               Log_Debug("Server", "Client assumed PID %i", authhdr.pid);
-
-               tClient *client;
-               if( authhdr.pid == 0 ) {
-                       // Allocate PID and client structure/thread
-                       client = Server_GetClient(0);
-                       client->Socket = clientSock;
-                       authhdr.pid = client->ClientID;
+               int rv = select(maxfd+1, &fds, NULL, NULL, NULL);
+               Log_Debug("Server", "Select rv = %i", rv);
+               if( rv <= 0 ) {
+                       perror("select");
+                       return 1;
                }
-               else {
-                       // Get client structure and make sure it's unused
-                       // - Auth token / verifcation?
-                       client = Server_GetClient(authhdr.pid);
-                       if( !client ) {
-                               Log_Warning("Server", "Can't allocate a client struct for %s:%i",
-                                       addrstr, clientaddr.sin_port);
-                               close(clientSock);
-                               continue ;
+               
+               // Incoming connection
+               if( FD_ISSET(gSocket, &fds) )
+               {
+                       struct sockaddr_in      clientaddr;
+                       socklen_t       clientSize = sizeof(clientaddr);
+                        int    clientSock = accept(gSocket, (struct sockaddr*)&clientaddr, &clientSize);
+                       if( clientSock < 0 ) {
+                               perror("SyscallServer - accept");
+                               break ;
                        }
-                       if( client->Socket != 0 ) {
-                               Log_Warning("Server", "Client (%i)%p owned by FD%i but %s:%i tried to use it",
-                                       authhdr.pid, client, addrstr, clientaddr.sin_port);
+                       if( Server_int_HandshakeClient(clientSock, &clientaddr, clientSize) ) {
+                               Log_Warning("Server", "Client handshake failed :(");
                                close(clientSock);
-                               continue;
-                       }
-                       else {
-                               client->Socket = clientSock;
                        }
                }
-               Log_Debug("Server", "Client given PID %i - info %p", authhdr.pid, client);
                
-               len = send(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
-               if( len != sizeof(authhdr) ) {
-                       // Ok, this is an error
-                       perror("Sending auth reply");
+               for( int i = 0; i < MAX_CLIENTS; i ++ )
+               {
+                       tClient *client = &gaServer_Clients[i];
+                       if( client->ClientID == 0 )
+                               continue ;
+                       //Debug("Server_ListenThread: Idx %i ID %i FD %i",
+                       //      i, client->ClientID, client->Socket);
+                       if( !FD_ISSET(client->Socket, &fds) )
+                               continue ;
+                       
+                       if( Server_int_HandleRx( client ) )
+                       {
+                               Log_Warning("Server", "Client %p dropped, TODO: clean up", client);
+                               Server_int_RemoveClient(client);
+                       }
                }
-
-               // All done, client thread should be watching now               
-
+       
                #else
                char    data[BUFSIZ];
                tRequestHeader  *req = (void*)data;
                struct sockaddr_in      addr;
                uint    clientSize = sizeof(addr);
                 int    length;
-               tClient *client;
                
                length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
                
@@ -490,13 +513,13 @@ int Server_ListenThread(void *Unused)
                        break;
                }
                
-               // Hand off to a worker thread
-               // - TODO: Actually have worker threads
+               // Recive data
 //             Log_Debug("Server", "%i bytes from %x:%i", length,
 //                     ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
                
-               client = Server_GetClient(req->ClientID);
-               // NOTE: Hack - Should check if all zero
+               tClient *client = Server_GetClient(req->ClientID);
+               // NOTE: I should really check if the sin_addr is zero, but meh
+               // Shouldn't matter much
                if( req->ClientID == 0 || client->ClientAddr.sin_port == 0 )
                {
                        memcpy(&client->ClientAddr, &addr, sizeof(addr));
@@ -510,16 +533,15 @@ int Server_ListenThread(void *Unused)
                        continue;
                }
                
+//             Log_Debug("AcessSrv", "Message from Client %i (%p)",
+//                     client->ClientID, client);
                if( client->CurrentRequest ) {
                        printf("Worker thread for %x:%i is busy\n",
                                ntohl(client->ClientAddr.sin_addr.s_addr), ntohs(client->ClientAddr.sin_port));
                        continue;
                }
                
-//             Log_Debug("AcessSrv", "Message from Client %i (%p)",
-//                     client->ClientID, client);
-
-               // Make a copy of the request data      
+               // Duplicate the data currently on the stack, and dispatch to worker
                req = malloc(length);
                memcpy(req, data, length);
                client->CurrentRequest = req;
index 4194a36..ae2c92c 100644 (file)
@@ -277,12 +277,12 @@ const int ciNumSyscalls = sizeof(caSyscalls)/sizeof(caSyscalls[0]);
 /**
  * \brief Recieve a syscall structure from the server code
  */
-tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
+tRequestHeader *SyscallRecieve(tRequestHeader *Request, size_t *ReturnLength)
 {
        char    formatString[Request->NParams+1];
        char    *inData = (char*)&Request->Params[Request->NParams];
         int    argListLen = 0;
-        int    i, retVal;
+        int    retVal;
        tRequestHeader  *ret;
         int    retValueCount;
         int    retDataLen;
@@ -309,7 +309,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
        retDataLen = sizeof(Uint64) + sizeof(Uint32);   
 
        // Get size of argument list
-       for( i = 0; i < Request->NParams; i ++ )
+       for( int i = 0; i < Request->NParams; i ++ )
        {
                argSizes[i] = Request->Params[i].Length;
                switch(Request->Params[i].Type)
@@ -344,7 +344,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                        return NULL;    // ERROR!
                }
        }
-       formatString[i] = '\0';
+       formatString[Request->NParams] = '\0';
        
        LOG("Request %i(%s) '%s'", Request->CallID, casSYSCALL_NAMES[Request->CallID], formatString);
        
@@ -352,7 +352,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                char    argListData[argListLen];
                argListLen = 0;
                // Build argument list
-               for( i = 0; i < Request->NParams; i ++ )
+               for( int i = 0; i < Request->NParams; i ++ )
                {
                        returnData[i] = NULL;
                        switch(Request->Params[i].Type)
@@ -449,7 +449,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
        //Log_Debug("Syscalls", "Return 0x%llx", retVal);
        
        retValueCount = 2;
-       for( i = 0; i < Request->NParams; i ++ )
+       for( int i = 0; i < Request->NParams; i ++ )
        {
                if( Request->Params[i].Type != ARG_TYPE_DATA )  continue;
                if( !(Request->Params[i].Flags & ARG_FLAG_RETURN) )     continue;
index de61ef4..86b8a89 100644 (file)
@@ -5,7 +5,7 @@
  * threads.c
  * - Thread and process handling
  */
-
+#define DEBUG  1
 #include <arch.h>
 #include <acess.h>
 #include <mutex.h>
@@ -17,12 +17,14 @@ typedef signed long long int        time_t;
 #include <threads_int.h>
 #include <limits.h>
 #include "include/threads_glue.h"
+#include <stdbool.h>
 
 #define THREAD_EVENT_WAKEUP    0x80000000
 
 // === IMPORTS ===
 extern void    VFS_CloneHandleList(int PID);
 extern void    VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
+extern void    VFS_ClearHandles(int PID);
 
 // === STRUCTURES ===
 // === PROTOTYPES ===
@@ -52,25 +54,24 @@ tThread *Proc_GetCurThread(void)
 
 void Threads_Dump(void)
 {
-       tThread *thread;
-       for( thread = gpThreads; thread; thread = thread->GlobalNext )
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
        {
                Log_Log("Threads", "TID %i (%s), PID %i",
-                       thread->TID, thread->ThreadName, thread->PID);
+                       thread->TID, thread->ThreadName, thread->Process->PID);
                Log_Log("Threads", "User: %i, Group: %i",
-                       thread->UID, thread->GID);
+                       thread->Process->UID, thread->Process->GID);
                Log_Log("Threads", "Kernel Thread ID: %i",
                        thread->KernelTID);
        }
 }
 
-void Threads_SetThread(int TID)
+void Threads_SetThread(int TID, void *Client)
 {
-       tThread *thread;
-       for( thread = gpThreads; thread; thread = thread->GlobalNext )
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
        {
                if( thread->TID == TID ) {
                        gpCurrentThread = thread;
+                       thread->ClientPtr = Client;
                        return ;
                }
        }
@@ -79,8 +80,7 @@ void Threads_SetThread(int TID)
 
 tThread        *Threads_GetThread(Uint TID)
 {
-       tThread *thread;
-       for( thread = gpThreads; thread; thread = thread->GlobalNext )
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
        {
                if( thread->TID == TID ) {
                        return thread;
@@ -92,10 +92,9 @@ tThread      *Threads_GetThread(Uint TID)
 /**
  * \brief Clone a thread control block (with a different TID)
  */
-tThread *Threads_CloneTCB(tThread *TemplateThread)
+tThread *Threads_CloneTCB(tThread *TemplateThread, bool bNewProcess)
 {
        tThread *ret = malloc(sizeof(tThread));
-       
        memcpy(ret, TemplateThread, sizeof(tThread));
        
        ret->TID = giThreads_NextThreadID ++;
@@ -105,7 +104,22 @@ tThread *Threads_CloneTCB(tThread *TemplateThread)
        
        ret->WaitingThreads = NULL;
        ret->WaitingThreadsEnd = NULL;
-       
+
+       if( bNewProcess )
+       {
+               tProcess *proc = malloc( sizeof(tProcess) );
+               memcpy(proc, ret->Process, sizeof(tProcess));
+               proc->nThreads = 0;
+               proc->CWD = strdup(proc->CWD);
+               proc->Chroot = strdup(proc->Chroot);
+               
+               proc->PID = ret->TID;
+               
+               ret->Process = proc;
+       }       
+
+       ret->Process->nThreads ++;
+
        // Add to the end of the queue
        // TODO: Handle concurrency issues
        ret->GlobalNext = gpThreads;
@@ -114,10 +128,53 @@ tThread *Threads_CloneTCB(tThread *TemplateThread)
        return ret;
 }
 
-tUID Threads_GetUID() { return gpCurrentThread->UID; }
-tGID Threads_GetGID() { return gpCurrentThread->GID; }
+void Threads_int_Destroy(tThread *Thread)
+{
+       // Clear WaitingThreads
+       
+       Threads_Glue_SemDestroy(Thread->EventSem);
+       free(Thread->ThreadName);
+       Thread->Process->nThreads --;
+}
+
+void Threads_Terminate(void)
+{
+       tThread *us = gpCurrentThread;
+       tProcess *proc = us->Process;
+
+       if( us->TID == proc->PID )
+       {
+               // If we're the process leader, then tear down the entire process
+               VFS_ClearHandles(proc->PID);
+               tThread **next_ptr = &gpThreads;
+               for( tThread *thread = gpThreads; thread; thread = *next_ptr )
+               {
+                       if( thread->Process == proc ) {
+                               Threads_int_Destroy(thread);
+                       }
+                       else {
+                               next_ptr = &thread->Next;
+                       }
+               }
+       }
+       else
+       {
+               // Just a lowly thread, remove from process
+               Threads_int_Destroy(us);
+       }
+       
+       if( proc->nThreads == 0 )
+       {
+               free(proc->Chroot);
+               free(proc->CWD);
+               free(proc);
+       }
+}
+
+tUID Threads_GetUID() { return gpCurrentThread->Process->UID; }
+tGID Threads_GetGID() { return gpCurrentThread->Process->GID; }
 tTID Threads_GetTID() { return gpCurrentThread->TID; }
-tPID Threads_GetPID() { return gpCurrentThread->PID; }
+tPID Threads_GetPID() { return gpCurrentThread->Process->PID; }
 
 int Threads_SetUID(tUID NewUID)
 {
@@ -126,7 +183,7 @@ int Threads_SetUID(tUID NewUID)
                return -1;
        }
        
-       gpCurrentThread->UID = NewUID;
+       gpCurrentThread->Process->UID = NewUID;
        return 0;
 }
 
@@ -137,7 +194,7 @@ int Threads_SetGID(tGID NewGID)
                return -1;
        }
        
-       gpCurrentThread->GID = NewGID;
+       gpCurrentThread->Process->GID = NewGID;
        return 0;
 }
 
@@ -167,8 +224,8 @@ tTID Threads_WaitTID(int TID, int *Status)
        }
        
        // Specific Thread
-       if(TID > 0) {
-               
+       if(TID > 0)
+       {
                tThread *thread = Threads_GetThread(TID);
                tThread *us = gpCurrentThread;
                if(!thread)     return -1;
@@ -189,7 +246,7 @@ tTID Threads_WaitTID(int TID, int *Status)
                
                Threads_WaitEvents( THREAD_EVENT_WAKEUP );
                
-               if(Status)      *Status = thread->ExitStatus;
+               if(Status)      *Status = thread->RetStatus;
                thread->WaitingThreads = thread->WaitingThreads->Next;
                us->Next = NULL;
                
@@ -199,24 +256,13 @@ tTID Threads_WaitTID(int TID, int *Status)
        return 0;
 }
 
-void Threads_Sleep(void)
-{
-       // TODO: Add to a sleeping queue
-       //pause();
-}
-
-void Threads_Yield(void)
-{
-//     yield();
-}
-
 void Threads_Exit(int TID, int Status)
 {
        tThread *toWake;
        
 //     VFS_Handles_Cleanup();
 
-       gpCurrentThread->ExitStatus = Status;
+       gpCurrentThread->RetStatus = Status;
        
        #if 1
        if( gpCurrentThread->Parent )
@@ -238,6 +284,12 @@ void Threads_Exit(int TID, int Status)
        }
 }
 
+void Threads_Sleep()
+{
+       gpCurrentThread->Status = THREAD_STAT_SLEEPING;
+       Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
+}
+
 int Threads_Wake(tThread *Thread)
 {
        Thread->Status = THREAD_STAT_ACTIVE;
@@ -255,121 +307,108 @@ int Threads_WakeTID(tTID TID)
 
 int Threads_CreateRootProcess(void)
 {
-       tThread *thread = Threads_CloneTCB(&gThreadZero);
-       thread->PID = thread->TID;
+       tThread *thread = Threads_CloneTCB(&gThreadZero, true);
        
        // Handle list is created on first open
        
-       return thread->PID;
+       return thread->Process->PID;
 }
 
 int Threads_Fork(void)
 {
-       tThread *thread = Threads_CloneTCB(gpCurrentThread);
-       thread->PID = thread->TID;
+       tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
 
        // Duplicate the VFS handles (and nodes) from vfs_handle.c
-       VFS_CloneHandleList(thread->PID);
+       VFS_CloneHandleList(thread->Process->PID);
        
-       return thread->PID;
+       return thread->Process->PID;
 }
 
 int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
 {
-       tThread *thread = Threads_CloneTCB(gpCurrentThread);
-       thread->PID = thread->TID;
+       tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
        if( info )
        {
                // TODO: PGID?
                //if( info->flags & SPAWNFLAG_NEWPGID )
                //      thread->PGID = thread->PID;
-               if( info->gid && thread->UID == 0 )
-                       thread->GID = info->gid;
-               if( info->uid && thread->UID == 0 )     // last because ->UID is used above
-                       thread->UID = info->uid;
+               if( thread->Process->UID == 0 )
+               {
+                       if( info->gid )
+                               thread->Process->GID = info->gid;
+                       if( info->uid )
+                               thread->Process->UID = info->uid;
+               }
        }
        
-       VFS_CloneHandlesFromList(thread->PID, nFD, FDs);
+       VFS_CloneHandlesFromList(thread->Process->PID, nFD, FDs);
 
-       Log_Debug("Threads", "_spawn: %i", thread->PID);
-       return thread->PID;
-}
-
-// --------------------------------------------------------------------
-// Mutexes 
-// --------------------------------------------------------------------
-int Mutex_Acquire(tMutex *Mutex)
-{
-       Threads_Glue_AcquireMutex(&Mutex->Protector.Mutex);
-       return 0;
-}
-
-void Mutex_Release(tMutex *Mutex)
-{
-       Threads_Glue_ReleaseMutex(&Mutex->Protector.Mutex);
-}
-
-// --------------------------------------------------------------------
-// Semaphores
-// --------------------------------------------------------------------
-void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
-{
-       memset(Sem, 0, sizeof(tSemaphore));
-       // HACK: Use `Sem->Protector` as space for the semaphore pointer
-       Threads_Glue_SemInit( &Sem->Protector.Mutex, InitValue );
+       return thread->Process->PID;
 }
 
-int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
+// ----
+// ----
+void Threads_int_Terminate(tThread *Thread)
 {
-       return Threads_Glue_SemWait( Sem->Protector.Mutex, MaxToTake );
+       Thread->RetStatus = -1;
+       Threads_AddActive(Thread);
 }
 
-int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
 {
-       return Threads_Glue_SemSignal( Sem->Protector.Mutex, AmmountToAdd );
-}
-
-// --------------------------------------------------------------------
-// Event handling
-// --------------------------------------------------------------------
-Uint32 Threads_WaitEvents(Uint32 Mask)
-{
-       Uint32  rv;
-
-       //Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);      
-
-       gpCurrentThread->WaitMask = Mask;
-       if( !(gpCurrentThread->EventState & Mask) )
+       tThread *us = Proc_GetCurThread();
+       ASSERT(Status != THREAD_STAT_ACTIVE);
+       ASSERT(Status != THREAD_STAT_DEAD);
+       LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
+       while( us->Status == Status )
        {
                if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
                        Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
                                gpCurrentThread, gpCurrentThread->EventSem);
+                       return ;
                }
-               //Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
+               if( us->Status == Status )
+                       Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
+                               us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
        }
-       rv = gpCurrentThread->EventState & Mask;
-       gpCurrentThread->EventState &= ~Mask;
-       gpCurrentThread->WaitMask = -1;
-
-       //Log_Debug("Threads", "- rv = %x", rv);
-
-       return rv;
 }
 
-void Threads_PostEvent(tThread *Thread, Uint32 Events)
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
 {
-       Thread->EventState |= Events;
-//     Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
-
-       if( Events == 0 || Thread->WaitMask & Events ) {
-               Threads_Glue_SemSignal( Thread->EventSem, 1 );
-//             Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
+       tThread *us = Proc_GetCurThread();
+       us->Next = NULL;
+       // - Mark as sleeping
+       us->Status = Status;
+       us->WaitPointer = Ptr;
+       us->RetStatus = Num;    // Use RetStatus as a temp variable
+               
+       // - Add to waiting
+       if( ListTail ) {
+               if(*ListTail) {
+                       (*ListTail)->Next = us;
+               }
+               else {
+                       *ListHead = us;
+               }
+               *ListTail = us;
        }
+       else {
+               *ListHead = us;
+       }
+       
+       if( Lock ) {
+               SHORTREL( Lock );
+       }
+       Threads_int_WaitForStatusEnd(Status);
+       us->WaitPointer = NULL;
+       return us->RetStatus;
 }
 
-void Threads_ClearEvent(Uint32 EventMask)
+void Threads_AddActive(tThread *Thread)
 {
-       gpCurrentThread->EventState &= ~EventMask;
+       LOG("%i(%s)", Thread->TID, Thread->ThreadName);
+       Thread->Status = THREAD_STAT_ACTIVE;
+       Threads_Glue_SemSignal(Thread->EventSem, 1);
 }
 
 // --------------------------------------------------------------------
index d400b27..c2efb71 100644 (file)
@@ -18,7 +18,6 @@ typedef void  **tShortSpinlock;
 //#include "/usr/include/signal.h"
 #include <SDL/SDL.h>
 #include <pthread.h>
-#include <assert.h>
 
 #define NORETURN       __attribute__((noreturn))
 #include <logdebug.h>  // Kernel land, but uses standards
@@ -66,35 +65,31 @@ int Threads_Glue_SemWait(void *Ptr, int Max)
 
 int Threads_Glue_SemSignal( void *Ptr, int AmmountToAdd )
 {
-        int    i;
-       for( i = 0; i < AmmountToAdd; i ++ )
+       for( int i = 0; i < AmmountToAdd; i ++ )
                SDL_SemPost( Ptr );
        return AmmountToAdd;
 }
 
-// --------------------------------------------------------------------
-// Event handling
-// --------------------------------------------------------------------
-int RWLock_AcquireRead(tRWLock *Lock)
+void Threads_Glue_SemDestroy( void *Ptr )
 {
-       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;
+       SDL_DestroySemaphore(Ptr);
 }
-int RWLock_AcquireWrite(tRWLock *Lock)
+
+// ---
+// Short Locks
+// ---
+void Threads_int_ShortLock(void **MutexPtr)
 {
-       if( !Lock->ReaderWaiting ) {
-               Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
-               pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
+       if( !*MutexPtr ) {
+               *MutexPtr = malloc( sizeof(pthread_mutex_t) );
+               pthread_mutex_init(*MutexPtr, NULL);
        }
-       pthread_rwlock_wrlock( (void*)Lock->ReaderWaiting );
-       return 0;
+       pthread_mutex_lock(*MutexPtr);
 }
-void RWLock_Release(tRWLock *Lock)
+
+void Threads_int_ShortRel(void **MutexPtr)
 {
-       pthread_rwlock_unlock( (void*)Lock->ReaderWaiting );
+       pthread_mutex_unlock(*MutexPtr);
 }
 
+
index eb0bfc5..6c3992f 100644 (file)
@@ -155,11 +155,10 @@ tVFS_Handle *VFS_GetHandle(int FD)
        }
        else
        {
-               tUserHandles    *ent;
                 int    pid = Threads_GetPID();
                 int    maxhandles = *Threads_GetMaxFD();
                
-               ent = VFS_int_GetUserHandles(pid, 0);
+               tUserHandles *ent = VFS_int_GetUserHandles(pid, 0);
                if(!ent) {
                        Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
                        return NULL;
@@ -248,3 +247,18 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
        
        return -1;
 }
+
+void VFS_ClearHandles(int PID)
+{
+       // Find the PID's handle list
+       tUserHandles *ent = VFS_int_GetUserHandles(PID, 0);
+       if( !ent )      return;
+       // Get a handle
+        int    maxhandles = *Threads_GetMaxFD();
+       for( int i = 0; i < maxhandles; i ++ )
+       {
+               if(ent->Handles[i].Node)        continue;
+               _CloseNode(ent->Handles[i].Node);
+               ent->Handles[i].Node = NULL;
+       }
+}

UCC git Repository :: git.ucc.asn.au