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 | |
14 | static Process *kthreadd; |
15 | |
16 | struct kthread_arg_t : mos::NamedType<"KThread.Arg" > |
17 | { |
18 | thread_entry_t entry; |
19 | void *arg; |
20 | }; |
21 | |
22 | static 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 | |
30 | void 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 | |
37 | Thread *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 | |
44 | Thread *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 | |