source: mainline/kernel/generic/include/proc/thread.h@ 3fcea34

Last change on this file since 3fcea34 was 3fcea34, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 9 months ago

Simplify the SYS_THREAD_CREATE syscall interface

Removed the beefy uarg structure. Instead, the syscall gets two
parameters: %pc (program counter) and %sp (stack pointer). It starts
a thread with those values in corresponding registers, with no other
fuss whatsoever.

libc initializes threads by storing any other needed arguments on
the stack and retrieving them in thread_entry. Importantly, this
includes the address of the
thread_main function which is now
called indirectly to fix dynamic linking issues on some archs.

There's a bit of weirdness on SPARC and IA-64, because of their
stacked register handling. The current solution is that we require
some space *above* the stack pointer to be available for those
architectures. I think for SPARC, it can be made more normal.

For the remaining ones, we can (probably) just set the initial
%sp to the top edge of the stack. There's some lingering offsets
on some archs just because I didn't want to accidentally break
anything. The initial thread bringup should be functionally
unchanged from the previous state, and no binaries are currently
multithreaded except thread1 test, so there should be minimal
risk of breakage. Naturally, I tested all available emulator
builds, save for msim.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 * Copyright (c) 2001-2007 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_generic_proc
30 * @{
31 */
32/** @file
33 */
34
35#ifndef KERN_THREAD_H_
36#define KERN_THREAD_H_
37
38#include <synch/waitq.h>
39#include <proc/task.h>
40#include <time/timeout.h>
41#include <cpu.h>
42#include <synch/spinlock.h>
43#include <adt/odict.h>
44#include <mm/slab.h>
45#include <arch/cpu.h>
46#include <mm/tlb.h>
47#include <udebug/udebug.h>
48#include <abi/proc/thread.h>
49#include <abi/sysinfo.h>
50#include <arch.h>
51
52#define THREAD CURRENT->thread
53
54#define THREAD_NAME_BUFLEN 20
55
56extern const char *thread_states[];
57
58/* Thread flags */
59typedef enum {
60 THREAD_FLAG_NONE = 0,
61 /** Thread executes in user space. */
62 THREAD_FLAG_USPACE = (1 << 0),
63 /** Thread will be attached by the caller. */
64 THREAD_FLAG_NOATTACH = (1 << 1),
65 /** Thread accounting doesn't affect accumulated task accounting. */
66 THREAD_FLAG_UNCOUNTED = (1 << 2)
67} thread_flags_t;
68
69/** Thread structure. There is one per thread. */
70typedef struct thread {
71 atomic_refcount_t refcount;
72
73 link_t rq_link; /**< Run queue link. */
74 link_t wq_link; /**< Wait queue link. */
75 link_t th_link; /**< Links to threads within containing task. */
76
77 /** Link to @c threads ordered dictionary. */
78 odlink_t lthreads;
79
80 /** Tracking variable for thread_wait/thread_wakeup */
81 atomic_int sleep_state;
82
83 /**
84 * If true, the thread is terminating.
85 * It will not go to sleep in interruptible synchronization functions
86 * and will call thread_exit() before returning to userspace.
87 */
88 volatile bool interrupted;
89
90 /** Wait queue in which this thread sleeps. Used for debug printouts. */
91 _Atomic(waitq_t *) sleep_queue;
92
93 /** Waitq for thread_join_timeout(). */
94 waitq_t join_wq;
95
96 /** Thread accounting. */
97 atomic_time_stat_t ucycles;
98 atomic_time_stat_t kcycles;
99
100 /** Architecture-specific data. */
101 thread_arch_t arch;
102
103#ifdef CONFIG_UDEBUG
104 /**
105 * If true, the scheduler will print a stack trace
106 * to the kernel console upon scheduling this thread.
107 */
108 atomic_int_fast8_t btrace;
109
110 /** Debugging stuff */
111 udebug_thread_t udebug;
112#endif /* CONFIG_UDEBUG */
113
114 /*
115 * Immutable fields.
116 *
117 * These fields are only modified during initialization, and are not
118 * changed at any time between initialization and destruction.
119 * Can be accessed without synchronization in most places.
120 */
121
122 /** Thread ID. */
123 thread_id_t tid;
124
125 /** Function implementing the thread. */
126 void (*thread_code)(void *);
127 /** Argument passed to thread_code() function. */
128 void *thread_arg;
129
130 char name[THREAD_NAME_BUFLEN];
131
132 /** Thread is executed in user space. */
133 bool uspace;
134
135 /** Thread doesn't affect accumulated accounting. */
136 bool uncounted;
137
138 /** Containing task. */
139 task_t *task;
140
141 /** Thread's kernel stack. */
142 uint8_t *kstack;
143
144 /*
145 * Local fields.
146 *
147 * These fields can be safely accessed from code that _controls execution_
148 * of this thread. Code controls execution of a thread if either:
149 * - it runs in the context of said thread AND interrupts are disabled
150 * (interrupts can and will access these fields)
151 * - the thread is not running, and the code accessing it can legally
152 * add/remove the thread to/from a runqueue, i.e., either:
153 * - it is allowed to enqueue thread in a new runqueue
154 * - it holds the lock to the runqueue containing the thread
155 *
156 */
157
158 /**
159 * From here, the stored context is restored
160 * when the thread is scheduled.
161 */
162 context_t saved_context;
163
164 // TODO: we only need one of the two bools below
165
166 /**
167 * True if this thread is executing copy_from_uspace().
168 * False otherwise.
169 */
170 bool in_copy_from_uspace;
171
172 /**
173 * True if this thread is executing copy_to_uspace().
174 * False otherwise.
175 */
176 bool in_copy_to_uspace;
177
178 /*
179 * FPU context is a special case. If lazy FPU switching is disabled,
180 * it acts as a regular local field. However, if lazy switching is enabled,
181 * the context is synchronized via CPU->fpu_lock
182 */
183#ifdef CONFIG_FPU
184 fpu_context_t fpu_context;
185#endif
186 bool fpu_context_exists;
187
188 /* The thread will not be migrated if nomigrate is non-zero. */
189 unsigned int nomigrate;
190
191 /** Thread was migrated to another CPU and has not run yet. */
192 bool stolen;
193
194 /**
195 * Thread state (state_t).
196 * This is atomic because we read it via some commands for debug output,
197 * otherwise it could just be a regular local.
198 */
199 atomic_int_fast32_t state;
200
201 /** Thread CPU. */
202 _Atomic(cpu_t *) cpu;
203
204 /** Thread's priority. Implemented as index to CPU->rq */
205 atomic_int_fast32_t priority;
206
207 /** Last sampled cycle. */
208 uint64_t last_cycle;
209} thread_t;
210
211IRQ_SPINLOCK_EXTERN(threads_lock);
212extern odict_t threads;
213
214extern void thread_init(void);
215extern thread_t *thread_create(void (*)(void *), void *, task_t *,
216 thread_flags_t, const char *);
217extern void thread_wire(thread_t *, cpu_t *);
218extern void thread_attach(thread_t *, task_t *);
219extern void thread_start(thread_t *);
220extern void thread_requeue_sleeping(thread_t *);
221extern void thread_exit(void) __attribute__((noreturn));
222extern void thread_interrupt(thread_t *);
223
224enum sleep_state {
225 SLEEP_INITIAL,
226 SLEEP_ASLEEP,
227 SLEEP_WOKE,
228};
229
230typedef enum {
231 THREAD_OK,
232 THREAD_TERMINATING,
233} thread_termination_state_t;
234
235typedef enum {
236 THREAD_WAIT_SUCCESS,
237 THREAD_WAIT_TIMEOUT,
238} thread_wait_result_t;
239
240extern thread_termination_state_t thread_wait_start(void);
241extern thread_wait_result_t thread_wait_finish(deadline_t);
242extern void thread_wakeup(thread_t *);
243
244static inline thread_t *thread_ref(thread_t *thread)
245{
246 refcount_up(&thread->refcount);
247 return thread;
248}
249
250static inline thread_t *thread_try_ref(thread_t *thread)
251{
252 if (refcount_try_up(&thread->refcount))
253 return thread;
254 else
255 return NULL;
256}
257
258extern void thread_put(thread_t *);
259
260#ifndef thread_create_arch
261extern errno_t thread_create_arch(thread_t *, thread_flags_t);
262#endif
263
264#ifndef thr_constructor_arch
265extern void thr_constructor_arch(thread_t *);
266#endif
267
268#ifndef thr_destructor_arch
269extern void thr_destructor_arch(thread_t *);
270#endif
271
272extern void thread_sleep(uint32_t);
273extern void thread_usleep(uint32_t);
274
275extern errno_t thread_join(thread_t *);
276extern errno_t thread_join_timeout(thread_t *, uint32_t, unsigned int);
277extern void thread_detach(thread_t *);
278
279extern void thread_yield(void);
280
281extern void thread_print_list(bool);
282extern thread_t *thread_find_by_id(thread_id_t);
283extern size_t thread_count(void);
284extern thread_t *thread_first(void);
285extern thread_t *thread_next(thread_t *);
286extern void thread_update_accounting(bool);
287extern thread_t *thread_try_get(thread_t *);
288
289extern void thread_migration_disable(void);
290extern void thread_migration_enable(void);
291
292#ifdef CONFIG_UDEBUG
293extern void thread_stack_trace(thread_id_t);
294#endif
295
296/** Fpu context slab cache. */
297extern slab_cache_t *fpu_context_cache;
298
299/* Thread syscall prototypes. */
300extern sys_errno_t sys_thread_create(uspace_ptr_uspace_arg_t, uspace_ptr_char, size_t,
301 uspace_ptr_thread_id_t);
302extern sys_errno_t sys_thread_exit(int);
303extern sys_errno_t sys_thread_get_id(uspace_ptr_thread_id_t);
304extern sys_errno_t sys_thread_usleep(uint32_t);
305extern sys_errno_t sys_thread_udelay(uint32_t);
306
307#endif
308
309/** @}
310 */
Note: See TracBrowser for help on using the repository browser.