<commit_before>use common::slice::GetSlice;

use alloc::arc::Arc;
use alloc::boxed::{Box, FnBox};

use arch::memory;
use arch::paging::Page;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::time::Duration;

use core::cell::UnsafeCell;
use core::slice::{Iter, IterMut};
use core::{mem, ptr};
use core::ops::DerefMut;

use fs::Resource;

use syscall::{do_sys_exit, Error, Result, CLONE_FILES, CLONE_FS, CLONE_VM, CLONE_VFORK, EBADF, EFAULT, ENOMEM, ESRCH};

use sync::WaitMap;

pub const CONTEXT_STACK_SIZE: usize = 1024 * 1024;
pub const CONTEXT_STACK_ADDR: usize = 0x70000000;

pub struct ContextManager {
    pub inner: Vec<Box<Context>>,
    pub enabled: bool,
    pub i: usize,
    pub next_pid: usize,
}

impl ContextManager {
    pub fn new() -> ContextManager {
        ContextManager {
            inner: Vec::new(),
            enabled: false,
            i: 0,
            next_pid: 1,
        }
    }

    pub fn current(&self) -> Result<&Box<Context>> {
        let i = self.i;
        self.get(i)
    }

    pub fn current_mut(&mut self) -> Result<&mut Box<Context>> {
        let i = self.i;
        self.get_mut(i)
    }

    pub fn iter(&self) -> Iter<Box<Context>> {
        self.inner.iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<Box<Context>> {
        self.inner.iter_mut()
    }

    pub fn get(&self, i: usize) -> Result<&Box<Context>> {
        if self.enabled {
            self.inner.get(i).ok_or(Error::new(ESRCH))
        } else{
            Err(Error::new(ESRCH))
        }
    }

    pub fn get_mut(&mut self, i: usize) -> Result<&mut Box<Context>> {
        if self.enabled {
            self.inner.get_mut(i).ok_or(Error::new(ESRCH))
        } else{
            Err(Error::new(ESRCH))
        }
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub unsafe fn push(&mut self, context: Box<Context>) {
        self.inner.push(context);
    }

    pub unsafe fn clean(&mut self) {
        loop {
            if self.i >= self.len() {
                self.i -= self.len();
            }

            let mut remove = false;
            if let Ok(next) = self.current() {
                if next.exited {
                    remove = true;
                }
            }

            if remove {
                let i = self.i;
                drop(self.inner.remove(i));
            } else {
                break;
            }
        }

        if self.i >= self.len() {
            self.i -= self.len();
        }
    }
}


/// Switch context
///
/// Unsafe due to interrupt disabling, raw pointers, and unsafe Context functions
pub unsafe fn context_switch() {
    let mut current_ptr: *mut Context = 0 as *mut Context;
    let mut next_ptr: *mut Context = 0 as *mut Context;

    {
        let mut contexts = ::env().contexts.lock();
        if contexts.enabled {
            let current_i = contexts.i;
            'searching: loop {
                contexts.i += 1;
                contexts.clean();
                if let Ok(mut next) = contexts.current_mut() {
                    if next.blocked {
                        if let Some(wake) = next.wake {
                            if wake < Duration::monotonic() {
                                next.blocked = false;
                                next.wake = None;
                                break 'searching;
                            }
                        }
                    } else {
                        break 'searching;
                    }
                }
                if contexts.i == current_i {
                    break 'searching;
                }
            }

            if contexts.i != current_i {
                if let Ok(mut current) = contexts.get_mut(current_i) {
                    current.unmap();

                    current_ptr = current.deref_mut();
                }

                if let Ok(mut next) = contexts.current_mut() {
                    next.switch += 1;

                    if let Some(ref mut tss) = ::TSS_PTR {
                        if next.kernel_stack > 0 {
                            tss.sp0 = next.kernel_stack + CONTEXT_STACK_SIZE - 128;
                        } else {
                            tss.sp0 = 0x200000 - 128;
                        }
                    }<commit_msg>Fix comparison in kernel for waking<commit_after>use common::slice::GetSlice;

use alloc::arc::Arc;
use alloc::boxed::{Box, FnBox};

use arch::memory;
use arch::paging::Page;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::time::Duration;

use core::cell::UnsafeCell;
use core::slice::{Iter, IterMut};
use core::{mem, ptr};
use core::ops::DerefMut;

use fs::Resource;

use syscall::{do_sys_exit, Error, Result, CLONE_FILES, CLONE_FS, CLONE_VM, CLONE_VFORK, EBADF, EFAULT, ENOMEM, ESRCH};

use sync::WaitMap;

pub const CONTEXT_STACK_SIZE: usize = 1024 * 1024;
pub const CONTEXT_STACK_ADDR: usize = 0x70000000;

pub struct ContextManager {
    pub inner: Vec<Box<Context>>,
    pub enabled: bool,
    pub i: usize,
    pub next_pid: usize,
}

impl ContextManager {
    pub fn new() -> ContextManager {
        ContextManager {
            inner: Vec::new(),
            enabled: false,
            i: 0,
            next_pid: 1,
        }
    }

    pub fn current(&self) -> Result<&Box<Context>> {
        let i = self.i;
        self.get(i)
    }

    pub fn current_mut(&mut self) -> Result<&mut Box<Context>> {
        let i = self.i;
        self.get_mut(i)
    }

    pub fn iter(&self) -> Iter<Box<Context>> {
        self.inner.iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<Box<Context>> {
        self.inner.iter_mut()
    }

    pub fn get(&self, i: usize) -> Result<&Box<Context>> {
        if self.enabled {
            self.inner.get(i).ok_or(Error::new(ESRCH))
        } else{
            Err(Error::new(ESRCH))
        }
    }

    pub fn get_mut(&mut self, i: usize) -> Result<&mut Box<Context>> {
        if self.enabled {
            self.inner.get_mut(i).ok_or(Error::new(ESRCH))
        } else{
            Err(Error::new(ESRCH))
        }
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub unsafe fn push(&mut self, context: Box<Context>) {
        self.inner.push(context);
    }

    pub unsafe fn clean(&mut self) {
        loop {
            if self.i >= self.len() {
                self.i -= self.len();
            }

            let mut remove = false;
            if let Ok(next) = self.current() {
                if next.exited {
                    remove = true;
                }
            }

            if remove {
                let i = self.i;
                drop(self.inner.remove(i));
            } else {
                break;
            }
        }

        if self.i >= self.len() {
            self.i -= self.len();
        }
    }
}


/// Switch context
///
/// Unsafe due to interrupt disabling, raw pointers, and unsafe Context functions
pub unsafe fn context_switch() {
    let mut current_ptr: *mut Context = 0 as *mut Context;
    let mut next_ptr: *mut Context = 0 as *mut Context;

    {
        let mut contexts = ::env().contexts.lock();
        if contexts.enabled {
            let current_i = contexts.i;
            'searching: loop {
                contexts.i += 1;
                contexts.clean();
                if let Ok(mut next) = contexts.current_mut() {
                    if next.blocked {
                        if let Some(wake) = next.wake {
                            if wake <= Duration::monotonic() {
                                next.blocked = false;
                                next.wake = None;
                                break 'searching;
                            }
                        }
                    } else {
                        break 'searching;
                    }
                }
                if contexts.i == current_i {
                    break 'searching;
                }
            }

            if contexts.i != current_i {
                if let Ok(mut current) = contexts.get_mut(current_i) {
                    current.unmap();

                    current_ptr = current.deref_mut();
                }

                if let Ok(mut next) = contexts.current_mut() {
                    next.switch += 1;

                    if let Some(ref mut tss) = ::TSS_PTR {
                        if next.kernel_stack > 0 {
                            tss.sp0 = next.kernel_stack + CONTEXT_STACK_SIZE - 128;
                        } else {
                            tss.sp0 = 0x200000 - 128;
                        }
                    }
{'fraction_non_alphanumeric': 0.11925764692404628, 'fraction_numerical': 0.008935731469813267, 'mean_word_length': 1.3505654281098547, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '7353977', 'n_tokens_mistral': 2701, 'n_tokens_neox': 2522, 'n_words': 607}