Kernel, libc: Implement O_NONBLOCK

This commit is contained in:
apio 2022-10-21 21:51:03 +02:00
parent da61e3648f
commit b2f5a0502f
9 changed files with 68 additions and 13 deletions

View File

@ -1,4 +1,4 @@
APPS := init sym sh crash uname uptime hello APPS := init sym sh crash uname uptime hello block
APPS_DIR := $(LUNA_ROOT)/apps APPS_DIR := $(LUNA_ROOT)/apps
APPS_SRC := $(APPS_DIR)/src APPS_SRC := $(APPS_DIR)/src

34
apps/src/block.c Normal file
View File

@ -0,0 +1,34 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/kbd", O_RDONLY | O_NONBLOCK);
if (fd < 0)
{
perror("open");
return 1;
}
FILE* fp = fdopen(fd, "r");
if (!fp)
{
perror("fdopen");
close(fd);
return 1;
}
char buf[32];
fread(buf, sizeof(buf) - 1, 1, fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
return 1;
}
fclose(fp);
return 0;
}

View File

@ -32,7 +32,7 @@ struct Descriptor
ssize_t read(size_t size, char* buffer); ssize_t read(size_t size, char* buffer);
ssize_t write(size_t size, const char* buffer); ssize_t write(size_t size, const char* buffer);
void open(VFS::Node* node, bool can_read, bool can_write); void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block);
int seek(long offset); int seek(long offset);
long offset() long offset()
@ -45,6 +45,11 @@ struct Descriptor
return m_node->length; return m_node->length;
} }
bool able_to_block()
{
return m_able_to_block;
}
Descriptor(const Descriptor& other); Descriptor(const Descriptor& other);
Descriptor(); Descriptor();
@ -54,6 +59,7 @@ struct Descriptor
bool m_is_open; bool m_is_open;
bool m_can_read; bool m_can_read;
bool m_can_write; bool m_can_write;
bool m_able_to_block;
VFS::Node* m_node; VFS::Node* m_node;
uint64_t m_offset; uint64_t m_offset;
}; };

View File

@ -6,6 +6,7 @@
#define EINTR 4 #define EINTR 4
#define ENOEXEC 8 #define ENOEXEC 8
#define EBADF 9 #define EBADF 9
#define EAGAIN 11
#define ENOMEM 12 #define ENOMEM 12
#define EFAULT 14 #define EFAULT 14
#define EEXIST 17 #define EEXIST 17

View File

@ -6,15 +6,16 @@ Descriptor::Descriptor() : m_is_open(false)
} }
Descriptor::Descriptor(const Descriptor& other) Descriptor::Descriptor(const Descriptor& other)
: m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), m_node(other.m_node), : m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write),
m_offset(other.m_offset) m_able_to_block(other.m_able_to_block), m_node(other.m_node), m_offset(other.m_offset)
{ {
} }
void Descriptor::open(VFS::Node* node, bool can_read, bool can_write) void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block)
{ {
m_can_read = can_read; m_can_read = can_read;
m_can_write = can_write; m_can_write = can_write;
m_able_to_block = able_to_block;
m_node = node; m_node = node;
m_offset = 0; m_offset = 0;
m_is_open = true; m_is_open = true;
@ -49,5 +50,6 @@ const Descriptor& Descriptor::operator=(const Descriptor& other)
m_can_write = other.m_can_write; m_can_write = other.m_can_write;
m_offset = other.m_offset; m_offset = other.m_offset;
m_node = other.m_node; m_node = other.m_node;
m_able_to_block = other.m_able_to_block;
return other; return other;
} }

View File

@ -14,6 +14,7 @@
#define OPEN_READ 1 #define OPEN_READ 1
#define OPEN_WRITE 2 #define OPEN_WRITE 2
#define OPEN_NONBLOCK 4
#define SEEK_SET 0 #define SEEK_SET 0
#define SEEK_CUR 1 #define SEEK_CUR 1
@ -155,17 +156,17 @@ void sys_open(Context* context, const char* filename, int flags)
return; return;
} }
char* kernel_filename = strdup_from_user(filename); char* kfilename = strdup_from_user(filename);
if (!kernel_filename) if (!kfilename)
{ {
context->rax = -EFAULT; context->rax = -EFAULT;
return; return;
} }
VFS::Node* node = VFS::resolve_path(kernel_filename); VFS::Node* node = VFS::resolve_path(kfilename);
if (!node) if (!node)
{ {
kfree(kernel_filename); kfree(kfilename);
context->rax = -ENOENT; context->rax = -ENOENT;
return; return;
} }
@ -174,19 +175,21 @@ void sys_open(Context* context, const char* filename, int flags)
bool can_write = (flags & OPEN_WRITE) > 0; bool can_write = (flags & OPEN_WRITE) > 0;
if (!can_read && !can_write) if (!can_read && !can_write)
{ {
kfree(kernel_filename); kfree(kfilename);
context->rax = -EINVAL; context->rax = -EINVAL;
return; return;
} }
kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename, bool able_to_block = (flags & OPEN_NONBLOCK) == 0;
kdbgln("open(): opening %s %s, allocated file descriptor %d", kfilename,
(can_read && can_write) ? "rw" (can_read && can_write) ? "rw"
: can_read ? "r-" : can_read ? "r-"
: "-w", : "-w",
fd); fd);
kfree(kernel_filename); kfree(kfilename);
current_task->files[fd].open(node, can_read, can_write); current_task->files[fd].open(node, can_read, can_write, able_to_block);
context->rax = fd; context->rax = fd;
return; return;
} }
@ -211,6 +214,11 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
} }
if (VFS::would_block(current_task->files[fd].node())) if (VFS::would_block(current_task->files[fd].node()))
{ {
if (!current_task->files[fd].able_to_block())
{
context->rax = -EAGAIN;
return;
}
current_task->state = current_task->Blocking; current_task->state = current_task->Blocking;
current_task->blocking_read_info.fd = fd; 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.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.

View File

@ -10,6 +10,7 @@ extern int errno;
#define EINTR 4 // Interrupted system call. Not implemented. #define EINTR 4 // Interrupted system call. Not implemented.
#define ENOEXEC 8 // Exec format error #define ENOEXEC 8 // Exec format error
#define EBADF 9 // Bad file descriptor #define EBADF 9 // Bad file descriptor
#define EAGAIN 11 // Resource temporarily unavailable
#define ENOMEM 12 // Cannot allocate memory #define ENOMEM 12 // Cannot allocate memory
#define EFAULT 14 // Bad address #define EFAULT 14 // Bad address
#define EEXIST 17 // File exists #define EEXIST 17 // File exists

View File

@ -7,6 +7,8 @@
#define O_WRONLY 2 #define O_WRONLY 2
/* Open for reading and writing. */ /* Open for reading and writing. */
#define O_RDWR 3 #define O_RDWR 3
/* Open without blocking. */
#define O_NONBLOCK 4
/* Duplicate a file descriptor. */ /* Duplicate a file descriptor. */
#define F_DUPFD 0 #define F_DUPFD 0

View File

@ -207,6 +207,7 @@ extern "C"
case ENOSPC: return "No space left on device"; case ENOSPC: return "No space left on device";
case ENOTSUP: return "Operation not supported"; case ENOTSUP: return "Operation not supported";
case EPIPE: return "Broken pipe"; case EPIPE: return "Broken pipe";
case EAGAIN: return "Resource temporarily unavailable";
case 0: return "Success"; case 0: return "Success";
default: return "Unknown error"; default: return "Unknown error";
} }