Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pure ooc coroutines implementations on top of ucontext, based on libc…
…oroutine. Doesn't work yet for channels, for some reason.
- Loading branch information
nddrylliog
committed
Aug 14, 2010
1 parent
cb51fbb
commit f3cf821
Showing
3 changed files
with
131 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|