Scheduler optimization, console optimization (still slow as hell)

This commit is contained in:
Mark
2020-01-04 15:29:44 +02:00
parent b8c4917745
commit c5875c4639
24 changed files with 206 additions and 73 deletions
+2 -1
View File
@@ -118,8 +118,9 @@ endif
QEMU_OPTS?=-m $(QEMU_MEM) \
-chardev stdio,nowait,id=char0,mux=on \
-serial chardev:char0 -mon chardev=char0 \
--accel tcg,thread=multi \
-M $(QEMU_CHIPSET) \
-cpu host \
-enable-kvm \
-boot d \
$(QEMU_DEVS) \
-smp $(QEMU_SMP)
+11
View File
@@ -1,5 +1,16 @@
#pragma once
#include "sys/types.h"
struct rtc_time {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint16_t year;
};
void rtc_read(struct rtc_time *time);
void rtc_set_century(uint8_t c);
void rtc_init(void);
+3
View File
@@ -2,5 +2,8 @@
struct cpu_context;
extern uint64_t syscall_last_time;
extern uint64_t syscall_count;
void amd64_syscall_init(void);
extern void amd64_syscall_iretq(struct cpu_context *ctx);
+6 -6
View File
@@ -16,12 +16,12 @@
#define DEBUG_OUT_SERIAL 0
#define DEBUG_OUT_DISP 1
#define kdebug(f, ...) debugf(DEBUG_DEFAULT, "[%s] " f, __func__, ##__VA_ARGS__)
#define kinfo(f, ...) debugf(DEBUG_INFO, "[%s] " f, __func__, ##__VA_ARGS__)
#define kwarn(f, ...) debugf(DEBUG_WARN, "[%s] " f, __func__, ##__VA_ARGS__)
#define kerror(f, ...) debugf(DEBUG_ERROR, "[%s] " f, __func__, ##__VA_ARGS__)
#define kfatal(f, ...) debugf(DEBUG_FATAL, "[%s] " f, __func__, ##__VA_ARGS__)
#define kprint(l, f, ...) debugf(l, "[%s] " f, __func__, ##__VA_ARGS__)
#define kdebug(f, ...) debugf(DEBUG_DEFAULT, "[%s] " f, __func__, ##__VA_ARGS__)
#define kinfo(f, ...) debugf(DEBUG_INFO, "[%s] " f, __func__, ##__VA_ARGS__)
#define kwarn(f, ...) debugf(DEBUG_WARN, "[%s] " f, __func__, ##__VA_ARGS__)
#define kerror(f, ...) debugf(DEBUG_ERROR, "[%s] " f, __func__, ##__VA_ARGS__)
#define kfatal(f, ...) debugf(DEBUG_FATAL, "[%s] " f, __func__, ##__VA_ARGS__)
#define kprint(l, f, ...) debugf(l, "[%s] " f, __func__, ##__VA_ARGS__)
void fmtsiz(char *buf, size_t sz);
+1 -1
View File
@@ -14,5 +14,5 @@ struct ring {
size_t ring_avail(struct ring *b);
ssize_t ring_read(struct thread *ctx, struct ring *b, void *buf, size_t lim);
int ring_putc(struct ring *b, char c);
int ring_putc(struct thread *ctx, struct ring *b, char c);
void ring_init(struct ring *b, size_t cap);
+2
View File
@@ -9,10 +9,12 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
void *memcpy(void *restrict dst, const void *restrict src, size_t cnt);
uint64_t *memcpyq(uint64_t *restrict dst, const uint64_t *restrict src, size_t cnt);
void *memmove(void *dst, const void *src, size_t cnt);
void *memset(void *dst, int v, size_t count);
uint16_t *memsetw(uint16_t *dst, uint16_t v, size_t count);
uint32_t *memsetl(uint32_t *dst, uint32_t v, size_t count);
uint64_t *memsetq(uint64_t *dst, uint64_t v, size_t count);
int memcmp(const void *a, const void *b, size_t count);
size_t strlen(const char *s);
+12 -12
View File
@@ -19,7 +19,7 @@
#define ESC_CSI 2
#define CGA_BUFFER_ADDR 0xB8000
#define ATTR_DEFAULT 0x1700
#define ATTR_DEFAULT 0x1700ULL
static uint16_t *con_buffer;
static uint16_t x = 0, y = 0;
@@ -57,8 +57,8 @@ static uint16_t attr = ATTR_DEFAULT;
static void setc(uint16_t row, uint16_t col, uint16_t v);
void con_blink(void) {
#if defined(VESA_ENABLE)
void con_blink(void) {
if (vesa_available) {
uint32_t fg = rgb_map[(attr >> 8) & 0xF];
uint32_t bg = rgb_map[(attr >> 12) & 0xF];
@@ -70,8 +70,8 @@ void con_blink(void) {
psf_draw(y, x, ' ', fg, bg);
}
}
#endif
}
#endif
static void amd64_con_moveto(uint8_t row, uint8_t col) {
if (!vesa_available) {
@@ -85,11 +85,7 @@ static void amd64_con_moveto(uint8_t row, uint8_t col) {
}
static void amd64_scroll_down(void) {
for (int i = 0; i < con_height - 1; ++i) {
memcpy(&con_buffer[i * con_width], &con_buffer[(i + 1) * con_width], con_width * 2);
}
memsetw(&con_buffer[(con_height - 1) * con_width], ATTR_DEFAULT, con_width);
y = con_height - 1;
#if defined(VESA_ENABLE)
if (vesa_available) {
for (uint16_t row = 0; row < con_height; ++row) {
for (uint16_t col = 0; col < con_width; ++col) {
@@ -98,6 +94,12 @@ static void amd64_scroll_down(void) {
}
}
}
#else
memcpyq((uint64_t *) con_buffer, (uint64_t *) &con_buffer[con_width], 20 * 24);
memsetq((uint64_t *) &con_buffer[(con_height - 1) * con_width],
ATTR_DEFAULT | (ATTR_DEFAULT << 16) | (ATTR_DEFAULT << 32) | (ATTR_DEFAULT << 48), 20);
y = con_height - 1;
#endif
}
static void clear(void) {
@@ -112,10 +114,6 @@ static void clear(void) {
#endif
}
//static void clear_line(uint16_t row) {
//
//}
// I guess I could've implemented VT100 escape handling better, but
// this is all I invented so far
static void process_csi(void) {
@@ -257,6 +255,8 @@ void amd64_con_putc(int c) {
return;
}
c = (uint8_t) (c & 0xFF);
switch (esc_mode) {
case ESC_CSI:
if (c >= '0' && c <= '9') {
-1
View File
@@ -46,7 +46,6 @@ amd64_irq0:
movq %rax, 4(%rdi)
1:
// Assume we're now on TASK2's stack
// EOI
irq_eoi_lapic 0
+3 -2
View File
@@ -13,6 +13,7 @@ static void pci_ide_init(pci_addr_t addr) {
uint32_t irq_config = pci_config_read_dword(addr, PCI_CONFIG_IRQ);
uint32_t class = pci_config_read_dword(addr, PCI_CONFIG_CLASS);
uint8_t prog_if = (class >> 8) & 0xFF;
uint32_t bar;
uint32_t cmd = pci_config_read_dword(addr, PCI_CONFIG_CMD);
@@ -83,10 +84,10 @@ static void pci_ide_init(pci_addr_t addr) {
} else {
// The device either does not use IRQs or is a
// paraller IDE with IRQs 14 and 15
uint8_t prog_if = (class >> 8) & 0xFF;
if (prog_if == 0x80 || prog_if == 0x8A) {
// TODO: handle this case
panic("This is a parallel IDE controller\n");
//panic("This is a parallel IDE controller\n");
return;
} else {
// TODO: handle this case
panic("The device has no IRQs\n");
+6 -2
View File
@@ -1,6 +1,7 @@
#include "sys/amd64/hw/rs232.h"
#include "sys/amd64/hw/irq.h"
#include "sys/amd64/hw/io.h"
#include "sys/tty.h"
#include "sys/debug.h"
#define RS232_DTR 0
@@ -41,8 +42,11 @@ static uint32_t rs232_irq(void *ctx) {
has_data = 1;
uint8_t c = inb(port);
// Act as echo for now
rs232_send(port, c);
if (c == '\r') {
c = '\n';
}
tty_buffer_write(0, c);
}
return has_data ? IRQ_HANDLED : IRQ_UNHANDLED;
+1 -11
View File
@@ -26,16 +26,6 @@
#define FROMBCD(bcd) ((((bcd) / 16) * 10) + \
((bcd & 0xF)))
struct rtc_time {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint16_t year;
};
// [s]Please change this in Y3K[/s]I hope x86 dies by 3000
static uint8_t rtc_century = 20;
@@ -60,7 +50,7 @@ static inline uint8_t cmos_read_time(uint8_t reg, uint8_t reg_b) {
}
}
static void rtc_read(struct rtc_time *time) {
void rtc_read(struct rtc_time *time) {
uint8_t reg_b = cmos_inb(RTC_REGB_STATUS);
time->second = cmos_read_time(RTC_REG_SECOND, reg_b);
+3 -1
View File
@@ -25,11 +25,13 @@ uint64_t system_time = 0;
static uint32_t timer_tick(void *arg) {
switch ((uint64_t) arg) {
case TIMER_PIT:
#if defined(VESA_ENABLE)
++int_timer_ticks;
if (int_timer_ticks >= 500) {
con_blink();
int_timer_ticks = 0;
}
#endif
// Each tick is approx. 1ms, so add 1ms to system time
system_time += 1000000;
break;
@@ -60,7 +62,7 @@ void amd64_timer_init(void) {
// LAPIC Timer is only used to trigger task switches
LAPIC(LAPIC_REG_TMRDIV) = 0x3;
LAPIC(LAPIC_REG_LVTT) = 32 | (1 << 17);
LAPIC(LAPIC_REG_TMRINITCNT) = 10000;
LAPIC(LAPIC_REG_TMRINITCNT) = 1562500;
LAPIC(LAPIC_REG_TMRCURRCNT) = 0;
get_cpu()->ticks = 0;
+16 -4
View File
@@ -11,6 +11,7 @@
#include "sys/fcntl.h"
#include "sys/tty.h"
#include "sys/amd64/mm/phys.h"
#include "sys/amd64/hw/rtc.h"
#include "sys/amd64/mm/map.h"
#include "sys/fs/pty.h"
#include "sys/time.h"
@@ -41,8 +42,11 @@ static void sys_sigret(void);
__attribute__((noreturn)) void amd64_syscall_yield_stopped(void);
uint64_t syscall_last_time = 0;
uint64_t syscall_count = 0;
intptr_t amd64_syscall(uintptr_t rdi, uintptr_t rsi, uintptr_t rdx, uintptr_t rcx, uintptr_t r10, uintptr_t rax) {
asm volatile ("cli");
++syscall_count;
switch (rax) {
case SYSCALL_NR_READ:
return sys_read((int) rdi, (void *) rsi, (size_t) rdx);
@@ -392,13 +396,21 @@ static int sys_nanosleep(const struct timespec *req, struct timespec *rem) {
}
static int sys_gettimeofday(struct timeval *tv, struct timezone *tz) {
tz->tz_dsttime = 0;
tz->tz_minuteswest = 0;
if (tz) {
tz->tz_dsttime = 0;
tz->tz_minuteswest = 0;
}
uint64_t secs = system_time / 1000000000ULL;
struct rtc_time time_rtc;
rtc_read(&time_rtc);
secs += time_rtc.second + time_rtc.minute * 60 + time_rtc.hour * 3600;
// System time is in nanos
// TODO: use RTC-provided time for full system time
tv->tv_usec = (system_time / 1000) % 1000000;
tv->tv_sec = system_time / 1000000000ULL;
tv->tv_sec = secs;
return 0;
}
+17 -10
View File
@@ -1,3 +1,4 @@
#include "sys/thread.h"
#include "sys/assert.h"
#include "sys/debug.h"
#include "sys/ring.h"
@@ -44,22 +45,24 @@ static inline void ring_advance_write(struct ring *ring) {
int ring_getc(struct thread *ctx, struct ring *ring, char *out) {
uintptr_t flags;
spin_lock_irqsave(&ring->lock, &flags);
//spin_lock_irqsave(&ring->lock, &flags);
do {
if (ring_avail(ring)) {
break;
}
spin_release(&ring->lock);
//spin_release(&ring->lock);
ctx->flags |= THREAD_WAITING;
asm volatile ("sti; hlt");
spin_lock(&ring->lock);
ctx->flags &= ~THREAD_WAITING;
//spin_lock(&ring->lock);
} while (1);
*out = ring->data[ring->rdptr];
ring_advance_read(ring);
spin_release_irqrestore(&ring->lock, &flags);
//spin_release_irqrestore(&ring->lock, &flags);
return 0;
}
@@ -80,25 +83,29 @@ ssize_t ring_read(struct thread *ctx, struct ring *ring, void *buf, size_t count
return pos;
}
int ring_putc(struct ring *ring, char c) {
int ring_putc(struct thread *ctx, struct ring *ring, char c) {
uintptr_t flags;
spin_lock_irqsave(&ring->lock, &flags);
//spin_lock_irqsave(&ring->lock, &flags);
do {
if (ring_writable(ring)) {
break;
}
spin_release(&ring->lock);
asm volatile ("sti; hlt");
spin_lock(&ring->lock);
//spin_release(&ring->lock);
if (ctx) {
asm volatile ("sti; hlt");
} else {
asm volatile ("sti; hlt");
}
//spin_lock(&ring->lock);
} while (1);
ring->data[ring->wrptr] = c;
ring_advance_write(ring);
spin_release_irqrestore(&ring->lock, &flags);
//spin_release_irqrestore(&ring->lock, &flags);
return 0;
}
+13
View File
@@ -172,6 +172,13 @@ uint32_t *memsetl(uint32_t *blk, uint32_t v, size_t sz) {
return blk;
}
uint64_t *memsetq(uint64_t *blk, uint64_t v, size_t sz) {
for (size_t i = 0; i < sz; ++i) {
blk[i] = v;
}
return blk;
}
void *memcpy(void *dst, const void *src, size_t sz) {
for (size_t i = 0; i < sz; ++i) {
((char *) dst)[i] = ((const char *) src)[i];
@@ -179,3 +186,9 @@ void *memcpy(void *dst, const void *src, size_t sz) {
return dst;
}
uint64_t *memcpyq(uint64_t *restrict dst, const uint64_t *restrict src, size_t sz) {
for (size_t i = 0; i < sz; ++i) {
dst[i] = src[i];
}
return dst;
}
+1 -1
View File
@@ -33,7 +33,7 @@ static struct ring tty_ring = {0};
// This function receives keystrokes from keyboard drivers
void tty_buffer_write(int tty_no, char c) {
ring_putc(&tty_ring, c);
ring_putc(NULL, &tty_ring, c);
}
void tty_init(void) {
+2 -12
View File
@@ -15,16 +15,6 @@ static ssize_t pty_master_read(struct chrdev *dev, void *buf, size_t count, size
static ssize_t pty_slave_write(struct chrdev *dev, const void *buf, size_t count, size_t off);
static ssize_t pty_slave_read(struct chrdev *dev, void *buf, size_t count, size_t off);
//static struct chrdev pty_master_dev = {
// .read = pty_master_read,
// .write = pty_master_write
//};
//
//static struct chrdev pty_slave_dev = {
// .read = pty_slave_read,
// .write = pty_slave_write
//};
static ssize_t pty_slave_write(struct chrdev *dev, const void *buf, size_t off, size_t count) {
// Slave writes -> pty output -> Master reads
// AS-IS
@@ -33,7 +23,7 @@ static ssize_t pty_slave_write(struct chrdev *dev, const void *buf, size_t off,
int res = 0;
for (size_t i = 0; i < count; ++i) {
if ((res = ring_putc(&pty->ring_output, ((const char *) buf)[i])) < 0) {
if ((res = ring_putc(get_cpu()->thread, &pty->ring_output, ((const char *) buf)[i])) < 0) {
break;
}
}
@@ -75,7 +65,7 @@ static ssize_t pty_master_write(struct chrdev *dev, const void *buf, size_t pos,
int res = 0;
for (size_t i = 0; i < count; ++i) {
if ((res = ring_putc(&pty->ring_input, ((const char *) buf)[i])) < 0) {
if ((res = ring_putc(get_cpu()->thread, &pty->ring_input, ((const char *) buf)[i])) < 0) {
break;
}
}
+14 -2
View File
@@ -6,7 +6,8 @@ DIRS=$(O) \
$(O)/libc
HDRS=$(shell find $(S) -type f -name "*.h")
STAGE_BIN=$(STAGE)/init \
$(STAGE)/hello
$(STAGE)/hello \
$(STAGE)/time
CFLAGS=-ffreestanding \
-nostdlib \
@@ -35,7 +36,8 @@ libc_OBJS=$(O)/libc/crt0.o \
$(O)/libc/malloc.o \
$(O)/libc/dirent.o \
$(O)/libc/signal.o \
$(O)/libc/global.o
$(O)/libc/global.o \
$(O)/libc/time.o
sys_CRTBEGIN=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
sys_CRTEND=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)
@@ -60,6 +62,16 @@ $(STAGE)/init: init.c $(libc_CRTI) $(libc_CRTN) $(O)/libc.a
$(libc_CRTN) \
$(usr_STATIC_LIBS)
$(STAGE)/time: time.c $(libc_CRTI) $(libc_CRTN) $(O)/libc.a
@printf " CC\t%s\n" $(@:$(STAGE)/%=/%)
@$(CC) -o $@ $(CFLAGS) $(usr_LDFLAGS) \
$(libc_CRTI) \
$(sys_CRTBEGIN) \
time.c \
$(sys_CRTEND) \
$(libc_CRTN) \
$(usr_STATIC_LIBS)
$(STAGE)/hello: hello.c $(libc_CRTI) $(libc_CRTN) $(O)/libc.a
@printf " CC\t%s\n" $(@:$(STAGE)/%=/%)
@$(CC) -o $@ $(CFLAGS) $(usr_LDFLAGS) \
+65 -7
View File
@@ -18,6 +18,13 @@
#define clear() \
write(STDOUT_FILENO, "\033[2J", 4)
#define BOX_ANGLE_UL "\332"
#define BOX_ANGLE_UR "\277"
#define BOX_ANGLE_LL "\300"
#define BOX_ANGLE_LR "\331"
#define BOX_HOR "\304"
#define BOX_VERT "\263"
//
extern __attribute__((noreturn)) void abort(void);
@@ -178,24 +185,62 @@ static int b_cat(const char *arg) {
static int b_curs(const char *arg) {
char c;
size_t w = 60;
size_t h = 20;
size_t off_y = (25 - h) / 2 + 1;
size_t off_x = (80 - w) / 2;
const char *lines[18] = {
NULL,
"Demo something",
NULL,
"Slow as hell"
};
clear();
while (1) {
// Draw some kind of status bar
curs_set(25, 1);
printf("\033[7m This is statusbar\033[K");
if (c >= ' ') {
curs_set(25, 79);
printf("%c\033[0m", c);
printf("\033[47;30m");
curs_set(off_y, off_x);
printf(BOX_ANGLE_UL);
for (size_t i = 0; i < w; ++i) {
printf(BOX_HOR);
}
printf(BOX_ANGLE_UR);
for (size_t i = 0; i < h - 2; ++i) {
curs_set(off_y + 1 + i, off_x);
printf(BOX_VERT);
for (size_t j = 0; j < w; ++j) {
printf(" ");
}
if (lines[i]) {
curs_set(off_y + 1 + i, off_x + (w - strlen(lines[i])) / 2);
printf("%s", lines[i]);
}
curs_set(off_y + 1 + i, off_x + w + 1);
printf(BOX_VERT);
}
curs_set(off_y + h - 3, off_x + (w - 8) / 2);
printf("\033[0m\033[7m[ OK ]\033[47;30m");
curs_set(off_y + h - 1, off_x);
printf(BOX_ANGLE_LL);
for (size_t i = 0; i < w; ++i) {
printf(BOX_HOR);
}
printf(BOX_ANGLE_LR);
printf("\033[0m");
curs_set(1, 1);
if (read(STDIN_FILENO, &c, 1) < 0) {
break;
}
if (c == 'q') {
if (c == 'q' || c == '\n') {
break;
}
}
@@ -294,6 +339,19 @@ int main(int argc, char **argv) {
int res;
prompt();
#if 0
if ((res = fork()) < 0) {
perror("fork()");
return -1;
} else if (res == 0) {
if (execve("/time", NULL, NULL) != 0) {
perror("execve()");
}
exit(-1);
}
#endif
while (1) {
if (read(STDIN_FILENO, &c, 1) < 0) {
break;
+1
View File
@@ -22,5 +22,6 @@ int chdir(const char *filename);
char *getcwd(char *buf, size_t size);
int nanosleep(const struct timespec *req, struct timespec *rem);
int openpty(int *amaster, int *aslave);
int gettimeofday(struct timeval *tv, struct timezone *tz);
__attribute__((noreturn)) void exit(int code);
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include <sys/time.h>
int usleep(long us);
+4
View File
@@ -133,6 +133,10 @@ int openpty(int *master, int *slave) {
return SET_ERRNO(int, ASM_SYSCALL2(SYSCALL_NRX_OPENPTY, master, slave));
}
int gettimeofday(struct timeval *tv, struct timezone *tz) {
return SET_ERRNO(int, ASM_SYSCALL2(SYSCALL_NR_GETTIMEOFDAY, tv, tz));
}
// Although sbrk() is implemented in userspace, I guess it should also be here
void *sbrk(intptr_t inc) {
if (inc == 0) {
+7
View File
@@ -0,0 +1,7 @@
#include "time.h"
#include "bits/syscall.h"
int usleep(long us) {
struct timeval tv = { us / 1000000, (us % 1000) * 1000 };
return nanosleep(&tv, NULL);
}
+12
View File
@@ -0,0 +1,12 @@
#include <stdio.h>
#include <sys/time.h>
int main() {
struct timeval tv;
while (1) {
usleep(100000);
gettimeofday(&tv, NULL);
printf("\033[s\033[1;70f%u\033[u", tv.tv_sec);
}
}