select() syscall for character device reads

This commit is contained in:
Mark
2020-01-17 12:53:56 +02:00
parent 4584b22585
commit c1bd980264
8 changed files with 125 additions and 6 deletions
+8
View File
@@ -2,6 +2,9 @@
#include "sys/types.h"
#include "sys/fs/dirent.h"
#include "sys/stat.h"
#include "sys/select.h"
struct timeval;
ssize_t sys_read(int fd, void *buf, size_t lim);
ssize_t sys_write(int fd, const void *buf, size_t lim);
@@ -20,6 +23,11 @@ int sys_rmdir(const char *pathname);
int sys_stat(const char *filename, struct stat *st);
int sys_access(const char *path, int mode);
// XXX: Except timeout is const, as I don't want to modify it
// No one cares about how much time is remaining once
// select() returns, right?
int sys_select(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, struct timeval *timeout);
// TODO: const struct termios *termp, const struct winsize *winp
int sys_openpty(int *master, int *slave);
+2
View File
@@ -1,8 +1,10 @@
#pragma once
#include "sys/types.h"
#include "sys/ring.h"
struct chrdev {
void *dev_data;
struct ring buffer;
ssize_t (*write) (struct chrdev *chr, const void *buf, size_t pos, size_t lim);
ssize_t (*read) (struct chrdev *chr, void *buf, size_t pos, size_t lim);
+30
View File
@@ -0,0 +1,30 @@
#pragma once
struct timeval;
// 64 bits
typedef long int __fd_mask;
#define __NFDBITS (8 * (int) sizeof(__fd_mask))
// TODO: Guess this should be the same as the maximum
// per-process filedes count
#define __FD_SETSIZE 64
typedef struct {
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
} fd_set;
#define FD_SET(fd, fds) \
(fds)->fds_bits[(fd) / __NFDBITS] |= (1ULL << ((fd) % __NFDBITS))
#define FD_ISSET(fd, fds) \
(!!((fds)->fds_bits[(fd) / __NFDBITS] & (1ULL << ((fd) % __NFDBITS))))
#define FD_ZERO(fds) \
for (int __i = 0; __i < (__FD_SETSIZE / __NFDBITS); ++__i) \
(fds)->fds_bits[__i] = 0
#if !defined(__KERNEL__)
// Implemented by libc
int select(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, struct timeval *tv);
#endif
+1
View File
@@ -7,6 +7,7 @@
#define SYSCALL_NR_STAT 4
#define SYSCALL_NR_LSEEK 8
#define SYSCALL_NR_ACCESS 21
#define SYSCALL_NR_SELECT 23
#define SYSCALL_NR_GETCWD 79
#define SYSCALL_NR_CHDIR 80
#define SYSCALL_NR_MKDIR 83
+2 -1
View File
@@ -14,7 +14,8 @@ KERNEL_HEADERS="include/sys/fcntl.h \
include/sys/time.h \
include/sys/errno.h \
include/sys/signum.h \
include/sys/utsname.h"
include/sys/utsname.h \
include/sys/select.h"
for src_file in $KERNEL_HEADERS; do
dst_file=$INSTALL_HDR$(echo $src_file | sed -e 's/^include//g')
+74
View File
@@ -216,3 +216,77 @@ off_t sys_lseek(int fd, off_t offset, int whence) {
return vfs_lseek(&thr->ioctx, ofile, offset, whence);
}
int sys_select(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, struct timeval *tv) {
struct thread *thr = get_cpu()->thread;
_assert(thr);
// Not implemented yet
_assert(!wr);
_assert(!exc);
// TODO: write fd_set
fd_set _rd;
memcpy(&_rd, rd, sizeof(fd_set));
FD_ZERO(rd);
if (!rd) {
return 0;
}
// Check file descriptors
for (int i = 0; i < nfds; ++i) {
if (FD_ISSET(i, &_rd)) {
if (i > THREAD_MAX_FDS) {
kwarn("Bad FD: %d\n", i);
return -EBADF;
}
struct ofile *fd = thr->fds[i];
if (!fd) {
kwarn("Bad FD: %d\n", i);
return -EBADF;
}
_assert(fd->vnode);
if (fd->vnode->type != VN_CHR) {
// select() does not make sense for non-char devices yet
FD_SET(i, rd);
return 0;
}
}
}
uint64_t deadline = tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL + system_time;
int res;
while (1) {
// Check for any ready FD
for (int i = 0; i < nfds; ++i) {
if (FD_ISSET(i, &_rd)) {
struct ofile *fd = thr->fds[i];
_assert(fd && fd->vnode && fd->vnode->type == VN_CHR);
struct chrdev *chr = fd->vnode->dev;
_assert(chr);
if (ring_avail(&chr->buffer) > 0) {
FD_SET(i, rd);
res = 0;
goto done;
}
}
}
// Check timer deadline
if (system_time >= deadline) {
res = 0;
goto done;
}
// Yield
asm volatile ("sti; hlt; cli");
}
done:
return res;
}
+1
View File
@@ -18,6 +18,7 @@ const void *amd64_syscall_jmp_table[256] = {
[SYSCALL_NR_OPEN] = sys_open,
[SYSCALL_NR_CLOSE] = sys_close,
[SYSCALL_NR_LSEEK] = sys_lseek,
[SYSCALL_NR_SELECT] = sys_select,
[SYSCALL_NR_GETCWD] = sys_getcwd,
[SYSCALL_NR_CHDIR] = sys_chdir,
[SYSCALL_NR_STAT] = sys_stat,
+7 -5
View File
@@ -23,15 +23,17 @@ static struct chrdev _dev_tty0 = {
.read = tty_read
};
static struct ring tty_ring = {0};
// This function receives keystrokes from keyboard drivers
void tty_buffer_write(int tty_no, char c) {
ring_putc(NULL, &tty_ring, c);
switch (tty_no) {
case 0:
ring_putc(NULL, &_dev_tty0.buffer, c);
break;
}
}
void tty_init(void) {
ring_init(&tty_ring, 16);
ring_init(&_dev_tty0.buffer, 16);
dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_tty0, "tty0");
}
@@ -67,7 +69,7 @@ static ssize_t tty_read(struct chrdev *tty, void *buf, size_t pos, size_t lim) {
size_t p = 0;
while (rem) {
ssize_t rd = ring_read(get_cpu()->thread, &tty_ring, ibuf, MIN(16, rem));
ssize_t rd = ring_read(get_cpu()->thread, &tty->buffer, ibuf, MIN(16, rem));
if (rd < 0) {
break;
}