diff --git a/kern/include/ec.h b/kern/include/ec.h index 0d9a6b1..1901245 100644 --- a/kern/include/ec.h +++ b/kern/include/ec.h @@ -30,6 +30,7 @@ class Ec private: void (*cont)(); Exc_regs regs; + Ec *prev, *next; [[gnu::regparm(1)]] static void handle_exc(Exc_regs *) asm("exc_handler"); @@ -51,6 +52,8 @@ class Ec return ®s; } + void enqueue(); + public: static Ec *current; @@ -86,6 +89,10 @@ class Ec static void sys_dump(); + static void sys_create_ec(); + + static void sys_yield(); + [[gnu::always_inline]] static inline void *operator new(size_t) { diff --git a/kern/src/ec.cc b/kern/src/ec.cc index 6f4525e..086257d 100644 --- a/kern/src/ec.cc +++ b/kern/src/ec.cc @@ -34,6 +34,8 @@ Ec::Ec(void (*f)(), mword mbi) : cont(f) regs.cs = SEL_USER_CODE; regs.ss = SEL_USER_DATA; regs.rfl = 0x200; // IF = 1 + + enqueue(); } // only used by syscall create thread (EC+SC) @@ -45,6 +47,20 @@ Ec::Ec(mword rip, mword rsp) regs.rfl = 0x200; // IF = 1 regs.rip = rip; regs.rsp = rsp; + + enqueue(); +} + +void Ec::enqueue() +{ + if (!current) { + next = prev = this; + } + else { + next = current; + prev = current->prev; + next->prev = prev->next = this; + } } void Ec::ret_user_sysexit() @@ -132,6 +148,14 @@ void Ec::syscall_handler(uint8 n) sys_dump(); break; + case 1: + sys_create_ec(); + break; + + case 2: + sys_yield(); + break; + default: printf("syscall %d - unknown\n", n); break; @@ -150,6 +174,23 @@ void Ec::sys_dump() current->sys_regs()->rdx); } +void Ec::sys_create_ec() +{ + mword rip = current->sys_regs()->rsi; + mword rsp = current->sys_regs()->rdx; + Ec *ec = new Ec(rip, rsp); + + printf("EC:%p SYS_CREATE_EC EC:%p (RIP=%#lx RSP=%#lx)\n", current, ec, rip, rsp); +} + +void Ec::sys_yield() +{ + printf("EC:%p SYS_YIELD to EC:%p\n", current, current->next); + + current->cont = ret_user_sysexit; + current->next->make_current(); +} + bool Ec::handle_exc_ts(Exc_regs *r) { if (r->user()) diff --git a/user/src/user.cc b/user/src/user.cc index b44604b..f6472f1 100644 --- a/user/src/user.cc +++ b/user/src/user.cc @@ -1,6 +1,48 @@ +unsigned long syscall1(unsigned long w0) +{ + asm volatile("syscall" : "+D"(w0) : : "rcx", "r11", "memory"); + return w0; +} + +unsigned long syscall2(unsigned long w0, unsigned long w1) +{ + asm volatile("syscall" : "+D"(w0) : "S"(w1) : "rcx", "r11", "memory"); + return w0; +} + +unsigned long syscall3(unsigned long w0, unsigned long w1, unsigned long w2) +{ + asm volatile("syscall" : "+D"(w0) : "S"(w1), "d"(w2) : "rcx", "r11", "memory"); + return w0; +} + +void sys_create_ec(void (*eip)(), void *esp) +{ + syscall3(1, reinterpret_cast(eip), reinterpret_cast(esp)); +} + +unsigned long sys_yield() +{ + return syscall1(2); +} + +[[noreturn]] +void thread() +{ + while (1) + sys_yield(); +} + extern "C" [[noreturn]] void main_func() { + char stack[512]; + + for (int i = 1; i <= 8; i++) { + sys_create_ec(thread, stack + i * 64); + sys_yield(); + } + while (1) - ; + sys_yield(); }