Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2016-2017 Wind River Systems, Inc. 3 : : * Copyright (c) 2024 Intel Corporation 4 : : * 5 : : * SPDX-License-Identifier: Apache-2.0 6 : : */ 7 : : 8 : : #ifndef ZEPHYR_KERNEL_INCLUDE_THREAD_H_ 9 : : #define ZEPHYR_KERNEL_INCLUDE_THREAD_H_ 10 : : 11 : : #include <zephyr/kernel.h> 12 : : #include <kernel_internal.h> 13 : : #include <timeout_q.h> 14 : : 15 : : 16 : : #define Z_STATE_STR_DUMMY "dummy" 17 : : #define Z_STATE_STR_PENDING "pending" 18 : : #define Z_STATE_STR_PRESTART "prestart" 19 : : #define Z_STATE_STR_DEAD "dead" 20 : : #define Z_STATE_STR_SUSPENDED "suspended" 21 : : #define Z_STATE_STR_ABORTING "aborting" 22 : : #define Z_STATE_STR_SUSPENDING "suspending" 23 : : #define Z_STATE_STR_QUEUED "queued" 24 : : 25 : : #ifdef CONFIG_THREAD_MONITOR 26 : : /* This lock protects the linked list of active threads; i.e. the 27 : : * initial _kernel.threads pointer and the linked list made up of 28 : : * thread->next_thread (until NULL) 29 : : */ 30 : : extern struct k_spinlock z_thread_monitor_lock; 31 : : #endif /* CONFIG_THREAD_MONITOR */ 32 : : 33 : : void idle(void *unused1, void *unused2, void *unused3); 34 : : 35 : : /* clean up when a thread is aborted */ 36 : : 37 : : #if defined(CONFIG_THREAD_MONITOR) 38 : : void z_thread_monitor_exit(struct k_thread *thread); 39 : : #else 40 : : #define z_thread_monitor_exit(thread) \ 41 : : do {/* nothing */ \ 42 : : } while (false) 43 : : #endif /* CONFIG_THREAD_MONITOR */ 44 : : 45 : : 46 : 4 : static inline void thread_schedule_new(struct k_thread *thread, k_timeout_t delay) 47 : : { 48 : : #ifdef CONFIG_SYS_CLOCK_EXISTS 49 [ + - ]: 4 : if (K_TIMEOUT_EQ(delay, K_NO_WAIT)) { 50 : 4 : k_thread_start(thread); 51 : : } else { 52 : 0 : z_add_thread_timeout(thread, delay); 53 : : } 54 : : #else 55 : : ARG_UNUSED(delay); 56 : : k_thread_start(thread); 57 : : #endif /* CONFIG_SYS_CLOCK_EXISTS */ 58 : 4 : } 59 : : 60 : 156 : static inline int thread_is_preemptible(struct k_thread *thread) 61 : : { 62 : : /* explanation in kernel_struct.h */ 63 : 156 : return thread->base.preempt <= _PREEMPT_THRESHOLD; 64 : : } 65 : : 66 : : 67 : 4 : static inline int thread_is_metairq(struct k_thread *thread) 68 : : { 69 : : #if CONFIG_NUM_METAIRQ_PRIORITIES > 0 70 : : return (thread->base.prio - K_HIGHEST_THREAD_PRIO) 71 : : < CONFIG_NUM_METAIRQ_PRIORITIES; 72 : : #else 73 : 4 : ARG_UNUSED(thread); 74 : 4 : return 0; 75 : : #endif /* CONFIG_NUM_METAIRQ_PRIORITIES */ 76 : : } 77 : : 78 : : #ifdef CONFIG_ASSERT 79 : 0 : static inline bool is_thread_dummy(struct k_thread *thread) 80 : : { 81 : 0 : return (thread->base.thread_state & _THREAD_DUMMY) != 0U; 82 : : } 83 : : #endif /* CONFIG_ASSERT */ 84 : : 85 : : 86 : 0 : static inline bool z_is_thread_suspended(struct k_thread *thread) 87 : : { 88 : 0 : return (thread->base.thread_state & _THREAD_SUSPENDED) != 0U; 89 : : } 90 : : 91 : 0 : static inline bool z_is_thread_pending(struct k_thread *thread) 92 : : { 93 : 0 : return (thread->base.thread_state & _THREAD_PENDING) != 0U; 94 : : } 95 : : 96 : 115 : static inline bool z_is_thread_prevented_from_running(struct k_thread *thread) 97 : : { 98 : 115 : uint8_t state = thread->base.thread_state; 99 : : 100 : 115 : return (state & (_THREAD_PENDING | _THREAD_PRESTART | _THREAD_DEAD | 101 : 115 : _THREAD_DUMMY | _THREAD_SUSPENDED)) != 0U; 102 : : 103 : : } 104 : : 105 : 57 : static inline bool z_is_thread_timeout_active(struct k_thread *thread) 106 : : { 107 : 57 : return !z_is_inactive_timeout(&thread->base.timeout); 108 : : } 109 : : 110 : 57 : static inline bool z_is_thread_ready(struct k_thread *thread) 111 : : { 112 [ + - ]: 57 : return !((z_is_thread_prevented_from_running(thread)) != 0U || 113 [ - + ]: 57 : z_is_thread_timeout_active(thread)); 114 : : } 115 : : 116 : 50 : static inline bool z_has_thread_started(struct k_thread *thread) 117 : : { 118 : 50 : return (thread->base.thread_state & _THREAD_PRESTART) == 0U; 119 : : } 120 : : 121 : 113 : static inline bool z_is_thread_state_set(struct k_thread *thread, uint32_t state) 122 : : { 123 : 113 : return (thread->base.thread_state & state) != 0U; 124 : : } 125 : : 126 : 113 : static inline bool z_is_thread_queued(struct k_thread *thread) 127 : : { 128 : 113 : return z_is_thread_state_set(thread, _THREAD_QUEUED); 129 : : } 130 : : 131 : 0 : static inline void z_mark_thread_as_suspended(struct k_thread *thread) 132 : : { 133 : 0 : thread->base.thread_state |= _THREAD_SUSPENDED; 134 : : 135 : 0 : SYS_PORT_TRACING_FUNC(k_thread, sched_suspend, thread); 136 : 0 : } 137 : : 138 : 0 : static inline void z_mark_thread_as_not_suspended(struct k_thread *thread) 139 : : { 140 : 0 : thread->base.thread_state &= ~_THREAD_SUSPENDED; 141 : : 142 : 0 : SYS_PORT_TRACING_FUNC(k_thread, sched_resume, thread); 143 : 0 : } 144 : : 145 : 48 : static inline void z_mark_thread_as_started(struct k_thread *thread) 146 : : { 147 : 48 : thread->base.thread_state &= ~_THREAD_PRESTART; 148 : 48 : } 149 : : 150 : 10 : static inline void z_mark_thread_as_pending(struct k_thread *thread) 151 : : { 152 : 10 : thread->base.thread_state |= _THREAD_PENDING; 153 : 10 : } 154 : : 155 : 10 : static inline void z_mark_thread_as_not_pending(struct k_thread *thread) 156 : : { 157 : 10 : thread->base.thread_state &= ~_THREAD_PENDING; 158 : 10 : } 159 : : 160 : : /* 161 : : * This function tags the current thread as essential to system operation. 162 : : * Exceptions raised by this thread will be treated as a fatal system error. 163 : : */ 164 : : static inline void z_thread_essential_set(struct k_thread *thread) 165 : : { 166 : : thread->base.user_options |= K_ESSENTIAL; 167 : : } 168 : : 169 : : /* 170 : : * This function tags the current thread as not essential to system operation. 171 : : * Exceptions raised by this thread may be recoverable. 172 : : * (This is the default tag for a thread.) 173 : : */ 174 : 0 : static inline void z_thread_essential_clear(struct k_thread *thread) 175 : : { 176 : 0 : thread->base.user_options &= ~K_ESSENTIAL; 177 : 0 : } 178 : : 179 : : /* 180 : : * This routine indicates if the current thread is an essential system thread. 181 : : * 182 : : * Returns true if current thread is essential, false if it is not. 183 : : */ 184 : 88 : static inline bool z_is_thread_essential(struct k_thread *thread) 185 : : { 186 : 88 : return (thread->base.user_options & K_ESSENTIAL) == K_ESSENTIAL; 187 : : } 188 : : 189 : : 190 : 114 : static ALWAYS_INLINE bool should_preempt(struct k_thread *thread, 191 : : int preempt_ok) 192 : : { 193 : : /* Preemption is OK if it's being explicitly allowed by 194 : : * software state (e.g. the thread called k_yield()) 195 : : */ 196 [ + + ]: 114 : if (preempt_ok != 0) { 197 : : return true; 198 : : } 199 : : 200 [ - + ]: 58 : __ASSERT(_current != NULL, ""); 201 : : 202 : : /* Or if we're pended/suspended/dummy (duh) */ 203 [ + + ]: 58 : if (z_is_thread_prevented_from_running(_current)) { 204 : : return true; 205 : : } 206 : : 207 : : /* Edge case on ARM where a thread can be pended out of an 208 : : * interrupt handler before the "synchronous" swap starts 209 : : * context switching. Platforms with atomic swap can never 210 : : * hit this. 211 : : */ 212 : 51 : if (IS_ENABLED(CONFIG_SWAP_NONATOMIC) 213 : : && z_is_thread_timeout_active(thread)) { 214 : : return true; 215 : : } 216 : : 217 : : /* Otherwise we have to be running a preemptible thread or 218 : : * switching to a metairq 219 : : */ 220 [ + + - + ]: 51 : if (thread_is_preemptible(_current) || thread_is_metairq(thread)) { 221 : 47 : return true; 222 : : } 223 : : 224 : : return false; 225 : : } 226 : : 227 : : 228 : 1 : static inline bool z_is_idle_thread_entry(void *entry_point) 229 : : { 230 : 1 : return entry_point == idle; 231 : : } 232 : : 233 : 113 : static inline bool z_is_idle_thread_object(struct k_thread *thread) 234 : : { 235 : : #ifdef CONFIG_MULTITHREADING 236 : : #ifdef CONFIG_SMP 237 : : return thread->base.is_idle; 238 : : #else 239 : 113 : return thread == &z_idle_threads[0]; 240 : : #endif /* CONFIG_SMP */ 241 : : #else 242 : : return false; 243 : : #endif /* CONFIG_MULTITHREADING */ 244 : : } 245 : : 246 : : 247 : : #endif /* ZEPHYR_KERNEL_INCLUDE_THREAD_H_ */