1/*
2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors.
3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com>
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef _KERNEL_TASKING_THREAD_H
10#define _KERNEL_TASKING_THREAD_H
11
12#include <drivers/generic/fpu.h>
13#include <fs/vfs.h>
14#include <libkern/lock.h>
15#include <libkern/types.h>
16#include <platform/generic/tasking/context.h>
17#include <platform/generic/tasking/trapframe.h>
18#include <tasking/signal.h>
19#include <time/time_manager.h>
20
21enum THREAD_STATUS {
22 THREAD_STATUS_INVALID = 0,
23 THREAD_STATUS_ALLOCATED,
24 THREAD_STATUS_RUNNING,
25 THREAD_STATUS_STOPPED,
26 THREAD_STATUS_BLOCKED,
27 THREAD_STATUS_DYING,
28};
29
30struct thread;
31struct blocker {
32 int reason;
33 int (*should_unblock)(struct thread* p);
34 bool should_unblock_for_signal;
35};
36typedef struct blocker blocker_t;
37
38enum BLOCKER_REASON {
39 BLOCKER_INVALID,
40 BLOCKER_JOIN,
41 BLOCKER_READ,
42 BLOCKER_WRITE,
43 BLOCKER_SLEEP,
44 BLOCKER_SELECT,
45 BLOCKER_DUMPING,
46 BLOCKER_STOP, // Just waiting for signal which will continue the thread.
47};
48
49struct blocker_join {
50 struct thread* joinee;
51 int join_pid;
52};
53typedef struct blocker_join blocker_join_t;
54
55struct blocker_rw {
56 file_descriptor_t* fd;
57};
58typedef struct blocker_rw blocker_rw_t;
59
60struct blocker_sleep {
61 time_t until;
62};
63typedef struct blocker_sleep blocker_sleep_t;
64
65struct blocker_select {
66 int nfds;
67 fd_set_t readfds;
68 fd_set_t writefds;
69 fd_set_t exceptfds;
70};
71typedef struct blocker_select blocker_select_t;
72
73struct proc;
74struct thread {
75 struct proc* process;
76 pid_t tid;
77 uint32_t status;
78
79 /* Kernel data */
80 kmemzone_t kstack;
81 context_t* context; // context of kernel's registers
82 trapframe_t* tf;
83 fpu_state_t* fpu_state;
84
85 /* Scheduler data */
86 struct thread* sched_prev;
87 struct thread* sched_next;
88 int last_cpu;
89 time_t ticks_until_preemption;
90 time_t start_time_in_ticks; // Time when the task was put to run.
91
92 /* Blocker data */
93 blocker_t blocker;
94 union {
95 blocker_join_t join;
96 blocker_rw_t rw;
97 blocker_sleep_t sleep;
98 blocker_select_t select;
99 } blocker_data;
100
101 /* Stat data */
102 time_t stat_total_running_ticks;
103
104 uint32_t signals_mask;
105 uint32_t pending_signals_mask;
106 void* signal_handlers[SIGNALS_CNT];
107};
108typedef struct thread thread_t;
109
110#define THREADS_PER_NODE (128)
111struct thread_list_node {
112 thread_t thread_storage[THREADS_PER_NODE];
113 struct thread_list_node* next;
114 int empty_spots;
115};
116typedef struct thread_list_node thread_list_node_t;
117
118struct thread_list {
119 struct thread_list_node* head;
120 struct thread_list_node* next_empty_node;
121 int next_empty_index;
122 lock_t lock;
123 struct thread_list_node* tail;
124};
125typedef struct thread_list thread_list_t;
126
127/**
128 * THREAD FUNCTIONS
129 */
130
131int thread_setup_main(struct proc* p, thread_t* thread);
132int thread_setup(struct proc* p, thread_t* thread);
133int thread_setup_kstack(thread_t* thread);
134int thread_copy_of(thread_t* thread, thread_t* from_thread);
135
136int thread_fill_up_stack(thread_t* thread, int argc, char** argv, int envc, char** envp);
137
138int thread_kstack_free(thread_t* thread);
139int thread_free(thread_t* thread);
140int thread_die(thread_t* thread);
141int thread_zombie(thread_t* thread);
142int thread_stop(thread_t* thread);
143int thread_stop_and_resched(thread_t* thread);
144int thread_continue(thread_t* thread);
145
146static ALWAYS_INLINE int thread_is_freed(thread_t* thread) { return (thread->status == THREAD_STATUS_INVALID); }
147static ALWAYS_INLINE int thread_is_alive(thread_t* thread) { return !thread_is_freed(thread); }
148
149/**
150 * BLOCKER FUNCTIONS
151 */
152
153int thread_init_blocker(thread_t* thread, const struct blocker* blocker);
154
155int init_join_blocker(thread_t* thread, int wait_for_pid);
156int init_read_blocker(thread_t* p, file_descriptor_t* bfd);
157int init_write_blocker(thread_t* thread, file_descriptor_t* bfd);
158int init_sleep_blocker(thread_t* thread, time_t time);
159int init_select_blocker(thread_t* thread, int nfds, fd_set_t* readfds, fd_set_t* writefds, fd_set_t* exceptfds, timeval_t* timeout);
160
161/**
162 * DEBUG FUNCTIONS
163 */
164
165int thread_dump_frame(thread_t* thread);
166int thread_print_backtrace();
167
168#endif /* _KERNEL_TASKING_THREAD_H */