253 lines
5.4 KiB
C
253 lines
5.4 KiB
C
#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);
|
|
}
|