<commit_before>use alloc::boxed::{Box, FnBox};

use collections::string::String;
use collections::vec::Vec;

use core::{mem, ptr};

use common::memory;
use common::paging::Page;
use common::scheduler;

use schemes::Resource;

pub const CONTEXT_STACK_SIZE: usize = 1024 * 1024;

pub static mut contexts_ptr: *mut Vec<Box<Context>> = 0 as *mut Vec<Box<Context>>;
pub static mut context_i: usize = 0;
pub static mut context_enabled: bool = false;

/// Switch context
///
/// Unsafe due to interrupt disabling, raw pointers, and unsafe Context functions
pub unsafe fn context_switch(interrupted: bool) {
    let reenable = scheduler::start_no_ints();

    let contexts = &mut *contexts_ptr;
    if context_enabled {
        let current_i = context_i;
        context_i += 1;
        // The only garbage collection in Redox
        loop {
            if context_i >= contexts.len() {
                context_i -= contexts.len();
            }

            let mut remove = false;
            if let Some(next) = contexts.get(context_i) {
                if next.exited {
                    remove = true;
                }
            }

            if remove {
                drop(contexts.remove(context_i));
            } else {
                break;
            }
        }

        if context_i >= contexts.len() {
            context_i -= contexts.len();
        }

        if context_i != current_i {
            match contexts.get(current_i) {
                Some(current) => match contexts.get(context_i) {
                    Some(next) => {
                        let current_ptr: *mut Context = mem::transmute(current);
                        let next_ptr: *mut Context = mem::transmute(next);

                        (*current_ptr).interrupted = interrupted;
                        (*next_ptr).interrupted = false;
                        (*current_ptr).remap(&mut *next_ptr);
                        (*current_ptr).switch(&mut *next_ptr);
                    }
                    None => (),
                },
                None => (),
            }
        }
    }

    scheduler::end_no_ints(reenable);
}

/// Fork context
///
/// Unsafe due to interrupt disabling, C memory handling, and raw pointers
pub unsafe extern "cdecl" fn context_fork(parent_i: usize){
    let reenable = scheduler::start_no_ints();

    let contexts = &mut *contexts_ptr;
    let mut context_option: Option<Box<Context>> = None;
    if let Some(parent) = contexts.get(parent_i) {<commit_msg>Fix context switch<commit_after>use alloc::boxed::{Box, FnBox};

use collections::string::String;
use collections::vec::Vec;

use core::{mem, ptr};

use common::memory;
use common::paging::Page;
use common::scheduler;

use schemes::Resource;

pub const CONTEXT_STACK_SIZE: usize = 1024 * 1024;

pub static mut contexts_ptr: *mut Vec<Box<Context>> = 0 as *mut Vec<Box<Context>>;
pub static mut context_i: usize = 0;
pub static mut context_enabled: bool = false;

/// Switch context
///
/// Unsafe due to interrupt disabling, raw pointers, and unsafe Context functions
pub unsafe fn context_switch(interrupted: bool) {
    let reenable = scheduler::start_no_ints();

    let contexts = &mut *contexts_ptr;
    if context_enabled {
        let current_i = context_i;
        context_i += 1;
        // The only garbage collection in Redox
        loop {
            if context_i >= contexts.len() {
                context_i -= contexts.len();
            }

            let mut remove = false;
            if let Some(next) = contexts.get(context_i) {
                if next.exited {
                    remove = true;
                }
            }

            if remove {
                drop(contexts.remove(context_i));
            } else {
                break;
            }
        }

        if context_i >= contexts.len() {
            context_i -= contexts.len();
        }

        if context_i != current_i {
            match contexts.get(current_i) {
                Some(current) => match contexts.get(context_i) {
                    Some(next) => {
                        let current_ptr: *mut Box<Context> = mem::transmute(current as *const Box<Context>);
                        let next_ptr: *mut Box<Context> = mem::transmute(next as *const Box<Context>);

                        (*current_ptr).interrupted = interrupted;
                        (*next_ptr).interrupted = false;
                        (*current_ptr).remap(&mut *next_ptr);
                        (*current_ptr).switch(&mut *next_ptr);
                    }
                    None => (),
                },
                None => (),
            }
        }
    }

    scheduler::end_no_ints(reenable);
}

/// Fork context
///
/// Unsafe due to interrupt disabling, C memory handling, and raw pointers
pub unsafe extern "cdecl" fn context_fork(parent_i: usize){
    let reenable = scheduler::start_no_ints();

    let contexts = &mut *contexts_ptr;
    let mut context_option: Option<Box<Context>> = None;
    if let Some(parent) = contexts.get(parent_i) {
{'fraction_non_alphanumeric': 0.11302795954788816, 'fraction_numerical': 0.004362482649216736, 'mean_word_length': 1.832116788321168, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 31, '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': '6925746', 'n_tokens_mistral': 1477, 'n_tokens_neox': 1370, 'n_words': 364}