From c14013efaa894b480651564dfabd7ef57c74ec51 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Tue, 18 Apr 2023 19:06:25 +0200 Subject: [PATCH] feature (proc): implemented file descriptors --- kernel/inc/proc/file_descriptor.h | 41 +++++++++++ kernel/src/proc/file_descriptor.c | 110 ++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 kernel/inc/proc/file_descriptor.h create mode 100644 kernel/src/proc/file_descriptor.c diff --git a/kernel/inc/proc/file_descriptor.h b/kernel/inc/proc/file_descriptor.h new file mode 100644 index 0000000..578b78e --- /dev/null +++ b/kernel/inc/proc/file_descriptor.h @@ -0,0 +1,41 @@ +// This file is part of noxos and licensed under the MIT open source license + +#ifndef NOX_FILE_DESCRIPTOR_H +#define NOX_FILE_DESCRIPTOR_H + +#include "utils/stdtypes.h" +#include "utils/bitmap.h" +#include "drivers/fs/vfs.h" + +#define FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE 2 + +typedef int32_t file_descriptor_t; + +typedef enum { + FILE_DESCRIPTOR_INVALID = -1 +} std_file_descriptors_E; + +typedef struct file_descriptor_array_chunk_T file_descriptor_array_chunk_T; +struct file_descriptor_array_chunk_T { + file_descriptor_array_chunk_T* prev; + file_descriptor_array_chunk_T* next; + vfs_node_T* lookup [FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE]; + bitmap_T bitmap; + uint32_t amount; +}; + +typedef struct { + file_descriptor_array_chunk_T* base_chunk; +} file_descriptor_array_T; + +file_descriptor_t file_descriptor_request (file_descriptor_array_T* fd_array, vfs_node_T* node); +vfs_node_T* file_descriptor_resolve (file_descriptor_array_T* fd_array, file_descriptor_t fd); +void file_descriptor_free (file_descriptor_array_T* fd_array, file_descriptor_t fd); + +file_descriptor_array_T* file_descriptor_array_alloc (); +void file_descriptor_array_destruct (file_descriptor_array_T* fd_array); + +file_descriptor_array_chunk_T* file_descriptor_array_chunk_alloc (file_descriptor_array_chunk_T* prev); +void file_descriptor_array_chunk_destruct (file_descriptor_array_chunk_T* chunk); + +#endif //NOX_FILE_DESCRIPTOR_H diff --git a/kernel/src/proc/file_descriptor.c b/kernel/src/proc/file_descriptor.c new file mode 100644 index 0000000..d607b76 --- /dev/null +++ b/kernel/src/proc/file_descriptor.c @@ -0,0 +1,110 @@ +// This file is part of noxos and licensed under the MIT open source license + +#include "proc/file_descriptor.h" +#include "utils/memory.h" + + +file_descriptor_t file_descriptor_request(file_descriptor_array_T* fd_array, vfs_node_T* node) { + file_descriptor_t fd = 0; + + file_descriptor_array_chunk_T* chunk = fd_array->base_chunk; + while (chunk->amount == FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE) { + if (chunk->next == NULL) file_descriptor_array_chunk_alloc(chunk); + chunk = chunk->next; + fd +=FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE; + } + + for (int i = 0; i < FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE; i++) { + if (bitmap_get(&chunk->bitmap, i)) continue; + + bitmap_set(&chunk->bitmap, i, true); + chunk->lookup[i] = node; + chunk->amount++; + fd += i; + + return fd; + } + + // this should never happen + return FILE_DESCRIPTOR_INVALID; +} + +vfs_node_T* file_descriptor_resolve(file_descriptor_array_T* fd_array, file_descriptor_t fd) { + if (fd == FILE_DESCRIPTOR_INVALID) return NULL; + + + uint32_t chunk_selector = fd / FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE; + file_descriptor_array_chunk_T* chunk = fd_array->base_chunk; + for (int i = 0; i < chunk_selector; i++) { + chunk = chunk->next; + if (chunk == NULL) return NULL; + } + + uint32_t fd_selector = fd % FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE; + + // Check if the file descriptor exists + if (!bitmap_get(&chunk->bitmap, fd_selector)) return NULL; + + return chunk->lookup[fd_selector]; +} + +void file_descriptor_free(file_descriptor_array_T* fd_array, file_descriptor_t fd) { + if (fd == FILE_DESCRIPTOR_INVALID) return; + + uint32_t chunk_selector = fd / FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE; + file_descriptor_array_chunk_T* chunk = fd_array->base_chunk; + for (int i = 0; i < chunk_selector; i++) { + chunk = chunk->next; + if (chunk == NULL) return; + } + + bitmap_set(&chunk->bitmap, fd % FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE, false); + + chunk->amount--; +} + + +file_descriptor_array_T* file_descriptor_array_alloc() { + file_descriptor_array_T* fd_array = memory_allocate(sizeof(file_descriptor_array_T)); + + fd_array->base_chunk = file_descriptor_array_chunk_alloc(NULL); + + return fd_array; +} + +void file_descriptor_array_destruct(file_descriptor_array_T* fd_array) { + file_descriptor_array_chunk_T* chunk = fd_array->base_chunk; + file_descriptor_array_chunk_T* next_chunk; + + while (chunk != NULL) { + next_chunk = chunk->next; + file_descriptor_array_chunk_destruct(chunk); + chunk = next_chunk; + } + + memory_free(fd_array); +} + + +file_descriptor_array_chunk_T* file_descriptor_array_chunk_alloc(file_descriptor_array_chunk_T* prev) { + file_descriptor_array_chunk_T* chunk = memory_allocate(sizeof(file_descriptor_array_chunk_T)); + + chunk->bitmap = bitmap_init(FILE_DESCRIPTOR_ARRAY_CHUNK_SIZE); + chunk->amount = 0; + chunk->prev = prev; + + if (chunk->prev != NULL) { + chunk->prev->next = chunk; + } + + return chunk; +} + +void file_descriptor_array_chunk_destruct(file_descriptor_array_chunk_T* chunk) { + if (chunk->prev != NULL) { + chunk->prev->next = NULL; + } + + bitmap_destruct(&chunk->bitmap); + memory_free(chunk); +}