mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
basic open/read/write/close syscalls
though it needs a lot of polishing now
This commit is contained in:
@@ -181,7 +181,7 @@ void stress() {
|
||||
|
||||
void templates_tester() {
|
||||
GlobalTtyManager.all_tty_putstr("Testing templates\n");
|
||||
for (int i = 0; i < 2000; i++)
|
||||
for (int i = 0; i < 100; i++)
|
||||
test_templates();
|
||||
GlobalTtyManager.all_tty_putstr("Testing templates OK\n");
|
||||
|
||||
@@ -189,7 +189,7 @@ void templates_tester() {
|
||||
}
|
||||
|
||||
void stress_tester() {
|
||||
for (int i = 0; i < 2000; i++)
|
||||
for (int i = 0; i < 100; i++)
|
||||
new_ktask(stress, "stress");
|
||||
|
||||
GlobalTtyManager.all_tty_putstr("Finished stress\n");
|
||||
|
||||
@@ -9,7 +9,8 @@ _syscall_entrypoint:
|
||||
mov [0x10016], rsp ; TASK_POINTER->ret_sp_val
|
||||
mov [0x10024], r11 ; TASK_POINTER->ret_flags
|
||||
mov rsp, [0x10008] ; TASK_POINTER->entry_ksp_val
|
||||
mov r15, rcx ; This seems like a hack
|
||||
mov r15, rcx ; We need to save rcx
|
||||
mov rcx, rax
|
||||
|
||||
sti
|
||||
; Do very complicated stuff here
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include "gdt.hpp"
|
||||
#include "misc.hpp"
|
||||
|
||||
#include "FDT.hpp"
|
||||
#include "File.hpp"
|
||||
|
||||
// Don't forget the correct order
|
||||
// Shockingly, it doesn't immediately break and even something simple as putchar works
|
||||
// even with completely broken 16-bit segments somehow
|
||||
@@ -60,6 +63,34 @@ uint64_t syscall_readchar() {
|
||||
return tty->readchar();
|
||||
}
|
||||
|
||||
uint64_t syscall_open(const char *pathname, int flags) {
|
||||
FDT::FD res = FDT::current()->open(StrToPath(pathname), static_cast<FileOpts>(flags));
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t syscall_close(uint64_t FD) {
|
||||
FDT::current()->close(FD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t syscall_read(uint64_t fd, char *buf, uint64_t len) {
|
||||
auto f = FDT::current()->get(fd);
|
||||
if (!f) return -1;
|
||||
return f->read(buf, len);
|
||||
}
|
||||
|
||||
uint64_t syscall_write(uint64_t fd, const char *buf, uint64_t len) {
|
||||
auto f = FDT::current()->get(fd);
|
||||
if (!f) return -1;
|
||||
return f->write(buf, len);
|
||||
}
|
||||
|
||||
uint64_t syscall_lseek(uint64_t fd, uint64_t off, uint64_t whence) {
|
||||
auto f = FDT::current()->get(fd);
|
||||
if (!f) return -1;
|
||||
return f->seek(off);
|
||||
}
|
||||
|
||||
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
|
||||
assert2(are_interrupts_enabled(), "why wouldn't they be?");
|
||||
switch (id_rdi) {
|
||||
@@ -70,6 +101,22 @@ extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_r
|
||||
case SYSCALL_READCHAR_ID:
|
||||
assert(a1_rsi == NULL);
|
||||
return syscall_readchar();
|
||||
case SYSCALL_OPEN_ID:
|
||||
return syscall_open(reinterpret_cast<const char *>(a1_rsi), a2_rdx);
|
||||
case SYSCALL_CLOSE_ID:
|
||||
return syscall_close(a1_rsi);
|
||||
case SYSCALL_READ_ID:
|
||||
return syscall_read(a1_rsi, reinterpret_cast<char *>(a2_rdx), a3_rcx);
|
||||
case SYSCALL_WRITE_ID:
|
||||
return syscall_write(a1_rsi, reinterpret_cast<const char *>(a2_rdx), a3_rcx);
|
||||
case SYSCALL_LSEEK_ID:
|
||||
return syscall_lseek(a1_rsi, a2_rdx, a3_rcx);
|
||||
|
||||
case SYSCALL_OPENDIR_ID:
|
||||
case SYSCALL_READDIR_ID:
|
||||
case SYSCALL_CLOSEDIR_ID:
|
||||
case SYSCALL_MKDIR_ID:
|
||||
case SYSCALL_UNLINK_ID:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,19 @@
|
||||
#include "File.hpp"
|
||||
#include "MountTable.hpp"
|
||||
#include "PointersCollection.hpp"
|
||||
#include "VFSApi.hpp"
|
||||
#include "VFSGlobals.hpp"
|
||||
#include "paging.hpp"
|
||||
|
||||
FDT::FD FDT::open(const Path &p, File::OptsT opts) {
|
||||
FDT::FD FDT::open(const Path &p, FileOpts opts) {
|
||||
if (auto n = VFSGlobals::root.traverse(p)) {
|
||||
_files.add(_cur_fd++, UniquePtr<File>(new File(n, opts)));
|
||||
return _cur_fd - 1;
|
||||
}
|
||||
if (opts & FileOpts::O_CREAT) {
|
||||
if (!VFSApi::touch(p)) return -1;
|
||||
return FDT::open(p, static_cast<FileOpts>(opts ^ FileOpts::O_CREAT));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
class FDT {
|
||||
public:
|
||||
using FD = int64_t;
|
||||
FD open(const Path &p, File::OptsT opts);
|
||||
FD open(const Path &p, FileOpts opts);
|
||||
void close(FD fd);
|
||||
File *get(FD fd);
|
||||
|
||||
|
||||
@@ -6,18 +6,19 @@
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
File::File(Node *node, OptsT opts) : _n(node), _opts(opts) {
|
||||
if (opts & (OptsT) Opts::W) assert(opts & (OptsT) Opts::R);
|
||||
if (opts & (OptsT) Opts::W)
|
||||
_n->lock_rw();
|
||||
File::File(Node *node, FileOpts opts) : _n(node), _opts(opts) {
|
||||
if (opts & FileOpts::O_WRONLY)
|
||||
assert(opts & FileOpts::O_RDONLY);
|
||||
if (opts & FileOpts::O_WRONLY)
|
||||
while (!_n->lock_rw()) { yield_self(); }
|
||||
else
|
||||
_n->lock_r();
|
||||
while (!_n->lock_r()) { yield_self(); }
|
||||
}
|
||||
File::~File() {
|
||||
if (_opts & (OptsT) Opts::W)
|
||||
_n->lock_rw();
|
||||
if (_opts & FileOpts::O_WRONLY)
|
||||
_n->unlock_rw();
|
||||
else
|
||||
_n->lock_r();
|
||||
_n->unlock_r();
|
||||
}
|
||||
Node *File::node() {
|
||||
return _n;
|
||||
@@ -42,7 +43,7 @@ uint64_t File::read(char *buf, uint64_t size) {
|
||||
}
|
||||
}
|
||||
uint64_t File::write(const char *buf, uint64_t size) {
|
||||
assert(_opts & (OptsT) Opts::W);
|
||||
if (!(_opts & FileOpts::O_WRONLY)) return -1;
|
||||
if (file()) {
|
||||
file()->write(buf, _pos, size);
|
||||
_pos += size;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef OS2_FILE_HPP
|
||||
#define OS2_FILE_HPP
|
||||
|
||||
#include "FileOpts.h"
|
||||
#include <cstdint>
|
||||
|
||||
class Node;
|
||||
@@ -13,14 +14,7 @@ class NodeFile;
|
||||
|
||||
class File {
|
||||
public:
|
||||
using OptsT = uint8_t;
|
||||
|
||||
enum Opts : uint8_t {
|
||||
R = 1 << 1,// Read
|
||||
W = 1 << 2,// Write
|
||||
};
|
||||
|
||||
File(Node *n, OptsT opts);
|
||||
File(Node *n, FileOpts opts);
|
||||
~File();
|
||||
File(const File &f) = delete;
|
||||
File &operator=(const File &o) = delete;
|
||||
@@ -37,7 +31,7 @@ public:
|
||||
private:
|
||||
Node *_n;
|
||||
uint64_t _pos = 0;
|
||||
OptsT _opts;
|
||||
FileOpts _opts;
|
||||
};
|
||||
|
||||
#endif//OS2_FILE_HPP
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
//FIXME: asserts on read also make sense
|
||||
Vector<Node *> MemFs::MemFsNodeDir::children() {
|
||||
assert(!_rw_lock.test() || _rw_lock.owner() == cur_task());
|
||||
// assert(!_rw_lock.test() || _rw_lock.owner() == cur_task());
|
||||
// assert(_lock.owner() == cur_task());
|
||||
|
||||
Vector<Node *> out;
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
|
||||
Node::~Node() = default;
|
||||
Node *Node::traverse(const Path &path) {
|
||||
lock_r();
|
||||
while (!lock_r()) { yield_self(); }
|
||||
|
||||
NodeDir &nodeDir = static_cast<NodeDir &>(*this);
|
||||
if (nodeDir._mount) return nodeDir._mount->root()->traverse(path);
|
||||
if (path.empty()) return this;
|
||||
if (path.empty()) {
|
||||
unlock_r();
|
||||
return this;
|
||||
}
|
||||
|
||||
if (_type == DIR) {
|
||||
// Horribly inefficient
|
||||
@@ -30,6 +33,7 @@ Node *Node::traverse(const Path &path) {
|
||||
unlock_r();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeDir::set_mounted(Filesystem *mount) {
|
||||
assert(_type == DIR);
|
||||
assert(_mount == nullptr);
|
||||
@@ -38,14 +42,26 @@ void NodeDir::set_mounted(Filesystem *mount) {
|
||||
|
||||
bool Node::lock_r() {
|
||||
LockGuard l(_lock);
|
||||
|
||||
if (_rw_lock.test() && _rw_lock.owner() != cur_task()) return false;
|
||||
_r_lock_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Node::lock_rw() {
|
||||
LockGuard l(_lock);
|
||||
|
||||
if (_rw_lock.test() && _rw_lock.owner() != cur_task()) return false;
|
||||
_rw_lock.lock();
|
||||
|
||||
if (_r_lock_count != 0 && !(_rw_lock.test() && _rw_lock.owner() == cur_task())) return false;
|
||||
|
||||
if (_rw_lock_count == 0) {
|
||||
assert(!_rw_lock.test());
|
||||
_rw_lock.lock();
|
||||
}
|
||||
|
||||
_rw_lock_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
void Node::unlock_r() {
|
||||
@@ -57,5 +73,8 @@ void Node::unlock_r() {
|
||||
void Node::unlock_rw() {
|
||||
LockGuard l(_lock);
|
||||
assert(_rw_lock.test() && _rw_lock.owner() == cur_task());
|
||||
_rw_lock.unlock();
|
||||
assert(_rw_lock_count > 0);
|
||||
_rw_lock_count--;
|
||||
if (_rw_lock_count == 0)
|
||||
_rw_lock.unlock();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ protected:
|
||||
// This is uuugly
|
||||
Mutex _lock;
|
||||
uint64_t _r_lock_count = 0;
|
||||
uint64_t _rw_lock_count = 0;
|
||||
List<Task *> r_lockers;
|
||||
Mutex _rw_lock;
|
||||
|
||||
String _name;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
bool VFSApi::mkdir(const Path &path) {
|
||||
auto root = path.subvector(0, path.size() - 1);
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, File::Opts::W | File::Opts::R));
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||
if (root_fd.get() == -1) return false;
|
||||
File *root_f = FDT::current()->get(root_fd.get());
|
||||
if (!root_f->dir()) return false;
|
||||
@@ -18,7 +18,7 @@ bool VFSApi::mkdir(const Path &path) {
|
||||
}
|
||||
bool VFSApi::touch(const Path &path) {
|
||||
auto root = path.subvector(0, path.size() - 1);
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, File::Opts::W | File::Opts::R));
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||
if (root_fd.get() == -1) return false;
|
||||
File *root_f = FDT::current()->get(root_fd.get());
|
||||
if (!root_f->dir()) return false;
|
||||
@@ -27,7 +27,7 @@ bool VFSApi::touch(const Path &path) {
|
||||
}
|
||||
|
||||
FDT::FD VFSApi::open(const Path &path) {
|
||||
return FDT::current()->open(path, File::Opts::W | File::Opts::R);
|
||||
return FDT::current()->open(path, O_RDWR);
|
||||
}
|
||||
void VFSApi::close(FDT::FD fd) {
|
||||
return FDT::current()->close(fd);
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
#include "syscalls_interface.h"
|
||||
|
||||
|
||||
void _start() {
|
||||
// putchar('h');
|
||||
// putchar('i');
|
||||
// putchar('\n');
|
||||
uint64_t test123 = open("/test123", O_CREAT | O_RDWR);
|
||||
const char *teststr = "test str";
|
||||
write(test123, teststr, 9);
|
||||
close(test123);
|
||||
|
||||
test123 = open("/test123", O_RDONLY);
|
||||
char buf[123];
|
||||
read(test123, buf, 9);
|
||||
|
||||
putchar('\n');
|
||||
for (int i = 0; i < 8; i++) {
|
||||
putchar(buf[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
while (true) {
|
||||
// putchar('h');
|
||||
// putchar('i');
|
||||
|
||||
27
src/uapi/FileOpts.h
Normal file
27
src/uapi/FileOpts.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.03.2024.
|
||||
//
|
||||
|
||||
#ifndef OS2_FILEOPTS_HPP
|
||||
#define OS2_FILEOPTS_HPP
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
enum FileOpts : uint8_t {
|
||||
O_RDONLY = 1 << 1,// Read
|
||||
O_WRONLY = 1 << 2,// Write
|
||||
O_RDWR = O_RDONLY | O_WRONLY,
|
||||
O_CREAT = 1 << 3,// Create
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//OS2_FILEOPTS_HPP
|
||||
26
src/uapi/dirent.h
Normal file
26
src/uapi/dirent.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.03.2024.
|
||||
//
|
||||
|
||||
#ifndef OS2_DIRENT_H
|
||||
#define OS2_DIRENT_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
struct dirent {
|
||||
uint64_t inode_n;
|
||||
char d_name[];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//OS2_DIRENT_H
|
||||
@@ -12,10 +12,25 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "FileOpts.h"
|
||||
|
||||
#define SYSCALL_PUTCHAR_ID 1
|
||||
#define SYSCALL_SLEEP_ID 2
|
||||
#define SYSCALL_READCHAR_ID 3
|
||||
|
||||
#define SYSCALL_OPEN_ID 4
|
||||
#define SYSCALL_CLOSE_ID 5
|
||||
|
||||
#define SYSCALL_READ_ID 6
|
||||
#define SYSCALL_WRITE_ID 7
|
||||
#define SYSCALL_LSEEK_ID 8
|
||||
|
||||
#define SYSCALL_OPENDIR_ID 9
|
||||
#define SYSCALL_READDIR_ID 10
|
||||
#define SYSCALL_CLOSEDIR_ID 11
|
||||
#define SYSCALL_MKDIR_ID 12
|
||||
#define SYSCALL_UNLINK_ID 13
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,24 +5,45 @@
|
||||
#include "syscalls_interface.h"
|
||||
#include "syscalls_defs.h"
|
||||
|
||||
uint64_t do_syscall(uint64_t num, uint64_t a1_rsi) {
|
||||
|
||||
uint64_t do_syscall(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
|
||||
uint64_t res;
|
||||
asm volatile("syscall; mov (0x10016), %%rsp"// TASK_POINTER->ret_sp_val
|
||||
: "=r"(res)
|
||||
: "D"(num), "S"(a1_rsi)
|
||||
: "cc", "rdx", "rcx", "r8",
|
||||
: "D"(id_rdi), "S"(a1_rsi), "d"(a2_rdx), "a"(a3_rcx)
|
||||
: "cc", "rcx", "r8",
|
||||
"r9", "r10", "r11", "r15", "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t readchar() {
|
||||
return do_syscall(SYSCALL_READCHAR_ID, 0);
|
||||
return do_syscall(SYSCALL_READCHAR_ID, 0, 0, 0);
|
||||
}
|
||||
|
||||
uint64_t putchar(char c) {
|
||||
return do_syscall(SYSCALL_PUTCHAR_ID, c);
|
||||
return do_syscall(SYSCALL_PUTCHAR_ID, c, 0, 0);
|
||||
}
|
||||
|
||||
uint64_t sleep(uint64_t micros) {
|
||||
return do_syscall(SYSCALL_SLEEP_ID, micros);
|
||||
return do_syscall(SYSCALL_SLEEP_ID, micros, 0, 0);
|
||||
}
|
||||
|
||||
uint64_t open(const char *pathname, int flags) {
|
||||
return do_syscall(SYSCALL_OPEN_ID, (uint64_t) pathname, flags, 0);
|
||||
}
|
||||
|
||||
uint64_t close(uint64_t FD) {
|
||||
return do_syscall(SYSCALL_CLOSE_ID, FD, 0, 0);
|
||||
}
|
||||
|
||||
uint64_t read(uint64_t fd, char *buf, uint64_t len) {
|
||||
return do_syscall(SYSCALL_READ_ID, fd, (uint64_t) buf, len);
|
||||
}
|
||||
|
||||
uint64_t write(uint64_t fd, const char *buf, uint64_t len) {
|
||||
return do_syscall(SYSCALL_WRITE_ID, fd, (uint64_t) buf, len);
|
||||
}
|
||||
|
||||
uint64_t lseek(uint64_t fd, uint64_t off, uint64_t whence) {
|
||||
return do_syscall(SYSCALL_LSEEK_ID, fd, off, whence);
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef OS2_SYSCALLS_INTERFACE_H
|
||||
#define OS2_SYSCALLS_INTERFACE_H
|
||||
|
||||
#include "dirent.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
@@ -12,10 +14,19 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "FileOpts.h"
|
||||
|
||||
uint64_t putchar(char c);
|
||||
uint64_t readchar();
|
||||
uint64_t sleep(uint64_t micros);
|
||||
|
||||
uint64_t open(const char *pathname, int flags);
|
||||
uint64_t close(uint64_t FD);
|
||||
|
||||
uint64_t read(uint64_t fd, char *buf, uint64_t len);
|
||||
uint64_t write(uint64_t fd, const char *buf, uint64_t len);
|
||||
uint64_t lseek(uint64_t fd, uint64_t off, uint64_t whence);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user