diff options
Diffstat (limited to 'tools/iso/kernel.soso/sharedmemory.c')
-rw-r--r-- | tools/iso/kernel.soso/sharedmemory.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/tools/iso/kernel.soso/sharedmemory.c b/tools/iso/kernel.soso/sharedmemory.c new file mode 100644 index 00000000..8082d2a4 --- /dev/null +++ b/tools/iso/kernel.soso/sharedmemory.c @@ -0,0 +1,224 @@ +#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); +} |