<commit_before>
/**
 * Portable ucontext-based coroutines implementation for cooperative multitasking.
 *
 * Based on the work of:
 *  - <NAME> (libcoroutine - http://github.com/stevedekorte/coroutine)
 *  - <NAME> (libcoroutine OSX10.6 fixes)
 *  - <NAME> (Minimalistic cooperative multitasking - http://www.goron.de/~froese/)
 */
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

    stack: Pointer
    env: UContext
    isMain: Bool

    init: func {}

    initializeMainCoro: func {
        isMain = true
    }

    startCoro: func (other: This, callback: Func) {
        other allocStackIfNeeded()
        other setup(this, ||
            callback()
            raise("Scheduler error: returned from coro start function")
            exit(-1)
        )
        switchTo(other)
    }

    setup: func (coro: Coro, callback: Func) {
        getcontext(env&)

        env stack stackPointer = stack
        env stack stackSize    = DEFAULT_STACK_SIZE
        env stack flags        = 0
        env link               = coro env&

        makecontext(env&, callback as Closure thunk, 1, callback as Closure context)
    }

    switchTo: func (next: This) {
        oldStackBase := GC_stackbottom
        stackBase := env stack stackPointer as UInt8*
        stackSize := env stack stackSize
        GC_add_roots(stackBase, stackBase + stackSize)
        GC_stackbottom = stackBase
        swapcontext(env&, next env&)
        GC_stackbottom = oldStackBase
        GC_remove_roots(stackBase, stackBase + stackSize)
    }

    allocStackIfNeeded: func {
        if (!stack) {
            stack = coro_malloc(DEFAULT_STACK_SIZE)
        }
    }

    free: func {
        if (stack) {
            coro_free(stack)
            stack = null
        }
    }

}

/* ------ C interfacing ------- */

coro_malloc: extern(malloc) func (s: SizeT) -> Pointer
coro_free: extern(free) func (p: Pointer)

include ucontext | (_XOPEN_SOURCE=600)

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

GC_add_roots: extern func (Pointer, Pointer)
GC_remove_roots: extern func (Pointer, Pointer)
GC_stackbottom: extern Pointer
<commit_msg>More os/Coro + GC fixes<commit_after>
/**
 * Portable ucontext-based coroutines implementation for cooperative multitasking.
 *
 * Based on the work of:
 *  - <NAME> (libcoroutine - http://github.com/stevedekorte/coroutine)
 *  - <NAME> (libcoroutine OSX10.6 fixes)
 *  - <NAME> (Minimalistic cooperative multitasking - http://www.goron.de/~froese/)
 */
Coro: class {

    // 128k stack = room for quite a few function calls
    DEFAULT_STACK_SIZE := static 128 * 1_024

    stack: UInt8*
    env: UContext
    isMain: Bool

    init: func

    initializeMainCoro: func {
        isMain = true
    }

    startCoro: func (other: This, callback: Func) {
        other allocStackIfNeeded()
        other setup(this, ||
            callback()
            raise("Scheduler error: returned from coro start function")
            exit(-1)
        )
        switchTo(other)
        other free()
    }

    setup: func (coro: Coro, callback: Func) {
        getcontext(env&)

        env stack address = stack
        env stack size    = DEFAULT_STACK_SIZE
        env stack flags   = 0
        env link          = coro env&

        GC_add_roots(
            stack,
            stack + DEFAULT_STACK_SIZE
        )

        makecontext(env&, callback as Closure thunk, 1, callback as Closure context)
    }

    switchTo: func (next: This) {
        GC_stackbottom = next env stack address
        swapcontext(env&, next env&)
    }

    allocStackIfNeeded: func {
        if (!stack) {
            stack = coro_malloc(DEFAULT_STACK_SIZE)
        }
    }

    free: func {
        GC_remove_roots(
            stack,
            stack + DEFAULT_STACK_SIZE
        )

        if (stack) {
            coro_free(stack)
            stack = null
        }
    }

}

/* ------ C interfacing ------- */

coro_malloc: extern(malloc) func (s: SizeT) -> Pointer
coro_free: extern(free) func (p: Pointer)

include ucontext | (_XOPEN_SOURCE=600)

StackT: cover from stack_t {
    address: extern(ss_sp) Pointer
    flags: extern(ss_flags) Int
    size: 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

GC_add_roots: extern func (Pointer, Pointer)
GC_remove_roots: extern func (Pointer, Pointer)
GC_stackbottom: extern UInt8*

{'fraction_non_alphanumeric': 0.10228136882129278, 'fraction_numerical': 0.009125475285171103, 'mean_word_length': 2.420676202860858, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2306086', 'n_tokens_mistral': 1716, 'n_tokens_neox': 1631, 'n_words': 468}