mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
kernel: pipefs
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include <kernel/keyboard.h>
|
#include <kernel/keyboard.h>
|
||||||
#include <kernel/console.h>
|
#include <kernel/console.h>
|
||||||
#include <kernel/dpc.h>
|
#include <kernel/dpc.h>
|
||||||
|
#include <kernel/pipefs.h>
|
||||||
|
|
||||||
static cpu_t bsp_cpu;
|
static cpu_t bsp_cpu;
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ void kernel_entry() {
|
|||||||
vfs_init();
|
vfs_init();
|
||||||
tmpfs_init();
|
tmpfs_init();
|
||||||
devfs_init();
|
devfs_init();
|
||||||
|
pipefs_init();
|
||||||
printf("mounting tmpfs on /\n");
|
printf("mounting tmpfs on /\n");
|
||||||
__assert(vfs_mount(NULL, vfsroot, "/", "tmpfs", NULL) == 0);
|
__assert(vfs_mount(NULL, vfsroot, "/", "tmpfs", NULL) == 0);
|
||||||
initrd_unpack();
|
initrd_unpack();
|
||||||
|
|||||||
@@ -0,0 +1,264 @@
|
|||||||
|
#include <kernel/vfs.h>
|
||||||
|
#include <kernel/pipefs.h>
|
||||||
|
#include <kernel/slab.h>
|
||||||
|
#include <kernel/alloc.h>
|
||||||
|
#include <kernel/timekeeper.h>
|
||||||
|
#include <kernel/vmm.h>
|
||||||
|
#include <logging.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <kernel/abi.h>
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 16 * PAGE_SIZE
|
||||||
|
|
||||||
|
static scache_t *nodecache;
|
||||||
|
static uintmax_t currentinode;
|
||||||
|
|
||||||
|
static vops_t vnops;
|
||||||
|
|
||||||
|
int pipefs_open(vnode_t **node, int flags, cred_t *cred) {
|
||||||
|
VOP_LOCK(*node);
|
||||||
|
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)(*node);
|
||||||
|
|
||||||
|
if (flags & V_FFLAGS_READ) {
|
||||||
|
++pipenode->readers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & V_FFLAGS_WRITE) {
|
||||||
|
++pipenode->writers;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOP_UNLOCK(*node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_close(vnode_t *node, int flags, cred_t *cred) {
|
||||||
|
VOP_LOCK(node);
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
|
||||||
|
if (flags & V_FFLAGS_READ) {
|
||||||
|
--pipenode->readers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & V_FFLAGS_WRITE) {
|
||||||
|
--pipenode->writers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipenode->readers == 0)
|
||||||
|
event_signal(&pipenode->writeevent);
|
||||||
|
|
||||||
|
if (pipenode->writers == 0)
|
||||||
|
event_signal(&pipenode->readevent);
|
||||||
|
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
VOP_LOCK(node);
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
*readc = 0;
|
||||||
|
size_t datacount = 0;
|
||||||
|
|
||||||
|
// wait until there is data to read or return if nonblock
|
||||||
|
while (datacount == 0) {
|
||||||
|
datacount = RINGBUFFER_DATACOUNT(&pipenode->data);
|
||||||
|
if (datacount == 0) {
|
||||||
|
if (pipenode->writers == 0)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||||
|
error = EAGAIN;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to make it harder for a race condition to happen TODO figure out a way to fix this
|
||||||
|
bool status = interrupt_set(false);
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
|
||||||
|
error = event_wait(&pipenode->writeevent, true);
|
||||||
|
interrupt_set(status);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*readc = ringbuffer_read(&pipenode->data, buffer, size);
|
||||||
|
|
||||||
|
if (*readc < datacount)
|
||||||
|
event_signal(&pipenode->writeevent);
|
||||||
|
|
||||||
|
event_signal(&pipenode->readevent);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
VOP_LOCK(node);
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
*writec = 0;
|
||||||
|
|
||||||
|
// wait until there is space to write data into or return if nonblock
|
||||||
|
size_t datacount = BUFFER_SIZE;
|
||||||
|
while (datacount == BUFFER_SIZE && pipenode->readers) {
|
||||||
|
datacount = RINGBUFFER_DATACOUNT(&pipenode->data);
|
||||||
|
if (datacount == BUFFER_SIZE) {
|
||||||
|
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||||
|
error = EAGAIN;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to make it harder for a race condition to happen TODO figure out a way to fix this
|
||||||
|
bool status = interrupt_set(false);
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
|
||||||
|
error = event_wait(&pipenode->readevent, true);
|
||||||
|
interrupt_set(status);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipenode->readers == 0) {
|
||||||
|
// TODO throw SIGPIPE
|
||||||
|
error = EPIPE;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
*writec = ringbuffer_write(&pipenode->data, buffer, size);
|
||||||
|
|
||||||
|
if (datacount + *writec < BUFFER_SIZE)
|
||||||
|
event_signal(&pipenode->readevent);
|
||||||
|
|
||||||
|
event_signal(&pipenode->writeevent);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_poll(vnode_t *node, int events) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
int revents = 0;
|
||||||
|
VOP_LOCK(node);
|
||||||
|
|
||||||
|
if (events & POLLIN) {
|
||||||
|
if (pipenode->writers == 0)
|
||||||
|
revents |= POLLHUP;
|
||||||
|
else if (RINGBUFFER_DATACOUNT(&pipenode->data) > 0)
|
||||||
|
revents |= POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & POLLOUT) {
|
||||||
|
if (pipenode->readers == 0)
|
||||||
|
revents |= POLLERR;
|
||||||
|
else if (RINGBUFFER_DATACOUNT(&pipenode->data) < BUFFER_SIZE)
|
||||||
|
revents |= POLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
return revents;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_getattr(vnode_t *node, vattr_t *attr, cred_t *cred) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
|
*attr = pipenode->attr;
|
||||||
|
attr->type = node->type;
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_setattr(vnode_t *node, vattr_t *attr, cred_t *cred) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
|
pipenode->attr.gid = attr->gid;
|
||||||
|
pipenode->attr.uid = attr->uid;
|
||||||
|
pipenode->attr.mode = attr->mode;
|
||||||
|
pipenode->attr.atime = attr->atime;
|
||||||
|
pipenode->attr.mtime = attr->mtime;
|
||||||
|
pipenode->attr.ctime = attr->ctime;
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_inactive(vnode_t *node) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
VOP_LOCK(node);
|
||||||
|
ringbuffer_destroy(&pipenode->data);
|
||||||
|
slab_free(nodecache, node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int pipefs_enodev() {
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vops_t vnops = {
|
||||||
|
.create = pipefs_enodev,
|
||||||
|
.open = pipefs_open,
|
||||||
|
.close = pipefs_close,
|
||||||
|
.getattr = pipefs_getattr,
|
||||||
|
.setattr = pipefs_setattr,
|
||||||
|
.lookup = pipefs_enodev,
|
||||||
|
.poll = pipefs_poll,
|
||||||
|
.read = pipefs_read,
|
||||||
|
.write = pipefs_write,
|
||||||
|
.access = pipefs_enodev,
|
||||||
|
.unlink = pipefs_enodev,
|
||||||
|
.link = pipefs_enodev,
|
||||||
|
.symlink = pipefs_enodev,
|
||||||
|
.readlink = pipefs_enodev,
|
||||||
|
.inactive = pipefs_inactive,
|
||||||
|
.mmap = pipefs_enodev,
|
||||||
|
.munmap = pipefs_enodev,
|
||||||
|
.getdents = pipefs_enodev
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ctor(scache_t *cache, void *obj) {
|
||||||
|
pipenode_t *node = obj;
|
||||||
|
memset(node, 0, sizeof(pipenode_t));
|
||||||
|
node->vnode.refcount = 1;
|
||||||
|
SPINLOCK_INIT(node->vnode.lock);
|
||||||
|
node->vnode.ops = &vnops;
|
||||||
|
node->attr.inode = ++currentinode;
|
||||||
|
EVENT_INIT(&node->writeevent);
|
||||||
|
EVENT_INIT(&node->readevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipefs_init() {
|
||||||
|
nodecache = slab_newcache(sizeof(pipenode_t), 0, ctor, ctor);
|
||||||
|
__assert(nodecache);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipefs_newpipe(vnode_t **nodep) {
|
||||||
|
__assert(_cpu()->intstatus);
|
||||||
|
vnode_t *vnode = slab_allocate(nodecache);
|
||||||
|
pipenode_t *node = (pipenode_t *)vnode;
|
||||||
|
if (node == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
int e = ringbuffer_init(&node->data, BUFFER_SIZE);
|
||||||
|
if (e) {
|
||||||
|
VOP_RELEASE(vnode);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nodep = vnode;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _PIPEFS_H
|
||||||
|
#define _PIPEFS_H
|
||||||
|
|
||||||
|
#include <kernel/vfs.h>
|
||||||
|
#include <ringbuffer.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <event.h>
|
||||||
|
|
||||||
|
typedef struct pipenode_t {
|
||||||
|
vnode_t vnode;
|
||||||
|
vattr_t attr;
|
||||||
|
ringbuffer_t data;
|
||||||
|
size_t readers, writers;
|
||||||
|
event_t readevent, writeevent;
|
||||||
|
} pipenode_t;
|
||||||
|
|
||||||
|
void pipefs_init();
|
||||||
|
int pipefs_newpipe(vnode_t **nodep);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -133,10 +133,10 @@ index 0000000..e5b087a
|
|||||||
+
|
+
|
||||||
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..e00428e
|
index 0000000..e76adfd
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
@@ -0,0 +1,235 @@
|
@@ -0,0 +1,246 @@
|
||||||
+#include <bits/ensure.h>
|
+#include <bits/ensure.h>
|
||||||
+#include <mlibc/debug.hpp>
|
+#include <mlibc/debug.hpp>
|
||||||
+#include <mlibc/all-sysdeps.hpp>
|
+#include <mlibc/all-sysdeps.hpp>
|
||||||
@@ -192,6 +192,17 @@ index 0000000..e00428e
|
|||||||
+ return 0;
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ int sys_pipe(int *fds, int flags) {
|
||||||
|
+ long ret = 0;
|
||||||
|
+ long err = syscall(SYSCALL_PIPE2, &ret, flags);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ fds[0] = ret & 0xffffffff;
|
||||||
|
+ fds[1] = (ret >> 32) & 0xffffffff;
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ int sys_chdir(const char *path) {
|
+ int sys_chdir(const char *path) {
|
||||||
+ long ret;
|
+ long ret;
|
||||||
+ return syscall(SYSCALL_CHDIR, &ret, (uint64_t)path);
|
+ return syscall(SYSCALL_CHDIR, &ret, (uint64_t)path);
|
||||||
@@ -391,10 +402,10 @@ index 0000000..990eca0
|
|||||||
+#endif
|
+#endif
|
||||||
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..e768d90
|
index 0000000..e432092
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
@@ -0,0 +1,45 @@
|
@@ -0,0 +1,46 @@
|
||||||
+#ifndef _SYSCALL_H_INCLUDE
|
+#ifndef _SYSCALL_H_INCLUDE
|
||||||
+#define _SYSCALL_H_INCLUDE
|
+#define _SYSCALL_H_INCLUDE
|
||||||
+
|
+
|
||||||
@@ -420,6 +431,7 @@ index 0000000..e768d90
|
|||||||
+#define SYSCALL_DUP3 19
|
+#define SYSCALL_DUP3 19
|
||||||
+#define SYSCALL_FCNTL 20
|
+#define SYSCALL_FCNTL 20
|
||||||
+#define SYSCALL_CHDIR 21
|
+#define SYSCALL_CHDIR 21
|
||||||
|
+#define SYSCALL_PIPE2 22
|
||||||
+
|
+
|
||||||
+#include <stddef.h>
|
+#include <stddef.h>
|
||||||
+#include <stdint.h>
|
+#include <stdint.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user