From 9fb3c9f3a8eaaacefc5e01718b2c88512a153e75 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 22 Jun 2014 01:36:38 +0800 Subject: [PATCH] Kernel - Start on SHM 'driver' (and common in-memory finddir/readdir) --- KernelLand/Kernel/Makefile | 4 +- KernelLand/Kernel/drv/fifo.c | 115 +++++------- KernelLand/Kernel/drv/shm.c | 204 +++++++++++++++++++++ KernelLand/Kernel/include/memfs_helpers.h | 56 ++++++ KernelLand/Kernel/include/syscalls.h | 6 +- KernelLand/Kernel/include/syscalls.inc.asm | 2 + KernelLand/Kernel/memfs_helpers.c | 54 ++++++ 7 files changed, 368 insertions(+), 73 deletions(-) create mode 100644 KernelLand/Kernel/drv/shm.c create mode 100644 KernelLand/Kernel/include/memfs_helpers.h create mode 100644 KernelLand/Kernel/memfs_helpers.c diff --git a/KernelLand/Kernel/Makefile b/KernelLand/Kernel/Makefile index cc4f2305..93536b8a 100644 --- a/KernelLand/Kernel/Makefile +++ b/KernelLand/Kernel/Makefile @@ -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 diff --git a/KernelLand/Kernel/drv/fifo.c b/KernelLand/Kernel/drv/fifo.c index de3192ab..6d5d4835 100644 --- a/KernelLand/Kernel/drv/fifo.c +++ b/KernelLand/Kernel/drv/fifo.c @@ -10,15 +10,16 @@ #include #include #include +#include // === 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 index 00000000..f825a0ef --- /dev/null +++ b/KernelLand/Kernel/drv/shm.c @@ -0,0 +1,204 @@ +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * drv/shm.c + * - Shared memory "device" + */ +#define DEBUG 0 +#include +#include +#include +#include +#include + +// === 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 index 00000000..c20e1704 --- /dev/null +++ b/KernelLand/Kernel/include/memfs_helpers.h @@ -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 + +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 + diff --git a/KernelLand/Kernel/include/syscalls.h b/KernelLand/Kernel/include/syscalls.h index 2a23031f..2a880f64 100644 --- a/KernelLand/Kernel/include/syscalls.h +++ b/KernelLand/Kernel/include/syscalls.h @@ -71,8 +71,10 @@ #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", "" }; diff --git a/KernelLand/Kernel/include/syscalls.inc.asm b/KernelLand/Kernel/include/syscalls.inc.asm index 748d01da..656526ca 100644 --- a/KernelLand/Kernel/include/syscalls.inc.asm +++ b/KernelLand/Kernel/include/syscalls.inc.asm @@ -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 index 00000000..a7e5fc4a --- /dev/null +++ b/KernelLand/Kernel/memfs_helpers.c @@ -0,0 +1,54 @@ +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * memfs_helpers.c + * - Helpers for in-memory filesystems + */ +#include + +// === 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; +} + -- 2.20.1