Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[tpg/acess2.git] / Kernel / drv / fifo.c
index 0057053..0779a60 100644 (file)
@@ -1,6 +1,7 @@
 /* AcessOS
  * FIFO Pipe Driver
  */
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 #include <fs_devfs.h>
@@ -20,7 +21,6 @@ typedef struct sPipe {
         int    WritePos;
         int    BufSize;
        char    *Buffer;
-       tSemaphore      Semaphore;
 } tPipe;
 
 // === PROTOTYPES ===
@@ -29,14 +29,30 @@ typedef struct sPipe {
 char   *FIFO_ReadDir(tVFS_Node *Node, int Id);
 tVFS_Node      *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
  int   FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+void   FIFO_Reference(tVFS_Node *Node);
 void   FIFO_Close(tVFS_Node *Node);
  int   FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName);
 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-tPipe  *FIFO_Int_NewPipe(int Size, char *Name);
+Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
+tPipe  *FIFO_Int_NewPipe(int Size, const char *Name);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
+tVFS_NodeType  gFIFO_DirNodeType = {
+       .TypeName = "FIFO Dir Node",
+       .ReadDir = FIFO_ReadDir,
+       .FindDir = FIFO_FindDir,
+       .MkNod = FIFO_MkNod,
+       .Relink = FIFO_Relink,
+       .IOCtl = FIFO_IOCtl
+};
+tVFS_NodeType  gFIFO_PipeNodeType = {
+       .TypeName = "FIFO Pipe Node",
+       .Read = FIFO_Read,
+       .Write = FIFO_Write,
+       .Close = FIFO_Close,
+       .Reference = FIFO_Reference
+};
 tDevFS_Driver  gFIFO_DriverInfo = {
        NULL, "fifo",
        {
@@ -44,11 +60,7 @@ tDevFS_Driver        gFIFO_DriverInfo = {
        .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Flags = VFS_FFLAG_DIRECTORY,
-       .ReadDir = FIFO_ReadDir,
-       .FindDir = FIFO_FindDir,
-       .MkNod = FIFO_MkNod,
-       .Relink = FIFO_Relink,
-       .IOCtl = FIFO_IOCtl
+       .Type = &gFIFO_DirNodeType
        }
 };
 tVFS_Node      gFIFO_AnonNode = {
@@ -135,6 +147,13 @@ int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
        return 0;
 }
 
+void FIFO_Reference(tVFS_Node *Node)
+{
+       if(!Node->ImplPtr)      return ;
+       
+       Node->ReferenceCount ++;
+}
+
 /**
  * \fn void FIFO_Close(tVFS_Node *Node)
  * \brief Close a FIFO end
@@ -150,6 +169,7 @@ void FIFO_Close(tVFS_Node *Node)
        pipe = Node->ImplPtr;
        
        if(strcmp(pipe->Name, "anon") == 0) {
+               Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
                free(Node->ImplPtr);
                return ;
        }
@@ -214,32 +234,50 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        tPipe   *pipe = Node->ImplPtr;
        Uint    len;
        Uint    remaining = Length;
-       
+
        if(!pipe)       return 0;
        
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
        while(remaining)
        {
                // Wait for buffer to fill
-               if(pipe->Flags & PF_BLOCKING) {
-                       len = Semaphore_Wait( &pipe->Semaphore, remaining );
+               if(pipe->Flags & PF_BLOCKING)
+               {
+                       if( pipe->ReadPos == pipe->WritePos )
+                               VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
+                       
                }
                else
                {
                        if(pipe->ReadPos == pipe->WritePos)
+                       {
+                               VFS_MarkAvaliable(Node, 0);
+                               LEAVE('i', 0);
                                return 0;
-                       // Read buffer
-                       if(pipe->WritePos - pipe->ReadPos < remaining)
-                               len = pipe->WritePos - pipe->ReadPos;
-                       else
-                               len = remaining;
+                       }
                }
-               
+       
+               len = remaining;
+               if( pipe->ReadPos < pipe->WritePos )
+               {
+                        int    avail_bytes = pipe->WritePos - pipe->ReadPos;
+                       if( avail_bytes < remaining )   len = avail_bytes;
+               }
+               else
+               {
+                        int    avail_bytes = pipe->WritePos + pipe->BufSize - pipe->ReadPos;
+                       if( avail_bytes < remaining )   len = avail_bytes;
+               }
+
+               LOG("len = %i, remaining = %i", len, remaining);                
+
                // Check if read overflows buffer
                if(len > pipe->BufSize - pipe->ReadPos)
                {
                        int ofs = pipe->BufSize - pipe->ReadPos;
                        memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
-                       memcpy(Buffer + ofs, &pipe->Buffer, len-ofs);
+                       memcpy((Uint8*)Buffer + ofs, &pipe->Buffer, len-ofs);
                }
                else
                {
@@ -250,12 +288,23 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                pipe->ReadPos += len;
                pipe->ReadPos %= pipe->BufSize;
                
+               // Mark some flags
+               if( pipe->ReadPos == pipe->WritePos ) {
+                       VFS_MarkAvaliable(Node, 0);
+               }
+               VFS_MarkFull(Node, 0);  // Buffer can't still be full
+               
                // Decrement Remaining Bytes
                remaining -= len;
                // Increment Buffer address
-               Buffer += len;
+               Buffer = (Uint8*)Buffer + len;
+               
+               // TODO: Option to read differently
+               LEAVE('i', len);
+               return len;
        }
 
+       LEAVE('i', Length);
        return Length;
 
 }
@@ -264,24 +313,42 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
  * \fn Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
  * \brief Write to a fifo pipe
  */
-Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
 {
        tPipe   *pipe = Node->ImplPtr;
        Uint    len;
        Uint    remaining = Length;
        
        if(!pipe)       return 0;
+
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
        
        while(remaining)
        {
                // Wait for buffer to empty
                if(pipe->Flags & PF_BLOCKING) {
-                       len = Semaphore_Signal( &pipe->Semaphore, remaining );
+                       if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
+                               VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
+
+                       len = remaining;
+                       if( pipe->ReadPos > pipe->WritePos )
+                       {
+                                int    rem_space = pipe->ReadPos - pipe->WritePos;
+                               if(rem_space < remaining)       len = rem_space;
+                       }
+                       else
+                       {
+                                int    rem_space = pipe->ReadPos + pipe->BufSize - pipe->WritePos;
+                               if(rem_space < remaining)       len = rem_space;
+                       }
                }
                else
                {
                        if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
+                       {
+                               LEAVE('i', 0);
                                return 0;
+                       }
                        // Write buffer
                        if(pipe->ReadPos - pipe->WritePos < remaining)
                                len = pipe->ReadPos - pipe->WritePos;
@@ -294,7 +361,7 @@ Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                {
                        int ofs = pipe->BufSize - pipe->WritePos;
                        memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
-                       memcpy(&pipe->Buffer, Buffer + ofs, len-ofs);
+                       memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
                }
                else
                {
@@ -305,31 +372,37 @@ Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                pipe->WritePos += len;
                pipe->WritePos %= pipe->BufSize;
                
+               // Mark some flags
+               if( pipe->ReadPos == pipe->WritePos ) {
+                       VFS_MarkFull(Node, 1);  // Buffer full
+               }
+               VFS_MarkAvaliable(Node, 1);
+               
                // Decrement Remaining Bytes
                remaining -= len;
                // Increment Buffer address
-               Buffer += len;
+               Buffer = (Uint8*)Buffer + len;
        }
 
+       LEAVE('i', Length);
        return Length;
 }
 
 // --- HELPERS ---
 /**
- * \fn tPipe *FIFO_Int_NewPipe(int Size, char *Name)
+ * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
  * \brief Create a new pipe
  */
-tPipe *FIFO_Int_NewPipe(int Size, char *Name)
+tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
 {
        tPipe   *ret;
         int    namelen = strlen(Name) + 1;
         int    allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
        
-       ret = malloc(allocsize);
+       ret = calloc(1, allocsize);
        if(!ret)        return NULL;
        
        // Clear Return
-       memset(ret, 0, allocsize);
        ret->Flags = PF_BLOCKING;
        
        // Allocate Buffer
@@ -340,9 +413,10 @@ tPipe *FIFO_Int_NewPipe(int Size, char *Name)
        ret->Name = ret->Buffer + Size;
        strcpy(ret->Name, Name);
        // - Start empty, max of `Size`
-       Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
+       //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
        
        // Set Node
+       ret->Node.ReferenceCount = 1;
        ret->Node.Size = 0;
        ret->Node.ImplPtr = ret;
        ret->Node.UID = Threads_GetUID();
@@ -356,9 +430,7 @@ tPipe *FIFO_Int_NewPipe(int Size, char *Name)
        ret->Node.CTime
                = ret->Node.MTime
                = ret->Node.ATime = now();
-       ret->Node.Read = FIFO_Read;
-       ret->Node.Write = FIFO_Write;
-       ret->Node.Close = FIFO_Close;
+       ret->Node.Type = &gFIFO_PipeNodeType;
        
        return ret;
 }

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