about summary refs log tree commit diff stats
path: root/kernel.soso/sharedmemory.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel.soso/sharedmemory.c')
-rw-r--r--kernel.soso/sharedmemory.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/kernel.soso/sharedmemory.c b/kernel.soso/sharedmemory.c
new file mode 100644
index 00000000..8a4e635a
--- /dev/null
+++ b/kernel.soso/sharedmemory.c
@@ -0,0 +1,252 @@
+#include "fs.h"
+#include "common.h"
+#include "list.h"
+#include "alloc.h"
+#include "spinlock.h"
+#include "vmm.h"
+#include "sharedmemory.h"
+
+static List* gShmList = NULL;
+static Spinlock gShmListLock;
+
+static FileSystemNode* gShmRoot = NULL;
+
+static FileSystemDirent gDirent;
+
+static BOOL sharedmemorydir_open(File *file, uint32 flags);
+static FileSystemDirent *sharedmemorydir_readdir(FileSystemNode *node, uint32 index);
+static FileSystemNode *sharedmemorydir_finddir(FileSystemNode *node, char *name);
+
+typedef struct SharedMemory
+{
+    FileSystemNode* node;
+    List* physicalAddressList;
+    Spinlock physicalAddressListLock;
+    //TODO: permissions
+} SharedMemory;
+
+void initializeSharedMemory()
+{
+    Spinlock_Init(&gShmListLock);
+
+    gShmList = List_Create();
+
+    gShmRoot = getFileSystemNode("/system/shm");
+
+    if (NULL == gShmRoot)
+    {
+        WARNING("/system/shm not found!!");
+    }
+    else
+    {
+        gShmRoot->open = sharedmemorydir_open;
+        gShmRoot->finddir = sharedmemorydir_finddir;
+        gShmRoot->readdir = sharedmemorydir_readdir;
+    }
+}
+
+static BOOL sharedmemorydir_open(File *file, uint32 flags)
+{
+    return TRUE;
+}
+
+static FileSystemDirent *sharedmemorydir_readdir(FileSystemNode *node, uint32 index)
+{
+    FileSystemDirent* result = NULL;
+
+    int counter = 0;
+
+    Spinlock_Lock(&gShmListLock);
+
+    List_Foreach (n, gShmList)
+    {
+        SharedMemory* p = (SharedMemory*)n->data;
+
+        if (counter == index)
+        {
+            strcpy(gDirent.name, p->node->name);
+            gDirent.fileType = p->node->nodeType;
+
+            result = &gDirent;
+
+            break;
+        }
+        ++counter;
+    }
+
+    Spinlock_Unlock(&gShmListLock);
+
+    return result;
+}
+
+static FileSystemNode *sharedmemorydir_finddir(FileSystemNode *node, char *name)
+{
+    FileSystemNode* result = NULL;
+
+    Spinlock_Lock(&gShmListLock);
+
+    List_Foreach (n, gShmList)
+    {
+        SharedMemory* p = (SharedMemory*)n->data;
+
+        if (strcmp(name, p->node->name) == 0)
+        {
+            result = p->node;
+            break;
+        }
+    }
+
+    Spinlock_Unlock(&gShmListLock);
+
+    return result;
+}
+
+static BOOL sharedmemory_open(File *file, uint32 flags)
+{
+    return TRUE;
+}
+
+static void sharedmemory_unlink(File *file)
+{
+    destroySharedMemory(file->node->name);
+}
+
+static int32 sharedmemory_ftruncate(File *file, int32 length)
+{
+    if (length <= 0)
+    {
+        return -1;
+    }
+
+    SharedMemory* sharedMem = (SharedMemory*)file->node->privateNodeData;
+
+    if (0 != file->node->length)
+    {
+        //already set
+        return -1;
+    }
+
+    int pageCount = (length / PAGESIZE_4M) + 1;
+
+    Spinlock_Lock(&sharedMem->physicalAddressListLock);
+
+    for (int i = 0; i < pageCount; ++i)
+    {
+        char* pAddress = getPageFrame4M();
+
+        List_Append(sharedMem->physicalAddressList, pAddress);
+    }
+
+    file->node->length = length;
+
+    Spinlock_Unlock(&sharedMem->physicalAddressListLock);
+
+    return 0;
+}
+
+static void* sharedmemory_mmap(File* file, uint32 size, uint32 offset, uint32 flags)
+{
+    void* result = NULL;
+
+    SharedMemory* sharedMem = (SharedMemory*)file->node->privateNodeData;
+
+    Spinlock_Lock(&sharedMem->physicalAddressListLock);
+
+    if (List_GetCount(sharedMem->physicalAddressList) > 0)
+    {
+        result = mapMemory(file->thread->owner, size, 0, sharedMem->physicalAddressList);
+    }
+
+    Spinlock_Unlock(&sharedMem->physicalAddressListLock);
+
+    return result;
+}
+
+FileSystemNode* getSharedMemoryNode(const char* name)
+{
+    FileSystemNode* result = NULL;
+
+    Spinlock_Lock(&gShmListLock);
+
+    List_Foreach (n, gShmList)
+    {
+        SharedMemory* p = (SharedMemory*)n->data;
+
+        if (strcmp(name, p->node->name) == 0)
+        {
+            result = p->node;
+            break;
+        }
+    }
+
+    Spinlock_Unlock(&gShmListLock);
+
+    return result;
+}
+
+FileSystemNode* createSharedMemory(const char* name)
+{
+    if (getSharedMemoryNode(name) != NULL)
+    {
+        return NULL;
+    }
+
+    SharedMemory* sharedMem = (SharedMemory*)kmalloc(sizeof(SharedMemory));
+    memset((uint8*)sharedMem, 0, sizeof(SharedMemory));
+
+    FileSystemNode* node = (FileSystemNode*)kmalloc(sizeof(FileSystemNode));
+    memset((uint8*)node, 0, sizeof(FileSystemNode));
+
+    strcpy(node->name, name);
+    node->nodeType = FT_CharacterDevice;
+    node->open = sharedmemory_open;
+    //TODO: node->shm_unlink = sharedmemory_unlink;
+    node->ftruncate = sharedmemory_ftruncate;
+    node->mmap = sharedmemory_mmap;
+    node->privateNodeData = sharedMem;
+
+    sharedMem->node = node;
+    sharedMem->physicalAddressList = List_Create();
+    Spinlock_Init(&sharedMem->physicalAddressListLock);
+
+    Spinlock_Lock(&gShmListLock);
+    List_Append(gShmList, sharedMem);
+    Spinlock_Unlock(&gShmListLock);
+
+    return node;
+}
+
+void destroySharedMemory(const char* name)
+{
+    SharedMemory* sharedMem = NULL;
+
+    Spinlock_Lock(&gShmListLock);
+
+    List_Foreach (n, gShmList)
+    {
+        SharedMemory* p = (SharedMemory*)n->data;
+
+        if (strcmp(name, p->node->name) == 0)
+        {
+            sharedMem = (SharedMemory*)p;
+            break;
+        }
+    }
+
+    if (sharedMem)
+    {
+        Spinlock_Lock(&sharedMem->physicalAddressListLock);
+
+        kfree(sharedMem->node);
+
+        List_Destroy(sharedMem->physicalAddressList);
+
+        List_RemoveFirstOccurrence(gShmList, sharedMem);
+
+        Spinlock_Unlock(&sharedMem->physicalAddressListLock);
+
+        kfree(sharedMem);
+    }
+
+    Spinlock_Unlock(&gShmListLock);
+}