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:
parent
43073cfdbb
commit
da61e3648f
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
@ -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();
|
||||
};
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user