about summary refs log blame commit diff stats
path: root/kernel.soso/sharedmemory.c
blob: 8082d2a4dc1faea39ee2a49a979cbbe7e6fd9775 (plain) (tree)


















                                                                                     
                             





                                     
                               





                                                
                           

                                           
          





                                                    
                                                            


                
                                                                                      





                                    
                                

                                                 
                               














                                                 
                                                                                  



                                  
                                

                                                 
                                               









                                   
                                                         


                
                                             


                                          

                                                               




                                                                         
                                  







                                                       
                                         











                                                              
                                                                                      





                                                                         
                                                            







                                                                                         
                                                       



                                  
                                

                                                 
                                               









                                   

                                                      



























                                                                            
                                            



                                   
                                

                                                 
                                               




                                         
                    














                                                             
#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);
}