xref: /aosp_15_r20/external/coreboot/src/include/thread.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef THREAD_H_
3 #define THREAD_H_
4 
5 #include <arch/cpu.h>
6 #include <bootstate.h>
7 #include <types.h>
8 
9 struct thread_mutex {
10 	bool locked;
11 };
12 
13 enum thread_state {
14 	THREAD_UNINITIALIZED,
15 	THREAD_STARTED,
16 	THREAD_DONE,
17 };
18 
19 struct thread_handle {
20 	enum thread_state state;
21 	/* Only valid when state == THREAD_DONE */
22 	enum cb_err error;
23 };
24 
25 /* Run func(arg) on a new thread. Return 0 on successful start of thread, < 0
26  * when thread could not be started. The thread handle if populated, will
27  * reflect the state and return code of the thread.
28  */
29 int thread_run(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg);
30 
31 /* thread_run_until is the same as thread_run() except that it blocks state
32  * transitions from occurring in the (state, seq) pair of the boot state
33  * machine. */
34 int thread_run_until(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg,
35 		     boot_state_t state, boot_state_sequence_t seq);
36 
37 /* Waits until the thread has terminated and returns the error code */
38 enum cb_err thread_join(struct thread_handle *handle);
39 
40 #if ENV_SUPPORTS_COOP
41 
42 struct thread {
43 	int id;
44 	uintptr_t stack_current;
45 	uintptr_t stack_orig;
46 	struct thread *next;
47 	enum cb_err (*entry)(void *);
48 	void *entry_arg;
49 	int can_yield;
50 	struct thread_handle *handle;
51 };
52 
53 /* Return 0 on successful yield, < 0 when thread did not yield. */
54 int thread_yield(void);
55 
56 /* Return 0 on successful yield for the given amount of time, < 0 when thread
57  * did not yield. */
58 int thread_yield_microseconds(unsigned int microsecs);
59 
60 /* Allow and prevent thread cooperation on current running thread. By default
61  * all threads are marked to be cooperative. That means a thread can yield
62  * to another thread at a pre-determined switch point. i.e., udelay,
63  * thread_yield, or thread_yield_microseconds.
64  *
65  * These methods should be used to guard critical sections so a dead lock does
66  * not occur. The critical sections can be nested. Just make sure the methods
67  * are used in pairs.
68  */
69 void thread_coop_enable(void);
70 void thread_coop_disable(void);
71 
72 void thread_mutex_lock(struct thread_mutex *mutex);
73 void thread_mutex_unlock(struct thread_mutex *mutex);
74 
75 /* Architecture specific thread functions. */
76 asmlinkage void switch_to_thread(uintptr_t new_stack, uintptr_t *saved_stack);
77 /* Set up the stack frame for a new thread so that a switch_to_thread() call
78  * will enter the thread_entry() function with arg as a parameter. The
79  * saved_stack field in the struct thread needs to be updated accordingly. */
80 void arch_prepare_thread(struct thread *t,
81 			 asmlinkage void (*thread_entry)(void *), void *arg);
82 #else
thread_yield(void)83 static inline int thread_yield(void)
84 {
85 	return -1;
86 }
thread_yield_microseconds(unsigned int microsecs)87 static inline int thread_yield_microseconds(unsigned int microsecs)
88 {
89 	return -1;
90 }
thread_coop_enable(void)91 static inline void thread_coop_enable(void) {}
thread_coop_disable(void)92 static inline void thread_coop_disable(void) {}
93 
thread_mutex_lock(struct thread_mutex * mutex)94 static inline void thread_mutex_lock(struct thread_mutex *mutex) {}
95 
thread_mutex_unlock(struct thread_mutex * mutex)96 static inline void thread_mutex_unlock(struct thread_mutex *mutex) {}
97 #endif
98 
99 #endif /* THREAD_H_ */
100