Scheduler optimization, console optimization (still slow as hell)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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') {
|
||||
|
||||
@@ -46,7 +46,6 @@ amd64_irq0:
|
||||
movq %rax, 4(%rdi)
|
||||
1:
|
||||
// Assume we're now on TASK2's stack
|
||||
|
||||
// EOI
|
||||
irq_eoi_lapic 0
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <sys/time.h>
|
||||
|
||||
int usleep(long us);
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user