1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/tasks/schedule.hpp"
4
5#include <mos/lib/structures/hashmap.hpp>
6#include <mos/syslog/printk.hpp>
7#include <mos/tasks/kthread.hpp>
8#include <mos/tasks/process.hpp>
9#include <mos/tasks/task_types.hpp>
10#include <mos/tasks/thread.hpp>
11#include <mos/type_utils.hpp>
12#include <mos_stdlib.hpp>
13
14static Process *kthreadd;
15
16struct kthread_arg_t : mos::NamedType<"KThread.Arg">
17{
18 thread_entry_t entry;
19 void *arg;
20};
21
22static void kthread_entry(void *arg)
23{
24 kthread_arg_t *kthread_arg = static_cast<kthread_arg_t *>(arg);
25 kthread_arg->entry(kthread_arg->arg);
26 delete kthread_arg;
27 thread_exit(t: std::move(current_thread));
28}
29
30void kthread_init(void)
31{
32 kthreadd = Process::New(NULL, name: "kthreadd");
33 MOS_ASSERT_X(kthreadd->pid == 2, "kthreadd should have pid 2");
34 ProcessTable.insert(key: kthreadd->pid, value: kthreadd);
35}
36
37Thread *kthread_create(thread_entry_t entry, void *arg, const char *name)
38{
39 Thread *thread = kthread_create_no_sched(entry, arg, name);
40 scheduler_add_thread(thread);
41 return thread;
42}
43
44Thread *kthread_create_no_sched(thread_entry_t entry, void *arg, const char *name)
45{
46 MOS_ASSERT_X(kthreadd, "kthreadd not initialized");
47 pr_dinfo2(thread, "creating kernel thread '%s'", name);
48 kthread_arg_t *kthread_arg = mos::create<kthread_arg_t>();
49 kthread_arg->entry = entry;
50 kthread_arg->arg = arg;
51 auto thread = thread_new(owner: kthreadd, mode: THREAD_MODE_KERNEL, name, stack_size: 0, NULL);
52 if (thread.isErr())
53 {
54 delete kthread_arg;
55 pr_fatal("failed to create kernel thread");
56 return nullptr;
57 }
58
59 platform_context_setup_child_thread(thread: thread.get(), entry: kthread_entry, arg: kthread_arg);
60 thread_complete_init(thread: thread.get());
61 return thread.get();
62}
63