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
#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;
// === 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,
.NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
};
-tPipe *gFIFO_NamedPipes = NULL;
// === CODE ===
/**
*/
int FIFO_Install(char **Options)
{
+ MemFS_InitDir( &gFIFO_RootDir );
DevFS_AddDevice( &gFIFO_DriverInfo );
return MODULE_ERR_OK;
}
*/
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);
}
/**
*/
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 )
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;
}
/**
*/
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;
}
*/
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
*/
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;
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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
+
#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
"SYS_GETCWD",
"SYS_MOUNT",
"SYS_SELECT",
+ "SYS_MARSHALFD",
+ "SYS_UNMARSHALFD",
""
};
%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
--- /dev/null
+/*
+ * 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;
+}
+