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");
|
perror("fread");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (feof(stdin))
|
if (feof(stdin)) { return 0; }
|
||||||
{
|
|
||||||
clearerr(stdin);
|
|
||||||
msleep(20);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
buffer[nread] = 0;
|
buffer[nread] = 0;
|
||||||
command_concat(&shell_command, buffer);
|
command_concat(&shell_command, buffer);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace VFS
|
|||||||
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
|
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
|
||||||
typedef Node* (*node_finddir)(Node*, const char*);
|
typedef Node* (*node_finddir)(Node*, const char*);
|
||||||
typedef int (*node_mkdir)(Node*, const char*);
|
typedef int (*node_mkdir)(Node*, const char*);
|
||||||
|
typedef int (*node_block)(Node*);
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
@ -30,6 +31,7 @@ namespace VFS
|
|||||||
node_finddir find_func;
|
node_finddir find_func;
|
||||||
node_mkdir mkdir_func;
|
node_mkdir mkdir_func;
|
||||||
node_write write_func;
|
node_write write_func;
|
||||||
|
node_block block_func;
|
||||||
int tty = 0;
|
int tty = 0;
|
||||||
Node* link;
|
Node* link;
|
||||||
};
|
};
|
||||||
@ -39,6 +41,8 @@ namespace VFS
|
|||||||
int mkdir(const char* path, const char* name);
|
int mkdir(const char* path, const char* name);
|
||||||
int mkdir(const char* pathname);
|
int mkdir(const char* pathname);
|
||||||
|
|
||||||
|
int would_block(Node* node);
|
||||||
|
|
||||||
void mount_root(Node* root);
|
void mount_root(Node* root);
|
||||||
|
|
||||||
Node* resolve_path(const char* filename, Node* root = nullptr);
|
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);
|
ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer);
|
||||||
|
|
||||||
|
int would_block(VFS::Node* node);
|
||||||
|
|
||||||
void append(char c);
|
void append(char c);
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ struct Task
|
|||||||
Running,
|
Running,
|
||||||
Sleeping,
|
Sleeping,
|
||||||
Dying,
|
Dying,
|
||||||
|
Blocking,
|
||||||
Exited
|
Exited
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,4 +68,15 @@ struct Task
|
|||||||
bool has_died();
|
bool has_died();
|
||||||
|
|
||||||
char name[128];
|
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;
|
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)
|
ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer)
|
||||||
{
|
{
|
||||||
if (!node)
|
if (!node)
|
||||||
|
@ -11,10 +11,16 @@
|
|||||||
char* kbd_buffer = nullptr;
|
char* kbd_buffer = nullptr;
|
||||||
uint64_t kbd_bufsize = 0;
|
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* KeyboardDevice::create_new(const char* devname)
|
||||||
{
|
{
|
||||||
VFS::Node* dev = new VFS::Node;
|
VFS::Node* dev = new VFS::Node;
|
||||||
dev->read_func = KeyboardDevice::read;
|
dev->read_func = KeyboardDevice::read;
|
||||||
|
dev->block_func = KeyboardDevice::would_block;
|
||||||
dev->inode = 0;
|
dev->inode = 0;
|
||||||
dev->length = 0;
|
dev->length = 0;
|
||||||
dev->type = VFS_DEVICE;
|
dev->type = VFS_DEVICE;
|
||||||
|
@ -209,6 +209,14 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
|
|||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
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));
|
ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer));
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
|
@ -392,6 +392,14 @@ void Scheduler::task_yield(Context* context)
|
|||||||
Task* original_task = sched_current_task;
|
Task* original_task = sched_current_task;
|
||||||
do {
|
do {
|
||||||
sched_current_task = sched_current_task->next_task;
|
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->state == sched_current_task->Running)
|
||||||
{
|
{
|
||||||
if (sched_current_task->id != original_task->id || was_idle)
|
if (sched_current_task->id != original_task->id || was_idle)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
#define MODULE "sched"
|
||||||
|
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
|
#include "log/Log.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
@ -65,4 +68,18 @@ void Task::switch_to_address_space()
|
|||||||
bool Task::has_died()
|
bool Task::has_died()
|
||||||
{
|
{
|
||||||
return state == Exited;
|
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