|  | @@ -5,6 +5,7 @@
 | 
	
		
			
				|  |  |  #include <stdint.h>
 | 
	
		
			
				|  |  |  #include <stdio.h>
 | 
	
		
			
				|  |  |  #include <bits/alltypes.h>
 | 
	
		
			
				|  |  | +#include <sys/wait.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <asm/port_io.h>
 | 
	
		
			
				|  |  |  #include <asm/sys.h>
 | 
	
	
		
			
				|  | @@ -19,6 +20,8 @@
 | 
	
		
			
				|  |  |  #include <kernel/signal.hpp>
 | 
	
		
			
				|  |  |  #include <kernel/vfs.hpp>
 | 
	
		
			
				|  |  |  #include <kernel/user/thread_local.hpp>
 | 
	
		
			
				|  |  | +#include <kernel/task/thread.hpp>
 | 
	
		
			
				|  |  | +#include <kernel/task/readyqueue.hpp>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <types/allocator.hpp>
 | 
	
		
			
				|  |  |  #include <types/bitmap.hpp>
 | 
	
	
		
			
				|  | @@ -220,7 +223,6 @@ process::process(pid_t pid, pid_t ppid)
 | 
	
		
			
				|  |  |      assert(inserted);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -using kernel::tasks::thread;
 | 
	
		
			
				|  |  |  using signo_type = kernel::signal_list::signo_type;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void process::send_signal(signo_type signal)
 | 
	
	
		
			
				|  | @@ -229,108 +231,6 @@ void process::send_signal(signo_type signal)
 | 
	
		
			
				|  |  |          thd.send_signal(signal);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static std::priority_queue<std::byte*> s_kstacks;
 | 
	
		
			
				|  |  | -thread::kernel_stack::kernel_stack()
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    static int allocated;
 | 
	
		
			
				|  |  | -    static types::mutex mtx;
 | 
	
		
			
				|  |  | -    types::lock_guard lck(mtx);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (!s_kstacks.empty()) {
 | 
	
		
			
				|  |  | -        stack_base = s_kstacks.top();
 | 
	
		
			
				|  |  | -        esp = (uint32_t*)stack_base;
 | 
	
		
			
				|  |  | -        s_kstacks.pop();
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // kernel stack pt is at page#0x00005
 | 
	
		
			
				|  |  | -    kernel::paccess pa(0x00005);
 | 
	
		
			
				|  |  | -    auto pt = (pt_t)pa.ptr();
 | 
	
		
			
				|  |  | -    assert(pt);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int cnt = THREAD_KERNEL_STACK_SIZE / PAGE_SIZE;
 | 
	
		
			
				|  |  | -    pte_t* pte = *pt + allocated * cnt;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (int i = 0; i < cnt; ++i) {
 | 
	
		
			
				|  |  | -        pte[i].v = 0x3;
 | 
	
		
			
				|  |  | -        pte[i].in.page = __alloc_raw_page();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    stack_base = (std::byte*)(0xffc00000 + THREAD_KERNEL_STACK_SIZE * (allocated + 1));
 | 
	
		
			
				|  |  | -    esp = (uint32_t*)stack_base;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    ++allocated;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -thread::kernel_stack::kernel_stack(const kernel_stack& other)
 | 
	
		
			
				|  |  | -    : kernel_stack()
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    auto offset = vptrdiff(other.stack_base, other.esp);
 | 
	
		
			
				|  |  | -    esp = (uint32_t*)(stack_base - offset);
 | 
	
		
			
				|  |  | -    memcpy(esp, other.esp, offset);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -thread::kernel_stack::kernel_stack(kernel_stack&& other)
 | 
	
		
			
				|  |  | -    : stack_base(std::exchange(other.stack_base, nullptr))
 | 
	
		
			
				|  |  | -    , esp(std::exchange(other.esp, nullptr)) { }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -thread::kernel_stack::~kernel_stack()
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    s_kstacks.push(stack_base);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void thread::sleep()
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    attr.ready = 0;
 | 
	
		
			
				|  |  | -    readythds->remove_all(this);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void thread::wakeup()
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    attr.ready = 1;
 | 
	
		
			
				|  |  | -    readythds->push(this);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void thread::send_signal(signo_type signal)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    if (signals.raise(signal))
 | 
	
		
			
				|  |  | -        this->wakeup();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int thread::set_thread_area(kernel::user::user_desc* ptr)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    if (ptr->read_exec_only && ptr->seg_not_present) {
 | 
	
		
			
				|  |  | -        void* dst = (void*)ptr->base_addr;
 | 
	
		
			
				|  |  | -        std::size_t len = ptr->limit;
 | 
	
		
			
				|  |  | -        if (len > 0 && dst)
 | 
	
		
			
				|  |  | -            memset(dst, 0x00, len);
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (ptr->entry_number == -1U)
 | 
	
		
			
				|  |  | -        ptr->entry_number = 6;
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    tls_desc.limit_low = ptr->limit & 0xFFFF;
 | 
	
		
			
				|  |  | -    tls_desc.base_low = ptr->base_addr & 0xFFFF;
 | 
	
		
			
				|  |  | -    tls_desc.base_mid = (ptr->base_addr >> 16) & 0xFF;
 | 
	
		
			
				|  |  | -    tls_desc.access = SD_TYPE_DATA_USER;
 | 
	
		
			
				|  |  | -    tls_desc.limit_high = (ptr->limit >> 16) & 0xF;
 | 
	
		
			
				|  |  | -    tls_desc.flags = (ptr->limit_in_pages << 3) | (ptr->seg_32bit << 2);
 | 
	
		
			
				|  |  | -    tls_desc.base_high = (ptr->base_addr >> 24) & 0xFF;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int thread::load_thread_area() const
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    if (tls_desc.flags == 0)
 | 
	
		
			
				|  |  | -        return -1;
 | 
	
		
			
				|  |  | -    kernel::user::load_thread_area(tls_desc);
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  void kernel_threadd_main(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      kmsg("kernel thread daemon started\n");
 | 
	
	
		
			
				|  | @@ -380,7 +280,8 @@ proclist::proclist()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      current_process = &init;
 | 
	
		
			
				|  |  |      current_thread = &thd;
 | 
	
		
			
				|  |  | -    readythds->push(current_thread);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    kernel::task::dispatcher::enqueue(current_thread);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      tss.ss0 = KERNEL_DATA_SEGMENT;
 | 
	
		
			
				|  |  |      tss.esp0 = (uint32_t)current_thread->kstack.esp;
 | 
	
	
		
			
				|  | @@ -414,7 +315,7 @@ proclist::proclist()
 | 
	
		
			
				|  |  |          // original esp
 | 
	
		
			
				|  |  |          push_stack(esp, old_esp);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        readythds->push(&thd);
 | 
	
		
			
				|  |  | +        kernel::task::dispatcher::enqueue(&thd);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -432,7 +333,7 @@ void proclist::kill(pid_t pid, int exit_code)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // put all threads into sleep
 | 
	
		
			
				|  |  |      for (auto& thd : proc.thds)
 | 
	
		
			
				|  |  | -        thd.sleep();
 | 
	
		
			
				|  |  | +        thd.set_attr(kernel::task::thread::ZOMBIE);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // write back mmap'ped files and close them
 | 
	
		
			
				|  |  |      proc.files.close_all();
 | 
	
	
		
			
				|  | @@ -456,31 +357,33 @@ void proclist::kill(pid_t pid, int exit_code)
 | 
	
		
			
				|  |  |      auto& init = this->find(1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      bool flag = false;
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        auto& mtx = init.cv_wait.mtx();
 | 
	
		
			
				|  |  | -        types::lock_guard lck(mtx);
 | 
	
		
			
				|  |  | +    if (1) {
 | 
	
		
			
				|  |  | +        types::lock_guard lck(init.mtx_waitprocs);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            auto& mtx = proc.cv_wait.mtx();
 | 
	
		
			
				|  |  | -            types::lock_guard lck(mtx);
 | 
	
		
			
				|  |  | +        if (1) {
 | 
	
		
			
				|  |  | +            types::lock_guard lck(proc.mtx_waitprocs);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            for (const auto& item : proc.waitlist) {
 | 
	
		
			
				|  |  | -                init.waitlist.push_back(item);
 | 
	
		
			
				|  |  | +            for (const auto& item : proc.waitprocs) {
 | 
	
		
			
				|  |  | +                if (WIFSTOPPED(item.code) || WIFCONTINUED(item.code))
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                init.waitprocs.push_back(item);
 | 
	
		
			
				|  |  |                  flag = true;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            proc.waitlist.clear();
 | 
	
		
			
				|  |  | +            proc.waitprocs.clear();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (flag)
 | 
	
		
			
				|  |  | -        init.cv_wait.notify();
 | 
	
		
			
				|  |  | +        init.waitlist.notify_all();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        auto& mtx = parent.cv_wait.mtx();
 | 
	
		
			
				|  |  | -        types::lock_guard lck(mtx);
 | 
	
		
			
				|  |  | -        parent.waitlist.push_back({ pid, exit_code });
 | 
	
		
			
				|  |  | +    if (1) {
 | 
	
		
			
				|  |  | +        types::lock_guard lck(parent.mtx_waitprocs);
 | 
	
		
			
				|  |  | +        parent.waitprocs.push_back({ pid, exit_code });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    parent.cv_wait.notify();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    parent.waitlist.notify_all();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void release_kinit()
 | 
	
	
		
			
				|  | @@ -551,7 +454,7 @@ void NORETURN _kernel_init(void)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      current_process->attr.system = 0;
 | 
	
		
			
				|  |  | -    current_thread->attr.system = 0;
 | 
	
		
			
				|  |  | +    current_thread->attr |= kernel::task::thread::SYSTEM;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      const char* argv[] = { "/mnt/busybox", "sh", "/mnt/initsh" };
 | 
	
		
			
				|  |  |      const char* envp[] = { "LANG=C", "HOME=/root", "PATH=/mnt", "PWD=/", nullptr };
 | 
	
	
		
			
				|  | @@ -601,7 +504,6 @@ void k_new_thread(void (*func)(void*), void* data)
 | 
	
		
			
				|  |  |  SECTION(".text.kinit")
 | 
	
		
			
				|  |  |  void NORETURN init_scheduler(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    readythds = new readyqueue;
 | 
	
		
			
				|  |  |      procs = new proclist;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      asm volatile(
 | 
	
	
		
			
				|  | @@ -636,9 +538,9 @@ void NORETURN init_scheduler(void)
 | 
	
		
			
				|  |  |  extern "C" void asm_ctx_switch(uint32_t** curr_esp, uint32_t** next_esp);
 | 
	
		
			
				|  |  |  bool schedule()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    auto next_thd = readythds->query();
 | 
	
		
			
				|  |  | +    auto* next_thd = kernel::task::dispatcher::next();
 | 
	
		
			
				|  |  |      process* proc = nullptr;
 | 
	
		
			
				|  |  | -    kernel::tasks::thread* curr_thd = nullptr;
 | 
	
		
			
				|  |  | +    kernel::task::thread* curr_thd = nullptr;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (current_thread == next_thd)
 | 
	
		
			
				|  |  |          goto _end;
 |