Skip to content
Snippets Groups Projects
sched.cc 1.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Avi Kivity's avatar
    Avi Kivity committed
    #include "sched.hh"
    #include <list>
    #include "mutex.hh"
    #include <mutex>
    #include "debug.hh"
    
    namespace sched {
    
    std::list<thread*> runqueue;
    
    thread __thread * s_current;
    
    elf::tls_data tls;
    
    }
    
    #include "arch-switch.hh"
    
    namespace sched {
    
    void schedule()
    {
        thread* p = thread::current();
        if (!p->_waiting) {
            return;
        }
        assert(!runqueue.empty());
        thread* n = runqueue.front();
        runqueue.pop_front();
        assert(!n->_waiting);
        n->_on_runqueue = false;
        n->switch_to();
    }
    
    thread::thread(std::function<void ()> func, bool main)
        : _func(func)
        , _on_runqueue(true)
        , _waiting(false)
    {
        if (!main) {
            setup_tcb();
            init_stack();
            runqueue.push_back(this);
        } else {
            setup_tcb_main();
            s_current = this;
            func();
            abort();
        }
    }
    
    thread::~thread()
    {
        debug("thread dtor");
    }
    
    void thread::prepare_wait()
    {
        _waiting = true;
    }
    
    void thread::wake()
    {
        if (!_waiting) {
            return;
        }
        _waiting = false;
        if (!_on_runqueue) {
            _on_runqueue = true;
            runqueue.push_back(this);
            schedule();
        }
    }
    
    void thread::main()
    {
        _func();
    }
    
    thread* thread::current()
    {
        return sched::s_current;
    }
    
    void thread::wait()
    {
        if (!_waiting) {
            return;
        }
        schedule();
    }
    
    void thread::stop_wait()
    {
        _waiting = false;
    }
    
    void init(elf::program& prog)
    {
        tls = prog.tls();
    }
    
    }