diff --git a/kern/include/ec.h b/kern/include/ec.h index ead1858..3549ff2 100644 --- a/kern/include/ec.h +++ b/kern/include/ec.h @@ -30,6 +30,8 @@ class Ec private: void (*cont)(); Exc_regs regs; + Ec * prev; + Ec * next; REGPARM (1) static void handle_exc (Exc_regs *) asm ("exc_handler"); @@ -45,6 +47,8 @@ class Ec ALWAYS_INLINE inline Exc_regs *exc_regs() { return ®s; } + void enqueue(); + public: static Ec * current; @@ -78,6 +82,12 @@ class Ec NORETURN static void sys_dump(); + NORETURN + static void sys_create_ec(); + + NORETURN + static void sys_yield(); + ALWAYS_INLINE static inline void *operator new (size_t) { return Kalloc::allocator.alloc(sizeof (Ec)); } diff --git a/kern/src/ec.cc b/kern/src/ec.cc index 223ec4b..1f56b26 100644 --- a/kern/src/ec.cc +++ b/kern/src/ec.cc @@ -35,6 +35,9 @@ Ec::Ec (void (*f)(), mword mbi) : cont (f) regs.es = SEL_USER_DATA; regs.ss = SEL_USER_DATA; regs.efl = 0x200; // IF = 1 + + // created externally, need to enqueue itself + enqueue(); } // only used by syscall create thread (EC+SC) @@ -50,6 +53,20 @@ Ec::Ec (mword eip, mword esp) regs.esp = esp; } +void Ec::enqueue() +{ + if (!current) { + + next = prev = this; + + } else { + + next = current; + prev = current->prev; + next->prev = prev->next = this; + } +} + void Ec::ret_user_sysexit() { asm volatile ("lea %0, %%esp;" @@ -137,6 +154,8 @@ void Ec::handle_tss() void Ec::syscall_handler (uint8 n) { if (n == 0) sys_dump(); + else if (n == 1) sys_create_ec(); + else if (n == 2) sys_yield(); printf ("syscall %d - unknown\n", n); @@ -152,6 +171,27 @@ void Ec::sys_dump() ret_user_sysexit(); } +void Ec::sys_create_ec() +{ + Sys_create_ec * r = static_cast(current->sys_regs()); + + Ec * ec = new Ec (r->eip(), r->esp()); + ec->enqueue(); + + printf ("EC:%p SYS_CREATE_EC EC:%p (EIP=%#lx ESP=%#lx)\n", current, ec, r->eip(), r->esp()); + + ret_user_sysexit(); +} + +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 01791a1..0e9a8fb 100644 --- a/user/src/user.cc +++ b/user/src/user.cc @@ -1,3 +1,6 @@ +#define NORETURN __attribute__((noreturn)) +#define EXTERN_C extern "C" + unsigned syscall3 (unsigned w0, unsigned w1 = 0, unsigned w2 = 0) { asm volatile ( @@ -9,8 +12,32 @@ unsigned syscall3 (unsigned w0, unsigned w1 = 0, unsigned w2 = 0) return w0; } -extern "C" void main_func () +void sys_create_ec (void (*eip)(), void* esp) +{ + syscall3 (1, reinterpret_cast(eip), reinterpret_cast(esp)); +} + +void sys_yield() +{ + syscall3 (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) ; }