about summary refs log tree commit diff stats
path: root/tools/iso/kernel.soso/pipe.c
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-01-01 18:22:19 -0800
committerKartik Agaram <vc@akkartik.com>2020-01-01 18:42:48 -0800
commit65409d2312e702a48d3cf5b32479d25266bda3c3 (patch)
tree62a7262fce61f2302109246da4536ce6f8e9ef80 /tools/iso/kernel.soso/pipe.c
parenta6da50ad30d2e1825575ffef497ab450a8f26e94 (diff)
downloadmu-65409d2312e702a48d3cf5b32479d25266bda3c3.tar.gz
5858
Move script to create a Soso boot image into a sub-directory.

I'm trying to streamline newcomer attention to just a couple of use cases.
Diffstat (limited to 'tools/iso/kernel.soso/pipe.c')
-rw-r--r--tools/iso/kernel.soso/pipe.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/tools/iso/kernel.soso/pipe.c b/tools/iso/kernel.soso/pipe.c
new file mode 100644
index 00000000..7141305c
--- /dev/null
+++ b/tools/iso/kernel.soso/pipe.c
@@ -0,0 +1,224 @@
+#include "list.h"
+#include "pipe.h"
+#include "fs.h"
+#include "alloc.h"
+#include "fifobuffer.h"
+
+static List* gPipeList = NULL;
+
+static FileSystemNode* gPipesRoot = NULL;
+
+static FileSystemDirent gDirent;
+
+typedef struct Pipe {
+    char name[32];
+    FifoBuffer* buffer;
+    FileSystemNode* fsNode;
+    List* accessingThreads;
+} Pipe;
+
+static BOOL pipes_open(File *file, uint32 flags);
+static FileSystemDirent *pipes_readdir(FileSystemNode *node, uint32 index);
+static FileSystemNode *pipes_finddir(FileSystemNode *node, char *name);
+
+void initializePipes() {
+    gPipeList = List_Create();
+
+    gPipesRoot = getFileSystemNode("/system/pipes");
+
+    if (NULL == gPipesRoot) {
+        WARNING("/system/pipes not found!!");
+    }
+    else {
+        gPipesRoot->open = pipes_open;
+        gPipesRoot->finddir = pipes_finddir;
+        gPipesRoot->readdir = pipes_readdir;
+    }
+}
+
+static BOOL pipes_open(File *file, uint32 flags) {
+    return TRUE;
+}
+
+static FileSystemDirent *pipes_readdir(FileSystemNode *node, uint32 index) {
+    int counter = 0;
+
+    List_Foreach (n, gPipeList) {
+        Pipe* p = (Pipe*)n->data;
+
+        if (counter == index) {
+            strcpy(gDirent.name, p->name);
+            gDirent.fileType = FT_Pipe;
+
+            return &gDirent;
+        }
+        ++counter;
+    }
+
+    return NULL;
+}
+
+static FileSystemNode *pipes_finddir(FileSystemNode *node, char *name) {
+    List_Foreach (n, gPipeList) {
+        Pipe* p = (Pipe*)n->data;
+
+        if (strcmp(name, p->name) == 0) {
+            return p->fsNode;
+        }
+    }
+
+    return NULL;
+}
+
+static BOOL pipe_open(File *file, uint32 flags) {
+    beginCriticalSection();
+
+    Pipe* pipe = file->node->privateNodeData;
+
+    List_Append(pipe->accessingThreads, file->thread);
+
+    endCriticalSection();
+
+    return TRUE;
+}
+
+static void pipe_close(File *file) {
+    beginCriticalSection();
+
+    Pipe* pipe = file->node->privateNodeData;
+
+    List_RemoveFirstOccurrence(pipe->accessingThreads, file->thread);
+
+    endCriticalSection();
+}
+
+static void blockAccessingThreads(Pipe* pipe) {
+    disableInterrupts();
+
+    List_Foreach (n, pipe->accessingThreads) {
+        Thread* reader = n->data;
+
+        reader->state = TS_WAITIO;
+
+        reader->state_privateData = pipe;
+    }
+
+    enableInterrupts();
+
+    halt();
+}
+
+static void wakeupAccessingThreads(Pipe* pipe) {
+    beginCriticalSection();
+
+    List_Foreach (n, pipe->accessingThreads) {
+        Thread* reader = n->data;
+
+        if (reader->state == TS_WAITIO) {
+            if (reader->state_privateData == pipe) {
+                reader->state = TS_RUN;
+            }
+        }
+    }
+
+    endCriticalSection();
+}
+
+static int32 pipe_read(File *file, uint32 size, uint8 *buffer) {
+    if (0 == size || NULL == buffer) {
+        return -1;
+    }
+
+    Pipe* pipe = file->node->privateNodeData;
+
+    uint32 used = 0;
+    while ((used = FifoBuffer_getSize(pipe->buffer)) < size) {
+        blockAccessingThreads(pipe);
+    }
+
+    disableInterrupts();
+
+    int32 readBytes = FifoBuffer_dequeue(pipe->buffer, buffer, size);
+
+    wakeupAccessingThreads(pipe);
+
+    return readBytes;
+}
+
+static int32 pipe_write(File *file, uint32 size, uint8 *buffer) {
+    if (0 == size || NULL == buffer) {
+        return -1;
+    }
+
+    Pipe* pipe = file->node->privateNodeData;
+
+    uint32 free = 0;
+    while ((free = FifoBuffer_getFree(pipe->buffer)) < size) {
+        blockAccessingThreads(pipe);
+    }
+
+    disableInterrupts();
+
+    int32 bytesWritten = FifoBuffer_enqueue(pipe->buffer, buffer, size);
+
+    wakeupAccessingThreads(pipe);
+
+    return bytesWritten;
+}
+
+BOOL createPipe(const char* name, uint32 bufferSize) {
+    List_Foreach (n, gPipeList) {
+        Pipe* p = (Pipe*)n->data;
+        if (strcmp(name, p->name) == 0) {
+            return FALSE;
+        }
+    }
+
+    Pipe* pipe = (Pipe*)kmalloc(sizeof(Pipe));
+    memset((uint8*)pipe, 0, sizeof(Pipe));
+
+    strcpy(pipe->name, name);
+    pipe->buffer = FifoBuffer_create(bufferSize);
+
+    pipe->accessingThreads = List_Create();
+
+    pipe->fsNode = (FileSystemNode*)kmalloc(sizeof(FileSystemNode));
+    memset((uint8*)pipe->fsNode, 0, sizeof(FileSystemNode));
+    pipe->fsNode->privateNodeData = pipe;
+    pipe->fsNode->open = pipe_open;
+    pipe->fsNode->close = pipe_close;
+    pipe->fsNode->read = pipe_read;
+    pipe->fsNode->write = pipe_write;
+
+    List_Append(gPipeList, pipe);
+
+    return TRUE;
+}
+
+BOOL destroyPipe(const char* name) {
+    List_Foreach (n, gPipeList) {
+        Pipe* p = (Pipe*)n->data;
+        if (strcmp(name, p->name) == 0) {
+            List_RemoveFirstOccurrence(gPipeList, p);
+            FifoBuffer_destroy(p->buffer);
+            List_Destroy(p->accessingThreads);
+            kfree(p->fsNode);
+            kfree(p);
+
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+BOOL existsPipe(const char* name) {
+    List_Foreach (n, gPipeList) {
+        Pipe* p = (Pipe*)n->data;
+        if (strcmp(name, p->name) == 0) {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}