Преглед на файлове

refactor(thread): remove thdlist and some ctors

greatbridf преди 1 година
родител
ревизия
247863ce35
променени са 5 файла, в които са добавени 216 реда и са изтрити 278 реда
  1. 6 2
      include/kernel/event/evtqueue.hpp
  2. 188 261
      include/kernel/process.hpp
  3. 1 1
      src/kernel/event/event.cpp
  4. 15 9
      src/kernel/process.cpp
  5. 6 5
      src/kernel/syscall.cpp

+ 6 - 2
include/kernel/event/evtqueue.hpp

@@ -4,14 +4,18 @@
 #include <types/list.hpp>
 #include <types/lock.hpp>
 
+namespace kernel {
+
+namespace tasks {
+
 // declaration in kernel/process.hpp
 struct thread;
 
-namespace kernel {
+} // namespace tasks
 
 class cond_var : public types::non_copyable {
 private:
-    using list_type = types::list<thread*>;
+    using list_type = types::list<tasks::thread*>;
 
     types::mutex m_mtx;
     list_type m_subscribers;

+ 188 - 261
include/kernel/process.hpp

@@ -24,13 +24,18 @@
 #include <types/types.h>
 
 class process;
+
+namespace kernel::tasks {
+
 struct thread;
 
+} // namespace kernel::tasks
+
 class proclist;
 class readyqueue;
 
 inline process* volatile current_process;
-inline thread* volatile current_thread;
+inline kernel::tasks::thread* volatile current_thread;
 inline proclist* procs;
 inline readyqueue* readythds;
 
@@ -47,6 +52,8 @@ struct thread_attr {
     uint32_t wait : 1;
 };
 
+namespace kernel::tasks {
+
 struct thread {
 private:
     void alloc_kstack(void);
@@ -55,290 +62,233 @@ private:
 public:
     uint32_t* esp;
     uint32_t pkstack;
-    process* owner;
+    pid_t owner;
     thread_attr attr;
 
-    explicit inline thread(process* _owner, bool system)
-        : owner { _owner }
-        , attr {
-            .system = system,
-            .ready = 1,
-            .wait = 0,
-        }
+    explicit inline thread(pid_t owner)
+        : owner { owner }
+        , attr { .system = 1, .ready = 1, .wait = 0, }
     {
         alloc_kstack();
     }
 
-    constexpr thread(thread&& val)
-        : esp { std::exchange(val.esp, nullptr) }
-        , pkstack { std::exchange(val.pkstack, 0) }
-        , owner { std::exchange(val.owner, nullptr) }
-        , attr { std::exchange(val.attr, {}) } { }
-
-    inline thread(const thread& val)
-        : owner { val.owner }
-        , attr { val.attr }
+    inline thread(const thread& val, pid_t owner)
+        : owner { owner } , attr { val.attr }
     {
         alloc_kstack();
     }
 
-    inline thread(const thread& thd, process* new_parent)
-        : thread { thd }
-    {
-        owner = new_parent;
-    }
+    constexpr thread(thread&& val) = default;
+    inline ~thread() { free_kstack(pkstack); }
 
-    constexpr ~thread()
-    {
-        if (pkstack)
-            free_kstack(pkstack);
-    }
+    constexpr bool operator==(const thread& rhs) const
+    { return pkstack == rhs.pkstack; }
+    constexpr bool operator<(const thread& rhs) const
+    { return pkstack < rhs.pkstack; }
 };
 
-class thdlist {
+}
+
+class filearr {
 public:
-    using list_type = types::list<thread>;
+    using container_type = types::list<fs::file>;
+    using array_type = std::map<int, container_type::iterator_type>;
 
 private:
-    list_type thds;
+    inline static container_type* files;
+    array_type arr;
 
 public:
-    constexpr thdlist(const thdlist& obj) = delete;
-    constexpr thdlist(thdlist&& obj) = delete;
-
-    constexpr thdlist& operator=(const thdlist& obj) = delete;
-    constexpr thdlist& operator=(thdlist&& obj) = delete;
-
-    constexpr thdlist(thdlist&& obj, process* new_parent)
-        : thds { std::move(obj.thds) }
+    inline static void init_global_file_container(void)
     {
-        for (auto& thd : thds)
-            thd.owner = new_parent;
+        files = new container_type;
     }
 
-    explicit constexpr thdlist(void) = default;
-
-    // implementation is below
-    constexpr ~thdlist();
-
-    template <typename... Args>
-    constexpr thread& Emplace(Args&&... args)
+private:
+    // iter should not be nullptr
+    constexpr void _close(container_type::iterator_type iter)
     {
-        return *thds.emplace_back(std::forward<Args>(args)...);
-    }
+        if (iter->ref == 1) {
+            if (iter->type == fs::file::types::pipe) {
+                assert(iter->flags.read | iter->flags.write);
+                if (iter->flags.read)
+                    iter->ptr.pp->close_read();
+                else
+                    iter->ptr.pp->close_write();
+
+                if (iter->ptr.pp->is_free())
+                    delete iter->ptr.pp;
+            }
 
-    constexpr size_t size(void) const
-    {
-        return thds.size();
+            files->erase(iter);
+        } else
+            --iter->ref;
     }
 
-    constexpr list_type& underlying_list(void)
+    constexpr int _next_fd(void) const
     {
-        return thds;
-    }
-};
-
-class process {
-public:
-    class filearr {
-    public:
-        using container_type = types::list<fs::file>;
-        using array_type = std::map<int, container_type::iterator_type>;
-
-    private:
-        inline static container_type* files;
-        array_type arr;
-
-    public:
-        inline static void init_global_file_container(void)
-        {
-            files = new container_type;
-        }
+        int fd = 0;
 
-    private:
-        // iter should not be nullptr
-        constexpr void _close(container_type::iterator_type iter)
-        {
-            if (iter->ref == 1) {
-                if (iter->type == fs::file::types::pipe) {
-                    assert(iter->flags.read | iter->flags.write);
-                    if (iter->flags.read)
-                        iter->ptr.pp->close_read();
-                    else
-                        iter->ptr.pp->close_write();
-
-                    if (iter->ptr.pp->is_free())
-                        delete iter->ptr.pp;
-                }
-
-                files->erase(iter);
-            } else
-                --iter->ref;
+        for (auto [ item_fd, iter_file ] : arr) {
+            if (item_fd == fd)
+                ++fd;
         }
 
-        constexpr int _next_fd(void) const
-        {
-            int fd = 0;
+        return fd;
+    }
 
-            for (auto [ item_fd, iter_file ] : arr) {
-                if (item_fd == fd)
-                    ++fd;
-            }
+public:
+    constexpr filearr(const filearr&) = delete;
+    constexpr filearr& operator=(const filearr&) = delete;
+    constexpr filearr& operator=(filearr&&) = delete;
+    constexpr filearr(void) = default;
+    constexpr filearr(filearr&& val) = default;
 
-            return fd;
-        }
+    constexpr int dup(int old_fd)
+    {
+        return dup2(old_fd, _next_fd());
+    }
 
-    public:
-        constexpr filearr(const filearr&) = delete;
-        constexpr filearr& operator=(const filearr&) = delete;
-        constexpr filearr& operator=(filearr&&) = delete;
-        constexpr filearr(void) = default;
-        constexpr filearr(filearr&& val)
-            : arr { std::move(val.arr) } { }
-
-        constexpr int dup(int old_fd)
-        {
-            return dup2(old_fd, _next_fd());
-        }
+    // TODO: the third parameter should be int flags
+    //       determining whether the fd should be closed
+    //       after exec() (FD_CLOEXEC)
+    constexpr int dup2(int old_fd, int new_fd)
+    {
+        close(new_fd);
 
-        // TODO: the third parameter should be int flags
-        //       determining whether the fd should be closed
-        //       after exec() (FD_CLOEXEC)
-        constexpr int dup2(int old_fd, int new_fd)
-        {
-            close(new_fd);
+        auto iter = arr.find(old_fd);
+        if (!iter)
+            return -EBADF;
 
-            auto iter = arr.find(old_fd);
-            if (!iter)
-                return -EBADF;
+        auto [ _, iter_file ] = *iter;
 
-            auto [ _, iter_file ] = *iter;
+        this->arr.emplace(new_fd, iter_file);
+        ++iter_file->ref;
+        return new_fd;
+    }
 
-            this->arr.emplace(new_fd, iter_file);
+    constexpr void dup_all(const filearr& orig)
+    {
+        for (auto [ fd, iter_file ] : orig.arr) {
+            this->arr.emplace(fd, iter_file);
             ++iter_file->ref;
-            return new_fd;
         }
+    }
 
-        constexpr void dup_all(const filearr& orig)
-        {
-            for (auto [ fd, iter_file ] : orig.arr) {
-                this->arr.emplace(fd, iter_file);
-                ++iter_file->ref;
-            }
-        }
+    constexpr fs::file* operator[](int i) const
+    {
+        auto iter = arr.find(i);
+        if (!iter)
+            return nullptr;
+        return &iter->second;
+    }
 
-        constexpr fs::file* operator[](int i) const
-        {
-            auto iter = arr.find(i);
-            if (!iter)
-                return nullptr;
-            return &iter->second;
-        }
+    int pipe(int pipefd[2])
+    {
+        // TODO: set read/write flags
+        auto* pipe = new fs::pipe;
+
+        auto iter = files->emplace_back(fs::file {
+            fs::file::types::pipe,
+            { .pp = pipe },
+            nullptr,
+            0,
+            1,
+            {
+                .read = 1,
+                .write = 0,
+            },
+        });
+
+        bool inserted = false;
+        int fd = _next_fd();
+        std::tie(std::ignore, inserted) =
+            arr.insert(std::make_pair(fd, iter));
+        assert(inserted);
 
-        int pipe(int pipefd[2])
-        {
-            // TODO: set read/write flags
-            auto* pipe = new fs::pipe;
-
-            auto iter = files->emplace_back(fs::file {
-                fs::file::types::pipe,
-                { .pp = pipe },
-                nullptr,
-                0,
-                1,
-                {
-                    .read = 1,
-                    .write = 0,
-                },
-            });
-
-            bool inserted = false;
-            int fd = _next_fd();
-            std::tie(std::ignore, inserted) =
-                arr.insert(std::make_pair(fd, iter));
-            assert(inserted);
-
-            // TODO: use copy_to_user()
-            pipefd[0] = fd;
-
-            iter = files->emplace_back(fs::file {
-                fs::file::types::pipe,
-                { .pp = pipe },
-                nullptr,
-                0,
-                1,
-                {
-                    .read = 0,
-                    .write = 1,
-                },
-            });
-            fd = _next_fd();
-            std::tie(std::ignore, inserted) = arr.emplace(fd, iter);
-            assert(inserted);
-
-            // TODO: use copy_to_user()
-            pipefd[1] = fd;
-
-            return 0;
-        }
+        // TODO: use copy_to_user()
+        pipefd[0] = fd;
+
+        iter = files->emplace_back(fs::file {
+            fs::file::types::pipe,
+            { .pp = pipe },
+            nullptr,
+            0,
+            1,
+            {
+                .read = 0,
+                .write = 1,
+            },
+        });
+        fd = _next_fd();
+        std::tie(std::ignore, inserted) = arr.emplace(fd, iter);
+        assert(inserted);
 
-        // TODO: file opening permissions check
-        int open(const char* filename, uint32_t flags)
-        {
-            auto* dentry = fs::vfs_open(filename);
+        // TODO: use copy_to_user()
+        pipefd[1] = fd;
 
-            if (!dentry) {
-                errno = ENOTFOUND;
-                return -1;
-            }
+        return 0;
+    }
 
-            // check whether dentry is a file if O_DIRECTORY is set
-            if ((flags & O_DIRECTORY) && !dentry->ind->flags.in.directory) {
-                errno = ENOTDIR;
-                return -1;
-            }
+    // TODO: file opening permissions check
+    int open(const char* filename, uint32_t flags)
+    {
+        auto* dentry = fs::vfs_open(filename);
 
-            auto iter = files->emplace_back(fs::file {
-                fs::file::types::ind,
-                { .ind = dentry->ind },
-                dentry->parent,
-                0,
-                1,
-                {
-                    .read = !!(flags & (O_RDONLY | O_RDWR)),
-                    .write = !!(flags & (O_WRONLY | O_RDWR)),
-                },
-            });
-
-            int fd = _next_fd();
-            auto [ _, inserted ] = arr.emplace(fd, iter);
-            assert(inserted);
-            return fd;
+        if (!dentry) {
+            errno = ENOTFOUND;
+            return -1;
         }
 
-        constexpr void close(int fd)
-        {
-            auto iter = arr.find(fd);
-            if (!iter)
-                return;
-
-            _close(iter->second);
-            arr.erase(iter);
+        // check whether dentry is a file if O_DIRECTORY is set
+        if ((flags & O_DIRECTORY) && !dentry->ind->flags.in.directory) {
+            errno = ENOTDIR;
+            return -1;
         }
 
-        constexpr void close_all(void)
-        {
-            for (auto&& [ fd, file ] : arr)
-                _close(file);
-            arr.clear();
-        }
+        auto iter = files->emplace_back(fs::file {
+            fs::file::types::ind,
+            { .ind = dentry->ind },
+            dentry->parent,
+            0,
+            1,
+            {
+                .read = !!(flags & (O_RDONLY | O_RDWR)),
+                .write = !!(flags & (O_WRONLY | O_RDWR)),
+            },
+        });
+
+        int fd = _next_fd();
+        auto [ _, inserted ] = arr.emplace(fd, iter);
+        assert(inserted);
+        return fd;
+    }
 
-        constexpr ~filearr()
-        {
-            close_all();
-        }
-    };
+    constexpr void close(int fd)
+    {
+        auto iter = arr.find(fd);
+        if (!iter)
+            return;
 
+        _close(iter->second);
+        arr.erase(iter);
+    }
+
+    constexpr void close_all(void)
+    {
+        for (auto&& [ fd, file ] : arr)
+            _close(file);
+        arr.clear();
+    }
+
+    constexpr ~filearr()
+    {
+        close_all();
+    }
+};
+
+class process {
+public:
     struct wait_obj {
         pid_t pid;
         int code;
@@ -346,7 +296,7 @@ public:
 
 public:
     mutable kernel::mm_list mms;
-    thdlist thds;
+    std::set<kernel::tasks::thread> thds;
     kernel::cond_var cv_wait;
     types::list<wait_obj> waitlist;
     process_attr attr;
@@ -363,25 +313,7 @@ public:
     std::set<pid_t> children;
 
 public:
-    // if waitlist is not empty or mutex in cv_wait
-    // is locked, its behavior is undefined
-    constexpr process(process&& val)
-        : mms(std::move(val.mms))
-        , thds { std::move(val.thds), this }
-        , attr { val.attr }
-        , files(std::move(val.files))
-        , pwd(std::move(val.pwd))
-        , pid(val.pid)
-        , ppid(val.ppid)
-        , pgid(val.pgid)
-        , sid(val.sid)
-        , control_tty(val.control_tty)
-        , children(std::move(val.children))
-    {
-        if (current_process == &val)
-            current_process = this;
-    }
-
+    process(const process&) = delete;
     explicit process(const process& parent, pid_t pid);
 
     // this function is used for system initialization
@@ -494,6 +426,8 @@ public:
 
 class readyqueue final {
 public:
+    using thread = kernel::tasks::thread;
+
     using list_type = types::list<thread*>;
     using iterator_type = list_type::iterator_type;
     using const_iterator_type = list_type::const_iterator_type;
@@ -556,13 +490,6 @@ constexpr uint32_t push_stack(uint32_t** stack, uint32_t val)
     return val;
 }
 
-// class thdlist
-constexpr thdlist::~thdlist()
-{
-    for (auto iter = thds.begin(); iter != thds.end(); ++iter)
-        readythds->remove_all(&iter);
-}
-
 void k_new_thread(void (*func)(void*), void* data);
 
 void NORETURN freeze(void);

+ 1 - 1
src/kernel/event/event.cpp

@@ -48,7 +48,7 @@ void dispatch_event(void)
 
 bool kernel::cond_var::wait(types::mutex& lock)
 {
-    thread* thd = current_thread;
+    kernel::tasks::thread* thd = current_thread;
 
     current_thread->attr.ready = 0;
     current_thread->attr.wait = 1;

+ 15 - 9
src/kernel/process.cpp

@@ -50,7 +50,7 @@ struct no_irq_guard {
 
 static types::bitmap* pkstack_bmp;
 
-void thread::alloc_kstack(void)
+void kernel::tasks::thread::alloc_kstack(void)
 {
     static int __allocated;
     if (!pkstack_bmp)
@@ -84,7 +84,7 @@ void thread::alloc_kstack(void)
     ++__allocated;
 }
 
-void thread::free_kstack(uint32_t p)
+void kernel::tasks::thread::free_kstack(uint32_t p)
 {
     p -= 0xffc00000;
     p /= THREAD_KERNEL_STACK_SIZE;
@@ -123,7 +123,7 @@ void proclist::kill(pid_t pid, int exit_code)
     auto& proc = this->find(pid);
 
     // remove threads from ready list
-    for (auto& thd : proc.thds.underlying_list()) {
+    for (auto& thd : proc.thds) {
         thd.attr.ready = 0;
         readythds->remove_all(&thd);
     }
@@ -218,7 +218,9 @@ void NORETURN _kernel_init(void)
     assert(proc.pid == 2);
 
     // create thread
-    thread thd(&proc, true);
+    auto [ iter_thd, inserted] = proc.thds.emplace(proc.pid);
+    assert(inserted);
+    auto& thd = *iter_thd;
 
     auto* esp = &thd.esp;
 
@@ -235,7 +237,7 @@ void NORETURN _kernel_init(void)
     // eflags
     push_stack(esp, 0x200);
 
-    readythds->push(&proc.thds.Emplace(std::move(thd)));
+    readythds->push(&thd);
 
     // ------------------------------------------
 
@@ -319,12 +321,16 @@ void NORETURN init_scheduler(void)
     procs = new proclist;
     readythds = new readyqueue;
 
-    process::filearr::init_global_file_container();
+    filearr::init_global_file_container();
 
     // init process has no parent
     auto& init = procs->emplace(0);
     assert(init.pid == 1);
 
+    auto [ iter_thd, inserted ] = init.thds.emplace(init.pid);
+    assert(inserted);
+    auto& thd = *iter_thd;
+
     init.files.open("/dev/console", O_RDONLY);
     init.files.open("/dev/console", O_WRONLY);
     init.files.open("/dev/console", O_WRONLY);
@@ -334,7 +340,7 @@ void NORETURN init_scheduler(void)
     asm_cli();
 
     current_process = &init;
-    current_thread = &init.thds.Emplace(&init, true);
+    current_thread = &thd;
     readythds->push(current_thread);
 
     tss.ss0 = KERNEL_DATA_SEGMENT;
@@ -376,12 +382,12 @@ bool schedule()
 {
     auto thd = readythds->query();
     process* proc = nullptr;
-    thread* curr_thd = nullptr;
+    kernel::tasks::thread* curr_thd = nullptr;
 
     if (current_thread == thd)
         goto _end;
 
-    proc = thd->owner;
+    proc = &procs->find(thd->owner);
     if (current_process != proc) {
         asm_switch_pd(proc->mms.m_pd);
         current_process = proc;

+ 6 - 5
src/kernel/syscall.cpp

@@ -25,9 +25,11 @@ syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
 extern "C" void _syscall_stub_fork_return(void);
 int _syscall_fork(interrupt_stack* data)
 {
-    process& curproc = *current_process;
-    auto& newproc = procs->copy_from(curproc);
-    auto* newthd = &newproc.thds.Emplace(*current_thread, &newproc);
+    auto& newproc = procs->copy_from(*current_process);
+    auto [ iter_newthd, inserted ] = newproc.thds.emplace(*current_thread, newproc.pid);
+    assert(inserted);
+    auto* newthd = &*iter_newthd;
+
     readythds->push(newthd);
 
     // create fake interrupt stack
@@ -187,9 +189,8 @@ int NORETURN _syscall_exit(interrupt_stack* data)
     uint32_t exit_code = data->s_regs.edi;
 
     // TODO: terminating a thread only
-    if (current_thread->owner->thds.size() != 1) {
+    if (current_process->thds.size() != 1)
         assert(false);
-    }
 
     // terminating a whole process:
     procs->kill(current_process->pid, exit_code);