Skip to content

Instantly share code, notes, and snippets.

@nddrylliog
Created August 15, 2010 00:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nddrylliog/524871 to your computer and use it in GitHub Desktop.
Save nddrylliog/524871 to your computer and use it in GitHub Desktop.
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)
allocatedStackSize = requestedStackSize
"Coro_%p re-allocated stack size %i" printfln(this, requestedStackSize)
}
if (stack == null) {
stack = gc_malloc(requestedStackSize)
allocatedStackSize = requestedStackSize
"Coro_%p allocated 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()
"Scheduler error: returned from coro start function" println()
exit(-1)
)
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&)
"stackPointer = %p, stackSize = %d, flags = %d, link = %p" printfln(env stack stackPointer, env stack stackSize, env stack flags, env link)
makecontext(env&, callback as Closure thunk, 1, callback as Closure context)
}
switchTo: func (next: This) {
"Coro %p, switching to %p" printfln(this, next)
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment