<commit_before>#include "yoroutine.h"

Yoroutine::Yoroutine(yc_fn func, void *arg) {
    Scheduler* root = Scheduler::getInstance();
    int new_id = root->assign_size();

    this->scheduler = root;
    this->stack = nullptr;
    this->stack_size = 0;
    this->func = func;
    this->arg = arg;
    this->status = YOROUTINE_READY;

    this->id = new_id;
    scheduler->push_yc(this);
}

Yoroutine::~Yoroutine() {
    free(this->stack);
    delete (this);
    _compress_yclist(this->id);
}

void Yoroutine::resume() {
    int id = this->id;
    ucontext_t ctx = this->ctx;

    if (id == DUMMY_YOROUTINE_ID) {
        errPrint("Could not resume a dummy yoroutine");
        return;
    }

    Yoroutine *cryc = scheduler->get_yc(id);
    if (cryc == nullptr) {
        errPrint("Could not resume a null yoroutine");
        return;
    }

    switch (status) {
        case YOROUTINE_READY: {
            getcontext(&ctx);
            ctx.uc_stack.ss_size = scheduler->stack_size;
            ctx.uc_stack.ss_sp = scheduler->stack;
            ctx.uc_link = &scheduler->main;
            status = YOROUTINE_RUNNING;
            scheduler->set_cur_id(id);
            uintptr_t arg_ptr = (uintptr_t) this;
            makecontext(
                    &ctx,
                    (void (*)(void))_wrap_fn,
                    2,
                    (uint32_t) arg_ptr,
                    (uint32_t) (arg_ptr >> 32)
            );
            swapcontext(&scheduler->main, &ctx);
            break;
        }

        case YOROUTINE_SUSPENDED: {
            memcpy(
                    scheduler->stack + STACK_SIZE - this->stack_size,
                    this->stack,
                    this->stack_size
            );
            this->status = YOROUTINE_RUNNING;
            scheduler->set_cur_id(this->id);
            swapcontext(&scheduler->main, &ctx);
            break;
        }

        default:
            break;
    }
}

void Yoroutine::_pause(int to_status) {

    if ((char *) this <= scheduler->stack) {
        errPrint("Current yoroutine has run out of available stack");
        return;
    }
    if (!_save_stack()) {
        errPrint("Failed to save stack before pausing a yoroutine");
        return;
    }
    this->status = to_status;
    scheduler->set_cur_id(DUMMY_YOROUTINE_ID);
    swapcontext(&this->ctx, &scheduler->main);
}

void Yoroutine::_compress_yclist(int idx) {
    int size = scheduler->get_size();
    scheduler->get_yc(idx)->status = YOROUTINE_IDLE;

    if (size >= 1) {
        if (idx < size - 1) {
            scheduler->set_yc(idx, scheduler->get_yc(size - 1));
            scheduler->get_yc(idx)->id = idx;
        }
        scheduler->set_yc(size - 1, nullptr);<commit_msg>[bug-fix] linux debug third step, code run correct<commit_after>#include "yoroutine.h"

Yoroutine::Yoroutine(yc_fn func, void *arg) {
    Scheduler* root = Scheduler::getInstance();
    int new_id = root->assign_size();

    this->scheduler = root;
    this->stack = nullptr;
    this->stack_size = 0;
    this->func = func;
    this->arg = arg;
    this->status = YOROUTINE_READY;

    this->id = new_id;
    scheduler->push_yc(this);
}

Yoroutine::~Yoroutine() {
    free(this->stack);
    delete (this);
    _compress_yclist(this->id);
}

void Yoroutine::resume() {
    int id = this->id;
    ucontext_t ctx = this->ctx;

    if (id == DUMMY_YOROUTINE_ID) {
        errPrint("Could not resume a dummy yoroutine");
        return;
    }

    Yoroutine *cryc = scheduler->get_yc(id);
    if (cryc == nullptr) {
        errPrint("Could not resume a null yoroutine");
        return;
    }

    switch (status) {
        case YOROUTINE_READY: {
            getcontext(&ctx);
            ctx.uc_stack.ss_size = scheduler->stack_size;
            ctx.uc_stack.ss_sp = scheduler->stack;
            ctx.uc_link = &scheduler->main;
            status = YOROUTINE_RUNNING;
            scheduler->set_cur_id(id);
            uintptr_t arg_ptr = (uintptr_t) this;
            makecontext(
                    &ctx,
                    (void (*)(void))_wrap_fn,
                    2,
                    (uint32_t) arg_ptr,
                    (uint32_t) (arg_ptr >> 32)
            );
            swapcontext(&scheduler->main, &ctx);
            break;
        }

        case YOROUTINE_SUSPENDED: {
            memcpy(
                    scheduler->stack + STACK_SIZE - this->stack_size,
                    this->stack,
                    this->stack_size
            );
            this->status = YOROUTINE_RUNNING;
            scheduler->set_cur_id(this->id);
            swapcontext(&scheduler->main, &ctx);
            break;
        }

        default:
            break;
    }
}

void Yoroutine::_pause(int to_status) {

    if (!_save_stack()) {
        errPrint("Failed to save stack before pausing a yoroutine");
        return;
    }
    this->status = to_status;
    scheduler->set_cur_id(DUMMY_YOROUTINE_ID);
    swapcontext(&this->ctx, &scheduler->main);
}

void Yoroutine::_compress_yclist(int idx) {
    int size = scheduler->get_size();
    scheduler->get_yc(idx)->status = YOROUTINE_IDLE;

    if (size >= 1) {
        if (idx < size - 1) {
            scheduler->set_yc(idx, scheduler->get_yc(size - 1));
            scheduler->get_yc(idx)->id = idx;
        }
        scheduler->set_yc(size - 1, nullptr);
{'fraction_non_alphanumeric': 0.12822912766754024, 'fraction_numerical': 0.004492699363534257, 'mean_word_length': 1.8741258741258742, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 88, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2433446', 'n_tokens_mistral': 1773, 'n_tokens_neox': 1747, 'n_words': 323}