blob: 19b69fa30d5a2b71c3bed4ceecbd5f3922a531ea [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin4409a5e2013-05-06 12:20:52 -05002#ifndef THREAD_H_
3#define THREAD_H_
4
Aaron Durbin4409a5e2013-05-06 12:20:52 -05005#include <arch/cpu.h>
Raul E Rangelcc01da52021-07-12 13:43:48 -06006#include <bootstate.h>
7#include <commonlib/bsd/cb_err.h>
Raul E Rangela3b29072021-11-05 16:58:12 -06008#include <types.h>
Aaron Durbin4409a5e2013-05-06 12:20:52 -05009
Raul E Rangelb29f9d42021-07-12 13:49:59 -060010struct thread_mutex {
11 bool locked;
12};
13
Raul E Rangelcc01da52021-07-12 13:43:48 -060014enum thread_state {
15 THREAD_UNINITIALIZED,
16 THREAD_STARTED,
17 THREAD_DONE,
18};
19
20struct thread_handle {
21 enum thread_state state;
22 /* Only valid when state == THREAD_DONE */
23 enum cb_err error;
24};
25
Raul E Rangel5dd76022021-07-15 13:26:52 -060026/* Run func(arg) on a new thread. Return 0 on successful start of thread, < 0
27 * when thread could not be started. The thread handle if populated, will
28 * reflect the state and return code of the thread.
29 */
30int thread_run(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg);
31
32/* thread_run_until is the same as thread_run() except that it blocks state
33 * transitions from occurring in the (state, seq) pair of the boot state
34 * machine. */
35int thread_run_until(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg,
36 boot_state_t state, boot_state_sequence_t seq);
37
Raul E Rangelcc01da52021-07-12 13:43:48 -060038/* Waits until the thread has terminated and returns the error code */
39enum cb_err thread_join(struct thread_handle *handle);
40
Raul E Rangelca0606e2021-07-21 14:34:00 -060041#if (ENV_RAMSTAGE || ENV_ROMSTAGE) && CONFIG(COOP_MULTITASKING)
Aaron Durbin4409a5e2013-05-06 12:20:52 -050042
43struct thread {
44 int id;
45 uintptr_t stack_current;
46 uintptr_t stack_orig;
47 struct thread *next;
Raul E Rangelcc01da52021-07-12 13:43:48 -060048 enum cb_err (*entry)(void *);
Aaron Durbin4409a5e2013-05-06 12:20:52 -050049 void *entry_arg;
50 int can_yield;
Raul E Rangelcc01da52021-07-12 13:43:48 -060051 struct thread_handle *handle;
Aaron Durbin4409a5e2013-05-06 12:20:52 -050052};
53
Raul E Rangeld5dca212021-07-15 11:48:48 -060054/* Return 0 on successful yield, < 0 when thread did not yield. */
55int thread_yield(void);
56
Aaron Durbin4409a5e2013-05-06 12:20:52 -050057/* Return 0 on successful yield for the given amount of time, < 0 when thread
58 * did not yield. */
Lee Leahy0ca2a062017-03-06 18:01:04 -080059int thread_yield_microseconds(unsigned int microsecs);
Aaron Durbin4409a5e2013-05-06 12:20:52 -050060
61/* Allow and prevent thread cooperation on current running thread. By default
Martin Roth0cb07e32013-07-09 21:46:01 -060062 * all threads are marked to be cooperative. That means a thread can yield
Raul E Rangelbe60a0d2021-07-15 13:52:03 -060063 * to another thread at a pre-determined switch point. i.e., udelay,
64 * thread_yield, or thread_yield_microseconds.
65 *
66 * These methods should be used to guard critical sections so a dead lock does
67 * not occur. The critical sections can be nested. Just make sure the methods
68 * are used in pairs.
69 */
Raul E Rangel9ba36ab2021-07-15 17:34:05 -060070void thread_coop_enable(void);
71void thread_coop_disable(void);
Aaron Durbin4409a5e2013-05-06 12:20:52 -050072
Raul E Rangelb29f9d42021-07-12 13:49:59 -060073void thread_mutex_lock(struct thread_mutex *mutex);
74void thread_mutex_unlock(struct thread_mutex *mutex);
75
Aaron Durbin4409a5e2013-05-06 12:20:52 -050076/* Architecture specific thread functions. */
Lee Leahy22c28e02017-03-07 15:47:44 -080077asmlinkage void switch_to_thread(uintptr_t new_stack, uintptr_t *saved_stack);
Aaron Durbin4409a5e2013-05-06 12:20:52 -050078/* Set up the stack frame for a new thread so that a switch_to_thread() call
79 * will enter the thread_entry() function with arg as a parameter. The
80 * saved_stack field in the struct thread needs to be updated accordingly. */
81void arch_prepare_thread(struct thread *t,
Lee Leahy746d4af2017-03-07 15:31:49 -080082 asmlinkage void (*thread_entry)(void *), void *arg);
Aaron Durbin4409a5e2013-05-06 12:20:52 -050083#else
Raul E Rangeld5dca212021-07-15 11:48:48 -060084static inline int thread_yield(void)
85{
86 return -1;
87}
Lee Leahy0ca2a062017-03-06 18:01:04 -080088static inline int thread_yield_microseconds(unsigned int microsecs)
89{
90 return -1;
91}
Raul E Rangel9ba36ab2021-07-15 17:34:05 -060092static inline void thread_coop_enable(void) {}
93static inline void thread_coop_disable(void) {}
Raul E Rangelb29f9d42021-07-12 13:49:59 -060094
95static inline void thread_mutex_lock(struct thread_mutex *mutex) {}
96
97static inline void thread_mutex_unlock(struct thread_mutex *mutex) {}
Aaron Durbin4409a5e2013-05-06 12:20:52 -050098#endif
99
100#endif /* THREAD_H_ */