Kernel - Start on SHM 'driver' (and common in-memory finddir/readdir)
authorJohn Hodge <[email protected]>
Sat, 21 Jun 2014 17:36:38 +0000 (01:36 +0800)
committerJohn Hodge <[email protected]>
Sat, 21 Jun 2014 17:36:38 +0000 (01:36 +0800)
KernelLand/Kernel/Makefile
KernelLand/Kernel/drv/fifo.c
KernelLand/Kernel/drv/shm.c [new file with mode: 0644]
KernelLand/Kernel/include/memfs_helpers.h [new file with mode: 0644]
KernelLand/Kernel/include/syscalls.h
KernelLand/Kernel/include/syscalls.inc.asm
KernelLand/Kernel/memfs_helpers.c [new file with mode: 0644]

index cc4f230..93536b8 100644 (file)
@@ -56,13 +56,13 @@ BUILDINFO_SRC := $(OBJDIR)buildinfo.c$(OBJSUFFIX)
 OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
 OBJ += pmemmap.o
 OBJ += heap.o logging.o debug.o lib.o libc.o adt.o time.o utf16.o debug_hooks.o
-OBJ += drvutil_video.o drvutil_disk.o
+OBJ += drvutil_video.o drvutil_disk.o memfs_helpers.o
 OBJ += messages.o modules.o syscalls.o system.o
 OBJ += threads.o mutex.o semaphore.o workqueue.o events.o rwlock.o
 OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/dgram_pipe.o drv/iocache.o drv/pci.o drv/vpci.o
 OBJ += drv/vterm.o drv/vterm_font.o drv/vterm_vt100.o drv/vterm_output.o drv/vterm_input.o drv/vterm_termbuf.o
 OBJ += drv/vterm_2d.o
-OBJ += drv/pty.o drv/serial.o
+OBJ += drv/pty.o drv/serial.o drv/shm.o
 OBJ += binary.o bin/elf.o bin/pe.o
 OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o
 OBJ += vfs/memfile.o vfs/nodecache.o vfs/handle.o vfs/select.o vfs/mmap.o
index de3192a..6d5d483 100644 (file)
 #include <modules.h>
 #include <fs_devfs.h>
 #include <semaphore.h>
+#include <memfs_helpers.h>
 
 // === CONSTANTS ===
 #define DEFAULT_RING_SIZE      2048
 #define PF_BLOCKING            1
 
 // === TYPES ===
-typedef struct sPipe {
-       struct sPipe    *Next;
-       char    *Name;
+typedef struct sPipe
+{
+       tMemFS_FileHdr  FileHdr;
        tVFS_Node       Node;
        Uint    Flags;
         int    ReadPos;
@@ -42,6 +43,9 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
+tMemFS_DirHdr  gFIFO_RootDir = {
+       .FileHdr = { .Name = "FIFO" },
+};
 tVFS_NodeType  gFIFO_DirNodeType = {
        .TypeName = "FIFO Dir Node",
        .ReadDir = FIFO_ReadDir,
@@ -71,7 +75,6 @@ tVFS_Node     gFIFO_AnonNode = {
        .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        };
-tPipe  *gFIFO_NamedPipes = NULL;
 
 // === CODE ===
 /**
@@ -80,6 +83,7 @@ tPipe *gFIFO_NamedPipes = NULL;
  */
 int FIFO_Install(char **Options)
 {
+       MemFS_InitDir( &gFIFO_RootDir );
        DevFS_AddDevice( &gFIFO_DriverInfo );
        return MODULE_ERR_OK;
 }
@@ -98,22 +102,14 @@ int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
  */
 int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
 {
-       tPipe   *tmp = gFIFO_NamedPipes;
-       
        // Entry 0 is Anon Pipes
-       if(Id == 0) {
+       if(Id == 0)
+       {
                strcpy(Dest, "anon");
                return 0;
        }
        
-       // Find the id'th node
-       while(--Id && tmp)      tmp = tmp->Next;
-       // If the list ended, error return
-       if(!tmp)
-               return -EINVAL;
-       // Return good
-       strncpy(Dest, tmp->Name, FILENAME_MAX);
-       return 0;
+       return MemFS_ReadDir(&gFIFO_RootDir, Id-1, Dest);
 }
 
 /**
@@ -123,11 +119,8 @@ int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
  */
 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
 {
-       tPipe   *tmp;
-       if(!Filename)   return NULL;
-       
-       // NULL String Check
-       if(Filename[0] == '\0') return NULL;
+       ASSERTR(Filename, NULL);
+       ASSERTR(Filename[0], NULL);
        
        // Anon Pipe
        if( strcmp(Filename, "anon") == 0 )
@@ -135,19 +128,15 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
                if( Flags & VFS_FDIRFLAG_STAT ) {
                        //return &gFIFI_TemplateAnonNode;
                }
-               tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
-               return &tmp->Node;
+               tPipe *ret = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
+               return &ret->Node;
        }
        
        // Check Named List
-       tmp = gFIFO_NamedPipes;
-       while(tmp)
-       {
-               if(strcmp(tmp->Name, Filename) == 0)
-                       return &tmp->Node;
-               tmp = tmp->Next;
-       }
-       return NULL;
+       tPipe *ret = (tPipe*)MemFS_FindDir(&gFIFO_RootDir, Filename);
+       if(!ret)
+               return NULL;
+       return &ret->Node;
 }
 
 /**
@@ -155,6 +144,25 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
  */
 tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
 {
+       UNIMPLEMENTED();
+       return NULL;
+}
+
+/**
+ * \brief Delete a pipe
+ */
+int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
+{
+       if(Node != &gFIFO_DriverInfo.RootNode)  return 0;
+       
+       // Can't relink anon
+       if(strcmp(OldName, "anon"))     return 0;
+       
+       // Find node
+       tPipe* pipe = (tPipe*)MemFS_Remove(&gFIFO_RootDir, OldName);
+       if(!pipe)       return 0;
+       
+       free(pipe);
        return 0;
 }
 
@@ -171,54 +179,23 @@ void FIFO_Reference(tVFS_Node *Node)
  */
 void FIFO_Close(tVFS_Node *Node)
 {
-       tPipe   *pipe;
        if(!Node->ImplPtr)      return ;
        
        Node->ReferenceCount --;
        if(Node->ReferenceCount)        return ;
        
-       pipe = Node->ImplPtr;
+       tPipe   *pipe = Node->ImplPtr;
        
-       if(strcmp(pipe->Name, "anon") == 0) {
-               Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
-               free(Node->ImplPtr);
+       if(strcmp(pipe->FileHdr.Name, "anon") == 0)
+       {
+               Log_Debug("FIFO", "Pipe %p closed", pipe);
+               free(pipe);
                return ;
        }
        
        return ;
 }
 
-/**
- * \brief Delete a pipe
- */
-int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
-{
-       tPipe   *pipe;
-       
-       if(Node != &gFIFO_DriverInfo.RootNode)  return 0;
-       
-       // Can't relink anon
-       if(strcmp(OldName, "anon"))     return 0;
-       
-       // Find node
-       for(pipe = gFIFO_NamedPipes;
-               pipe;
-               pipe = pipe->Next)
-       {
-               if(strcmp(pipe->Name, OldName) == 0)
-                       break;
-       }
-       if(!pipe)       return 0;
-       
-       // Unlink the pipe
-       if(Node->ImplPtr) {
-               free(Node->ImplPtr);
-               return 1;
-       }
-       
-       return 0;
-}
-
 /**
  * \brief Read from a fifo pipe
  */
@@ -412,10 +389,8 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
        ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
        
        // Set name (and FIFO name)
-       ret->Name = ret->Buffer + Size;
-       strcpy(ret->Name, Name);
-       // - Start empty, max of `Size`
-       //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
+       ret->FileHdr.Name = ret->Buffer + Size;
+       strcpy((char*)ret->FileHdr.Name, Name);
        
        // Set Node
        ret->Node.ReferenceCount = 1;
diff --git a/KernelLand/Kernel/drv/shm.c b/KernelLand/Kernel/drv/shm.c
new file mode 100644 (file)
index 0000000..f825a0e
--- /dev/null
@@ -0,0 +1,204 @@
+/* 
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/shm.c
+ * - Shared memory "device"
+ */
+#define DEBUG  0
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <memfs_helpers.h> 
+#include <semaphore.h>
+
+// === TYPES ===
+#define PAGES_PER_BLOCK        1024
+typedef struct sSHM_BufferBlock
+{
+       struct sSHM_BufferBlock *Next;
+       tPAddr  Pages[PAGES_PER_BLOCK];
+} tSHM_BufferBlock;
+typedef struct
+{
+       tMemFS_FileHdr  FileHdr;
+       tVFS_Node       Node;
+       tSHM_BufferBlock        FirstBlock;
+} tSHM_Buffer;
+
+// === PROTOTYPES ===
+ int   SHM_Install(char **Arguments);
+ int   SHM_Uninstall(void);
+tSHM_Buffer    *SHM_CreateBuffer(const char *Name);
+void   SHM_DeleteBuffer(tSHM_Buffer *Buffer);
+// - Root directory
+ int   SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
+tVFS_Node      *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags);
+tVFS_Node      *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+ int   SHM_Unlink(tVFS_Node *Node, const char *OldName);
+// - Buffers
+void   SHM_Reference(tVFS_Node *Node);
+void   SHM_Close(tVFS_Node *Node);
+size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
+ int   SHM_MMap(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0100, SHM, SHM_Install, SHM_Uninstall, NULL);
+tMemFS_DirHdr  gSHM_RootDir = {
+       .FileHdr = {.Name = "SHMRoot"}
+};
+tVFS_NodeType  gSHM_DirNodeType = {
+       .TypeName = "SHM Root",
+       .ReadDir = SHM_ReadDir,
+       .FindDir = SHM_FindDir,
+       .MkNod   = SHM_MkNod,
+       .Unlink  = SHM_Unlink,
+};
+tVFS_NodeType  gSHM_FileNodeType = {
+       .TypeName = "SHM Buffer",
+       .Read  = SHM_Read,
+       .Write = SHM_Write,
+       .Close = SHM_Close,
+       .MMap  = SHM_MMap,
+       .Reference = SHM_Reference,
+};
+tDevFS_Driver  gSHM_DriverInfo = {
+       .Name = "shm",
+       .RootNode = {
+               .Size = 0,
+               .NumACLs = 1,
+               .ACLs = &gVFS_ACL_EveryoneRW,
+               .Flags = VFS_FFLAG_DIRECTORY,
+               .Type = &gSHM_DirNodeType
+       }
+};
+
+// === CODE ===
+int SHM_Install(char **Arguments)
+{
+       MemFS_InitDir(&gSHM_RootDir);
+       DevFS_AddDevice( &gSHM_DriverInfo );
+       return MODULE_ERR_OK;
+}
+int SHM_Uninstall(void)
+{
+       return MODULE_ERR_OK;
+}
+tSHM_Buffer *SHM_CreateBuffer(const char *Name)
+{
+       tSHM_Buffer *ret = calloc(1, sizeof(tSHM_Buffer) + strlen(Name) + 1);
+       MemFS_InitFile(&ret->FileHdr);
+       ret->FileHdr.Name = (const char*)(ret+1);
+       strcpy((char*)ret->FileHdr.Name, Name);
+       ret->Node.ImplPtr = ret;
+       ret->Node.Type = &gSHM_FileNodeType;
+       ret->Node.ReferenceCount = 1;
+       return ret;
+}
+void SHM_DeleteBuffer(tSHM_Buffer *Buffer)
+{
+       ASSERTCR(Buffer->Node.ReferenceCount,==,0,);
+       
+       // TODO: Destroy multi-block nodes
+       ASSERT(Buffer->FirstBlock.Next == NULL);
+       
+       free(Buffer);
+}
+// - Root directory
+int SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
+{
+       return MemFS_ReadDir(&gSHM_RootDir, Id, Dest);
+}
+
+/**
+ * \brief Open a shared memory buffer
+ *
+ * \note Opening 'anon' will always succeed, and will create an anonymous mapping
+ */
+tVFS_Node *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
+{
+       if( strcmp(Filename, "anon") == 0 )
+       {
+               tSHM_Buffer *ret = SHM_CreateBuffer("");
+               return &ret->Node;
+       }
+       
+       tMemFS_FileHdr  *file = MemFS_FindDir(&gSHM_RootDir, Filename);
+       if( !file )
+               return NULL;
+       
+       return &((tSHM_Buffer*)file)->Node;
+}
+
+
+/**
+ * \brief Create a named shared memory file
+ */
+tVFS_Node *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+{
+       if( MemFS_FindDir(&gSHM_RootDir, Name) )
+               return NULL;
+       
+       tSHM_Buffer *ret = SHM_CreateBuffer(Name);
+       if( !MemFS_Insert(&gSHM_RootDir, &ret->FileHdr) )
+       {
+               ret->Node.ReferenceCount = 0;
+               SHM_DeleteBuffer(ret);
+               return NULL;
+       }
+
+       return &ret->Node;
+}
+
+/**
+ * \breif Remove a named shared memory buffer (will be deleted when all references drop)
+ */
+int SHM_Unlink(tVFS_Node *Node, const char *OldName)
+{
+       tMemFS_FileHdr  *file = MemFS_Remove(&gSHM_RootDir, OldName);
+       if( !file )
+               return 1;
+
+       tSHM_Buffer *buf = (tSHM_Buffer*)file;
+       if( buf->Node.ReferenceCount == 0 )
+       {
+               SHM_DeleteBuffer(buf);
+       }
+       else
+       {
+               // dangling references, let them clean themselves up later
+       }
+       return 0;
+}
+// - Buffers
+void SHM_Reference(tVFS_Node *Node)
+{
+       Node->ReferenceCount ++;
+}
+void SHM_Close(tVFS_Node *Node)
+{
+       Node->ReferenceCount --;
+       if( Node->ReferenceCount == 0 )
+       {
+               // TODO: How to tell if a buffer should be deleted here?
+               UNIMPLEMENTED();
+       }
+}
+size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+{
+       UNIMPLEMENTED();
+       return -1;
+}
+size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
+{
+       // TODO: Should first write determine the fixed size of the buffer?
+       UNIMPLEMENTED();
+       return -1;
+}
+int SHM_MMap(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest)
+{
+       UNIMPLEMENTED();
+       return 1;
+}
+
diff --git a/KernelLand/Kernel/include/memfs_helpers.h b/KernelLand/Kernel/include/memfs_helpers.h
new file mode 100644 (file)
index 0000000..c20e170
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * memfs_helpers.h
+ * - Helpers for in-memory filesystems
+ *
+ * Provides name lookup, iteration, and node insertion
+ */
+#ifndef _MEMFS_HELPERS_H_
+#define _MEMFS_HELPERS_H_
+
+#include <vfs.h>
+
+typedef struct sMemFS_FileHdr  tMemFS_FileHdr;
+typedef struct sMemFS_DirHdr   tMemFS_DirHdr;
+
+extern void    MemFS_InitDir (tMemFS_DirHdr  *Dir);
+extern void    MemFS_InitFile(tMemFS_FileHdr *File);
+
+/*
+ * \brief Fetch the name of the file at the specified position
+ * \return standard tVFS_NodeType.ReadDir return values
+ */
+extern int     MemFS_ReadDir(tMemFS_DirHdr *Dir, int Pos, char Name[FILENAME_MAX]);
+/*
+ * \brief Look up a file in a directory
+ */
+extern tMemFS_FileHdr  *MemFS_FindDir(tMemFS_DirHdr *Dir, const char *Name);
+/**
+ * \brief Remove a named file from a directory
+ * \return File header for \a Name, or NULL if not found
+ */
+extern tMemFS_FileHdr  *MemFS_Remove(tMemFS_DirHdr *Dir, const char *Name);
+/**
+ * \brief Insert a pre-constructed file header into the directory
+ * \param Dir  Directory
+ * \return false if name already exists
+ */
+extern bool    MemFS_Insert(tMemFS_DirHdr *Dir, tMemFS_FileHdr *File);
+
+struct sMemFS_FileHdr
+{
+       tMemFS_FileHdr  *Next;
+       const char      *Name;
+};
+
+struct sMemFS_DirHdr
+{
+       tMemFS_FileHdr  FileHdr;
+       //tRWLock       Lock;
+       tMemFS_FileHdr  *FirstChild;
+};
+
+#endif
+
index 2a23031..2a880f6 100644 (file)
 #define SYS_GETCWD     87      // Get current directory
 #define SYS_MOUNT      88      // Mount a filesystem
 #define SYS_SELECT     89      // Wait for file handles
+#define SYS_MARSHALFD  90      // Create a reference to a FD suitable for handing to another process
+#define SYS_UNMARSHALFD        91      // Accept a marshaled FD
 
-#define NUM_SYSCALLS   90
+#define NUM_SYSCALLS   92
 #define SYS_DEBUG      0x100
 #define SYS_DEBUGHEX   0x101
 
@@ -168,6 +170,8 @@ static const char *cSYSCALL_NAMES[] = {
        "SYS_GETCWD",
        "SYS_MOUNT",
        "SYS_SELECT",
+       "SYS_MARSHALFD",
+       "SYS_UNMARSHALFD",
 
        ""
 };
index 748d01d..656526c 100644 (file)
@@ -63,3 +63,5 @@
 %define SYS_GETCWD     87       ;Get current directory
 %define SYS_MOUNT      88       ;Mount a filesystem
 %define SYS_SELECT     89       ;Wait for file handles
+%define SYS_MARSHALFD  90       ;Create a reference to a FD suitable for handing to another process
+%define SYS_UNMARSHALFD        91       ;Accept a marshaled FD
diff --git a/KernelLand/Kernel/memfs_helpers.c b/KernelLand/Kernel/memfs_helpers.c
new file mode 100644 (file)
index 0000000..a7e5fc4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * memfs_helpers.c
+ * - Helpers for in-memory filesystems
+ */
+#include <memfs_helpers.h>
+
+// === CODE ===
+void MemFS_InitDir(tMemFS_DirHdr *Dir)
+{
+       MemFS_InitFile(&Dir->FileHdr);
+}
+void MemFS_InitFile(tMemFS_FileHdr *File)
+{
+       File->Next = NULL;
+}
+
+int MemFS_ReadDir(tMemFS_DirHdr *Dir, int Pos, char Name[FILENAME_MAX])
+{
+        int    i = 0;
+       // TODO: Lock
+       for( tMemFS_FileHdr *file = Dir->FirstChild; file; file = file->Next, i ++ )
+       {
+               if( i == Pos )
+               {
+                       strncpy(Name, file->Name, FILENAME_MAX);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+tMemFS_FileHdr *MemFS_FindDir(tMemFS_DirHdr *Dir, const char *Name)
+{
+       // TODO: Lock
+       for( tMemFS_FileHdr *file = Dir->FirstChild; file; file = file->Next )
+       {
+               if( strcmp(file->Name, Name) == 0 )
+                       return file;
+       }
+       return NULL;
+}
+tMemFS_FileHdr *MemFS_Remove(tMemFS_DirHdr *Dir, const char *Name)
+{
+       UNIMPLEMENTED();
+       return NULL;
+}
+bool MemFS_Insert(tMemFS_DirHdr *Dir, tMemFS_FileHdr *File)
+{
+       UNIMPLEMENTED();
+       return false;
+}
+

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