mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 20:58:22 +00:00
kernel: file_t, fd_t and a few helper functions
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#include <kernel/file.h>
|
||||
#include <kernel/slab.h>
|
||||
#include <kernel/interrupt.h>
|
||||
#include <logging.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/alloc.h>
|
||||
|
||||
// TODO have a limit for the fd table
|
||||
|
||||
static scache_t *filecache;
|
||||
#define FILE_HOLD(f) __atomic_add_fetch(&(f)->refcount, 1, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define FILE_RELEASE(f) \
|
||||
if (__atomic_sub_fetch(&(f)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\
|
||||
cleanfile(f); \
|
||||
}
|
||||
|
||||
static void ctor(scache_t *cache, void *obj) {
|
||||
file_t *file = obj;
|
||||
file->vnode = NULL;
|
||||
MUTEX_INIT(&file->mutex);
|
||||
file->refcount = 1;
|
||||
file->offset = 0;
|
||||
}
|
||||
|
||||
static file_t* newfile() {
|
||||
if (filecache == NULL) {
|
||||
filecache = slab_newcache(sizeof(file_t), 0, ctor, ctor);
|
||||
__assert(filecache);
|
||||
}
|
||||
|
||||
return slab_allocate(filecache);
|
||||
}
|
||||
|
||||
static void cleanfile(file_t *file) {
|
||||
__assert(!"UNIMPLEMENTED");
|
||||
}
|
||||
|
||||
file_t *fd_get(int fd) {
|
||||
proc_t *proc = _cpu()->thread->proc;
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&proc->fdlock);
|
||||
|
||||
file_t *file = fd < proc->fdcount ? proc->fd[fd].file : NULL;
|
||||
if (file)
|
||||
FILE_HOLD(file);
|
||||
|
||||
spinlock_release(&proc->fdlock);
|
||||
interrupt_set(intstatus);
|
||||
|
||||
if (file)
|
||||
MUTEX_ACQUIRE(&file->mutex, false);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void fd_release(file_t *file) {
|
||||
MUTEX_RELEASE(&file->mutex);
|
||||
FILE_RELEASE(file);
|
||||
}
|
||||
|
||||
int fd_new(vnode_t *vnode, int flags, file_t **rfile, int *rfd) {
|
||||
file_t *file = newfile();
|
||||
if (file == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
proc_t *proc = _cpu()->thread->proc;
|
||||
spinlock_acquire(&proc->fdlock);
|
||||
|
||||
// find first free fd
|
||||
int fd = -1;
|
||||
for (fd = proc->fdfirst; fd < proc->fdcount && proc->fd[fd].file; ++fd);
|
||||
|
||||
// resize table if not found
|
||||
if (fd == -1) {
|
||||
void *newtable = realloc(proc->fd, sizeof(fd_t) * (proc->fdcount + 1));
|
||||
if (newtable == NULL) {
|
||||
spinlock_release(&proc->fdlock);
|
||||
cleanfile(file);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
proc->fd = newtable;
|
||||
fd = proc->fdcount;
|
||||
++proc->fdcount;
|
||||
}
|
||||
|
||||
proc->fdfirst = fd + 1;
|
||||
proc->fd[fd].file = file;
|
||||
proc->fd[fd].flags = flags;
|
||||
MUTEX_ACQUIRE(&file->mutex, false);
|
||||
FILE_HOLD(file);
|
||||
|
||||
spinlock_release(&proc->fdlock);
|
||||
|
||||
VOP_HOLD(vnode);
|
||||
file->vnode = vnode;
|
||||
*rfile = file;
|
||||
*rfd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_close(int fd) {
|
||||
proc_t *proc = _cpu()->thread->proc;
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&proc->fdlock);
|
||||
|
||||
file_t *file = fd < proc->fdcount ? proc->fd[fd].file : NULL;
|
||||
if (file) {
|
||||
proc->fd[fd].file = NULL;
|
||||
proc->fdfirst = fd;
|
||||
}
|
||||
|
||||
spinlock_release(&proc->fdlock);
|
||||
interrupt_set(intstatus);
|
||||
|
||||
if (file) {
|
||||
FILE_RELEASE(file);
|
||||
}
|
||||
else {
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
#include <kernel/vfs.h>
|
||||
#include <mutex.h>
|
||||
|
||||
typedef struct file_t {
|
||||
vnode_t *vnode;
|
||||
mutex_t mutex;
|
||||
int refcount;
|
||||
mode_t mode;
|
||||
uintmax_t offset;
|
||||
int flags;
|
||||
} file_t;
|
||||
|
||||
typedef struct fd_t {
|
||||
file_t *file;
|
||||
int flags;
|
||||
} fd_t;
|
||||
|
||||
file_t *fd_get(int fd);
|
||||
void fd_release(file_t *file);
|
||||
int fd_new(vnode_t *node, int flags, file_t **file, int *fd);
|
||||
int fd_close(int fd);
|
||||
int fd_dup(int oldfd, int newfd, bool exact, int flags, int *ret);
|
||||
|
||||
#endif
|
||||
@@ -42,6 +42,10 @@ typedef struct proc_t {
|
||||
thread_t **threads;
|
||||
size_t threadtablesize;
|
||||
size_t runningthreadcount;
|
||||
size_t fdcount;
|
||||
uintmax_t fdfirst;
|
||||
spinlock_t fdlock;
|
||||
struct fd_t *fd;
|
||||
mode_t umask;
|
||||
int flags;
|
||||
vnode_t *cwd;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <kernel/alloc.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/elf.h>
|
||||
#include <kernel/file.h>
|
||||
|
||||
#define QUANTUM_US 100000
|
||||
#define SCHEDULER_STACK_SIZE 4096
|
||||
@@ -39,6 +40,16 @@ proc_t *sched_newproc() {
|
||||
proc->threadtablesize = 1;
|
||||
proc->runningthreadcount = 1;
|
||||
SPINLOCK_INIT(proc->lock);
|
||||
proc->fdcount = 3;
|
||||
proc->fdfirst = 3;
|
||||
SPINLOCK_INIT(proc->fdlock);
|
||||
|
||||
proc->fd = alloc(sizeof(fd_t) * 3);
|
||||
if (proc->fd == NULL) {
|
||||
free(proc->threads);
|
||||
slab_free(processcache, proc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user