Kernel: Implement blocking reads

This is a huge step forward!! bc actually runs now, without echo or backspace, but it runs!!
This commit is contained in:
apio 2022-10-21 21:26:19 +02:00
parent 43073cfdbb
commit da61e3648f
9 changed files with 65 additions and 6 deletions

View File

@ -187,12 +187,7 @@ int main()
perror("fread");
return 1;
}
if (feof(stdin))
{
clearerr(stdin);
msleep(20);
continue;
}
if (feof(stdin)) { return 0; }
buffer[nread] = 0;
command_concat(&shell_command, buffer);
}

View File

@ -18,6 +18,7 @@ namespace VFS
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
typedef Node* (*node_finddir)(Node*, const char*);
typedef int (*node_mkdir)(Node*, const char*);
typedef int (*node_block)(Node*);
struct Node
{
@ -30,6 +31,7 @@ namespace VFS
node_finddir find_func;
node_mkdir mkdir_func;
node_write write_func;
node_block block_func;
int tty = 0;
Node* link;
};
@ -39,6 +41,8 @@ namespace VFS
int mkdir(const char* path, const char* name);
int mkdir(const char* pathname);
int would_block(Node* node);
void mount_root(Node* root);
Node* resolve_path(const char* filename, Node* root = nullptr);

View File

@ -7,5 +7,7 @@ namespace KeyboardDevice
ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer);
int would_block(VFS::Node* node);
void append(char c);
}

View File

@ -15,6 +15,7 @@ struct Task
Running,
Sleeping,
Dying,
Blocking,
Exited
};
@ -67,4 +68,15 @@ struct Task
bool has_died();
char name[128];
struct
{
size_t size;
int fd;
char* buf;
} blocking_read_info;
void resume_read();
bool is_still_blocking();
};

View File

@ -9,6 +9,13 @@
static VFS::Node* vfs_root;
int VFS::would_block(Node* node)
{
if (!node) { return 0; }
if (!node->block_func) { return 0; }
return node->block_func(node);
}
ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer)
{
if (!node)

View File

@ -11,10 +11,16 @@
char* kbd_buffer = nullptr;
uint64_t kbd_bufsize = 0;
int KeyboardDevice::would_block(VFS::Node*)
{
return kbd_bufsize == 0;
}
VFS::Node* KeyboardDevice::create_new(const char* devname)
{
VFS::Node* dev = new VFS::Node;
dev->read_func = KeyboardDevice::read;
dev->block_func = KeyboardDevice::would_block;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_DEVICE;

View File

@ -209,6 +209,14 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
context->rax = -EBADF;
return;
}
if (VFS::would_block(current_task->files[fd].node()))
{
current_task->state = current_task->Blocking;
current_task->blocking_read_info.fd = fd;
current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
current_task->blocking_read_info.size = size;
return Scheduler::task_yield(context);
}
ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer));
context->rax = (size_t)result;
return;

View File

@ -392,6 +392,14 @@ void Scheduler::task_yield(Context* context)
Task* original_task = sched_current_task;
do {
sched_current_task = sched_current_task->next_task;
if (sched_current_task->state == sched_current_task->Blocking)
{
if (!sched_current_task->is_still_blocking())
{
sched_current_task->resume_read();
sched_current_task->state = sched_current_task->Running;
}
}
if (sched_current_task->state == sched_current_task->Running)
{
if (sched_current_task->id != original_task->id || was_idle)

View File

@ -1,4 +1,7 @@
#define MODULE "sched"
#include "thread/Task.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "std/string.h"
@ -65,4 +68,18 @@ void Task::switch_to_address_space()
bool Task::has_died()
{
return state == Exited;
}
void Task::resume_read()
{
VMM::switch_back_to_kernel_address_space();
VMM::apply_address_space();
VMM::switch_to_previous_user_address_space();
regs.rax = files[blocking_read_info.fd].read(blocking_read_info.size, blocking_read_info.buf);
VMM::apply_address_space();
}
bool Task::is_still_blocking()
{
return VFS::would_block(files[blocking_read_info.fd].node());
}