From f3cf8211e32b3dbeaf58abc8b5cd8996cb84ceba Mon Sep 17 00:00:00 2001 From: nddrylliog Date: Sat, 14 Aug 2010 23:58:18 +0200 Subject: [PATCH] Pure ooc coroutines implementations on top of ucontext, based on libcoroutine. Doesn't work yet for channels, for some reason. --- sdk/lang/Memory.ooc | 2 + sdk/lang/Numbers.ooc | 5 +- sdk/os/Coro.ooc | 126 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 sdk/os/Coro.ooc diff --git a/sdk/lang/Memory.ooc b/sdk/lang/Memory.ooc index d987055e..2fabc67c 100644 --- a/sdk/lang/Memory.ooc +++ b/sdk/lang/Memory.ooc @@ -12,6 +12,7 @@ version(!gc) { gc_malloc_atomic: extern(malloc) func (size: SizeT) -> Pointer gc_realloc: extern(realloc) func (ptr: Pointer, size: SizeT) -> Pointer gc_calloc: extern(calloc) func (nmemb: SizeT, size: SizeT) -> Pointer + gc_free: extern(free) func (ptr: Pointer) } version(gc) { @@ -23,6 +24,7 @@ version(gc) { gc_calloc: func (nmemb: SizeT, size: SizeT) -> Pointer { gc_malloc(nmemb * size) } + gc_free: extern(GC_FREE) func (ptr: Pointer) } // memory management diff --git a/sdk/lang/Numbers.ooc b/sdk/lang/Numbers.ooc index fe9f1618..02bc49ed 100644 --- a/sdk/lang/Numbers.ooc +++ b/sdk/lang/Numbers.ooc @@ -1,4 +1,4 @@ -include stdlib, stdint, stdbool, float, ctype, sys/types +include stdlib, stdint, stdbool, stddef, float, ctype, sys/types LLong: cover from signed long long { @@ -26,7 +26,7 @@ LLong: cover from signed long long { for (i in 0..this) { fn(i) } - } + } } Long: cover from signed long extends LLong @@ -73,6 +73,7 @@ UInt64: cover from uint64_t extends ULLong Octet: cover from uint8_t SizeT: cover from size_t extends ULLong SSizeT: cover from ssize_t extends LLong +PtrDiff: cover from ptrdiff_t extends SizeT /** * real types diff --git a/sdk/os/Coro.ooc b/sdk/os/Coro.ooc new file mode 100644 index 00000000..4a960b48 --- /dev/null +++ b/sdk/os/Coro.ooc @@ -0,0 +1,126 @@ + +Coro: class { + + // this was originally commented '128k needed on PPC due to parser' + // I have no idea what that means but 128k sounds reasonable. + DEFAULT_STACK_SIZE := static 128 * 1_024 + MIN_STACK_SIZE := static 8_192 + + requestedStackSize: SizeT { get set } + allocatedStackSize: SizeT + stack: Pointer { get set } + env: UContext + isMain: Bool + + init: func { + requestedStackSize = DEFAULT_STACK_SIZE + allocatedStackSize = 0 + } + + allocStackIfNeeded: func { + if (stack != null && allocatedStackSize > requestedStackSize) { + gc_free(stack) + stack = gc_malloc(requestedStackSize) + "Coro_%p re-allocating stack size %i" printfln(this, requestedStackSize) + } + + if (stack == null) { + stack = gc_malloc(requestedStackSize) + "Coro_%p allocating stack size %i" printfln(this, requestedStackSize) + } + } + + free: func { + if(stack) { + gc_free(stack) + } + "Coro_%p free" printfln(this) + } + + currentStackPointer: func -> UInt8* { + a: UInt8 + b := a& // to avoid compiler warning about unused variables + b + } + + bytesLeftOnStack: func -> SizeT { + dummy: UChar + p1: PtrDiff = dummy& + p2: PtrDiff = currentStackPointer() + + start: PtrDiff = stack + end: PtrDiff = stack + requestedStackSize + + stackMovesUp := (p2 > p1) + if(stackMovesUp) { // like x86 + end - p1 + } else { // like OSX on PPC + p1 - start + } + } + + stackSpaceAlmostGone: func -> Bool { + bytesLeftOnStack() < MIN_STACK_SIZE + } + + initializeMainCoro: func { + isMain = true + } + + startCoro: func (other: This, callback: Func) { + other allocStackIfNeeded() + other setup(callback) + switchTo(other) + } + + setup: func (callback: Func) { + getcontext(env&) + + env stack stackPointer = stack + requestedStackSize - 8 + env stack stackSize = requestedStackSize + env stack flags = 0 + env link = null + + "Setting up Closure %p, callback thunk/context = %p/%p, env& = %p" printfln(this, callback as Closure thunk, callback as Closure context, env&) + makecontext(env&, callback as Closure thunk, 1, callback as Closure context) + } + + switchTo: func (next: This) { + swapcontext(env&, next env&) + } + +} + +/* ------ C interfacing ------- */ + +include ucontext + +StackT: cover from stack_t { + stackPointer: extern(ss_sp) Pointer + flags: extern(ss_flags) Int + stackSize: extern(ss_size) SizeT +} + +UContext: cover from ucontext_t { + stack: extern(uc_stack) StackT + link: extern(uc_link) Pointer +} + +getcontext: extern func (ucp: UContext*) -> Int +setcontext: extern func (ucp: UContext*) -> Int +makecontext: extern func (ucp: UContext*, _func: Pointer, argc: Int, ...) +swapcontext: extern func (oucp: UContext*, ucp: UContext*) -> Int + + + + + + + + + + + + + +