1// Copyright 2016 The Fuchsia Authors 2// Copyright (c) 2008-2015 Travis Geiselbrecht 3// 4// Use of this source code is governed by a MIT-style 5// license that can be found in the LICENSE file or at 6// https://opensource.org/licenses/MIT 7 8#pragma once 9 10#include <arch/defines.h> 11#include <arch/ops.h> 12#include <arch/thread.h> 13#include <debug.h> 14#include <kernel/cpu.h> 15#include <kernel/spinlock.h> 16#include <kernel/wait.h> 17#include <list.h> 18#include <sys/types.h> 19#include <vm/kstack.h> 20#include <zircon/compiler.h> 21#include <zircon/types.h> 22 23__BEGIN_CDECLS 24 25enum thread_state { 26 THREAD_INITIAL = 0, 27 THREAD_READY, 28 THREAD_RUNNING, 29 THREAD_BLOCKED, 30 THREAD_SLEEPING, 31 THREAD_SUSPENDED, 32 THREAD_DEATH, 33}; 34 35enum thread_user_state_change { 36 THREAD_USER_STATE_EXIT, 37 THREAD_USER_STATE_SUSPEND, 38 THREAD_USER_STATE_RESUME, 39}; 40 41typedef int (*thread_start_routine)(void* arg); 42typedef void (*thread_trampoline_routine)(void) __NO_RETURN; 43typedef void (*thread_user_callback_t)(enum thread_user_state_change new_state, 44 void* user_thread); 45typedef void (*thread_tls_callback_t)(void* tls_value); 46 47// clang-format off 48#define THREAD_FLAG_DETACHED (1 << 0) 49#define THREAD_FLAG_FREE_STRUCT (1 << 1) 50#define THREAD_FLAG_REAL_TIME (1 << 2) 51#define THREAD_FLAG_IDLE (1 << 3) 52 53#define THREAD_SIGNAL_KILL (1 << 0) 54#define THREAD_SIGNAL_SUSPEND (1 << 1) 55#define THREAD_SIGNAL_POLICY_EXCEPTION (1 << 2) 56// clang-format on 57 58#define THREAD_MAGIC (0x74687264) // 'thrd' 59 60// This includes the trailing NUL. 61// N.B. This must match ZX_MAX_NAME_LEN. 62#define THREAD_NAME_LENGTH 32 63 64#define THREAD_LINEBUFFER_LENGTH 128 65 66// Number of kernel tls slots. 67#define THREAD_MAX_TLS_ENTRY 2 68 69struct vmm_aspace; 70 71// This is a parallel structure to lockdep::ThreadLockState to work around the 72// fact that this header is included by C code and cannot reference C++ types 73// directly. This structure MUST NOT be touched by code outside of the lockdep 74// implementation and MUST be kept in sync with the C++ counterpart. 75typedef struct lockdep_state { 76 uintptr_t acquired_locks; 77 uint16_t reporting_disabled_count; 78 uint8_t last_result; 79} lockdep_state_t; 80 81typedef struct thread { 82 int magic; 83 struct list_node thread_list_node; 84 85 // active bits 86 struct list_node queue_node; 87 enum thread_state state; 88 zx_time_t last_started_running; 89 zx_duration_t remaining_time_slice; 90 unsigned int flags; 91 unsigned int signals; 92 93 // Total time in THREAD_RUNNING state. If the thread is currently in 94 // THREAD_RUNNING state, this excludes the time it has accrued since it 95 // left the scheduler. 96 zx_duration_t runtime_ns; 97 98 // priority: in the range of [MIN_PRIORITY, MAX_PRIORITY], from low to high. 99 // base_priority is set at creation time, and can be tuned with thread_set_priority(). 100 // priority_boost is a signed value that is moved around within a range by the scheduler. 101 // inherited_priority is temporarily set to >0 when inheriting a priority from another 102 // thread blocked on a locking primitive this thread holds. -1 means no inherit. 103 // effective_priority is MAX(base_priority + priority boost, inherited_priority) and is 104 // the working priority for run queue decisions. 105 int effec_priority; 106 int base_priority; 107 int priority_boost; 108 int inherited_priority; 109 110 // current cpu the thread is either running on or in the ready queue, undefined otherwise 111 cpu_num_t curr_cpu; 112 cpu_num_t last_cpu; // last cpu the thread ran on, INVALID_CPU if it's never run 113 cpu_mask_t cpu_affinity; // mask of cpus that this thread can run on 114 115 // if blocked, a pointer to the wait queue 116 struct wait_queue* blocking_wait_queue; 117 118 // list of other wait queue heads if we're a head 119 struct list_node wait_queue_heads_node; 120 121 // return code if woken up abnormally from suspend, sleep, or block 122 zx_status_t blocked_status; 123 124 // are we allowed to be interrupted on the current thing we're blocked/sleeping on 125 bool interruptable; 126 127 // number of mutexes we currently hold 128 int mutexes_held; 129 130#if WITH_LOCK_DEP 131 // state for runtime lock validation when in thread context 132 lockdep_state_t lock_state; 133#endif 134 135 // pointer to the kernel address space this thread is associated with 136 struct vmm_aspace* aspace; 137 138 // pointer to user thread if one exists for this thread 139 void* user_thread; 140 uint64_t user_tid; 141 uint64_t user_pid; 142 143 // callback for user thread state changes; do not invoke directly, use invoke_user_callback 144 // helper function instead 145 thread_user_callback_t user_callback; 146 147 // non-NULL if stopped in an exception 148 const struct arch_exception_context* exception_context; 149 150 // architecture stuff 151 struct arch_thread arch; 152 153 kstack_t stack; 154 155 // entry point 156 thread_start_routine entry; 157 void* arg; 158 159 // return code 160 int retcode; 161 struct wait_queue retcode_wait_queue; 162 163 // disable_counts contains two fields: 164 // 165 // * Bottom 16 bits: the preempt_disable counter. See 166 // thread_preempt_disable(). 167 // * Top 16 bits: the resched_disable counter. See 168 // thread_resched_disable(). 169 // 170 // This is a single field so that both counters can be compared against 171 // zero with a single memory access and comparison. 172 // 173 // disable_counts is modified by interrupt handlers, but it is always 174 // restored to its original value before the interrupt handler returns, 175 // so modifications are not visible to the interrupted thread. Despite 176 // that, "volatile" is still technically needed. Otherwise the 177 // compiler is technically allowed to compile 178 // "++thread->disable_counts" into code that stores a junk value into 179 // preempt_disable temporarily. 180 volatile uint32_t disable_counts; 181 182 // preempt_pending tracks whether a thread reschedule is pending. 183 // 184 // This is volatile because it can be changed asynchronously by an 185 // interrupt handler: If preempt_disable is set, an interrupt handler 186 // may change this from false to true. Otherwise, if resched_disable 187 // is set, an interrupt handler may change this from true to false. 188 // 189 // preempt_pending should only be true: 190 // * if preempt_disable or resched_disable are non-zero, or 191 // * after preempt_disable or resched_disable have been decremented, 192 // while preempt_pending is being checked. 193 volatile bool preempt_pending; 194 195 // thread local storage, intialized to zero 196 void* tls[THREAD_MAX_TLS_ENTRY]; 197 198 // callback for cleanup of tls slots 199 thread_tls_callback_t tls_callback[THREAD_MAX_TLS_ENTRY]; 200 201 char name[THREAD_NAME_LENGTH]; 202#if WITH_DEBUG_LINEBUFFER 203 // buffering for debug/klog output 204 size_t linebuffer_pos; 205 char linebuffer[THREAD_LINEBUFFER_LENGTH]; 206#endif 207} thread_t; 208 209// thread priority 210#define NUM_PRIORITIES (32) 211#define LOWEST_PRIORITY (0) 212#define HIGHEST_PRIORITY (NUM_PRIORITIES - 1) 213#define DPC_PRIORITY (NUM_PRIORITIES - 2) 214#define IDLE_PRIORITY LOWEST_PRIORITY 215#define LOW_PRIORITY (NUM_PRIORITIES / 4) 216#define DEFAULT_PRIORITY (NUM_PRIORITIES / 2) 217#define HIGH_PRIORITY ((NUM_PRIORITIES / 4) * 3) 218 219// stack size 220#ifdef CUSTOM_DEFAULT_STACK_SIZE 221#define DEFAULT_STACK_SIZE CUSTOM_DEFAULT_STACK_SIZE 222#else 223#define DEFAULT_STACK_SIZE ARCH_DEFAULT_STACK_SIZE 224#endif 225 226// functions 227void thread_init_early(void); 228void thread_become_idle(void) __NO_RETURN; 229void thread_secondary_cpu_init_early(thread_t* t); 230void thread_secondary_cpu_entry(void) __NO_RETURN; 231void thread_construct_first(thread_t* t, const char* name); 232thread_t* thread_create_idle_thread(uint cpu_num); 233void thread_set_name(const char* name); 234void thread_set_priority(thread_t* t, int priority); 235void thread_set_user_callback(thread_t* t, thread_user_callback_t cb); 236thread_t* thread_create(const char* name, thread_start_routine entry, void* arg, int priority); 237thread_t* thread_create_etc(thread_t* t, const char* name, thread_start_routine entry, void* arg, 238 int priority, thread_trampoline_routine alt_trampoline); 239void thread_resume(thread_t*); 240zx_status_t thread_suspend(thread_t*); 241void thread_signal_policy_exception(void); 242void thread_exit(int retcode) __NO_RETURN; 243void thread_forget(thread_t*); 244 245// set the mask of valid cpus to run the thread on. migrates the thread to satisfy 246// the new constraint 247void thread_set_cpu_affinity(thread_t* t, cpu_mask_t mask); 248 249// migrates the current thread to the CPU identified by target_cpu 250void thread_migrate_to_cpu(cpu_num_t target_cpuid); 251 252zx_status_t thread_detach(thread_t* t); 253zx_status_t thread_join(thread_t* t, int* retcode, zx_time_t deadline); 254zx_status_t thread_detach_and_resume(thread_t* t); 255zx_status_t thread_set_real_time(thread_t* t); 256 257// scheduler routines to be used by regular kernel code 258void thread_yield(void); // give up the cpu and time slice voluntarily 259void thread_preempt(void); // get preempted at irq time 260void thread_reschedule(void); // revaluate the run queue on the current cpu 261 262void thread_owner_name(thread_t* t, char out_name[THREAD_NAME_LENGTH]); 263 264// print the backtrace on the current thread 265void thread_print_current_backtrace(void); 266 267// append the backtrace of the current thread to the passed in char pointer up 268// to `len' characters. 269// return the number of chars appended. 270size_t thread_append_current_backtrace(char* out, size_t len); 271 272// print the backtrace on the current thread at the given frame 273void thread_print_current_backtrace_at_frame(void* caller_frame); 274 275// print the backtrace of the passed in thread, if possible 276zx_status_t thread_print_backtrace(thread_t* t); 277 278// Return true if stopped in an exception. 279static inline bool thread_stopped_in_exception(const thread_t* thread) { 280 return !!thread->exception_context; 281} 282 283// wait until after the specified deadline. interruptable may return early with 284// ZX_ERR_INTERNAL_INTR_KILLED if thread is signaled for kill. 285zx_status_t thread_sleep_etc(zx_time_t deadline, bool interruptable); 286 287// non interruptable version of thread_sleep_etc 288static inline zx_status_t thread_sleep(zx_time_t deadline) { 289 return thread_sleep_etc(deadline, false); 290} 291 292// non-interruptable relative delay version of thread_sleep 293zx_status_t thread_sleep_relative(zx_duration_t delay); 294 295// return the number of nanoseconds a thread has been running for 296zx_duration_t thread_runtime(const thread_t* t); 297 298// deliver a kill signal to a thread 299void thread_kill(thread_t* t); 300 301// return true if thread has been signaled 302static inline bool thread_is_signaled(thread_t* t) { 303 return t->signals != 0; 304} 305 306// process pending signals, may never return because of kill signal 307void thread_process_pending_signals(void); 308 309void dump_thread(thread_t* t, bool full); 310void arch_dump_thread(thread_t* t); 311void dump_all_threads(bool full); 312void dump_all_threads_locked(bool full); 313void dump_thread_user_tid(uint64_t tid, bool full); 314void dump_thread_user_tid_locked(uint64_t tid, bool full); 315 316// find a thread based on the thread id 317// NOTE: used only for debugging, its a slow linear search through the 318// global thread list 319thread_t* thread_id_to_thread_slow(uint64_t tid); 320 321static inline bool thread_is_realtime(thread_t* t) { 322 return (t->flags & THREAD_FLAG_REAL_TIME) && t->base_priority > DEFAULT_PRIORITY; 323} 324 325static inline bool thread_is_idle(thread_t* t) { 326 return !!(t->flags & THREAD_FLAG_IDLE); 327} 328 329static inline bool thread_is_real_time_or_idle(thread_t* t) { 330 return !!(t->flags & (THREAD_FLAG_REAL_TIME | THREAD_FLAG_IDLE)); 331} 332 333// the current thread 334#include <arch/current_thread.h> 335thread_t* get_current_thread(void); 336void set_current_thread(thread_t*); 337 338// scheduler lock 339extern spin_lock_t thread_lock; 340 341static inline bool thread_lock_held(void) { 342 return spin_lock_held(&thread_lock); 343} 344 345// Thread local storage. See tls_slots.h in the object layer above for 346// the current slot usage. 347 348static inline void* tls_get(uint entry) { 349 return get_current_thread()->tls[entry]; 350} 351 352static inline void* tls_set(uint entry, void* val) { 353 thread_t* curr_thread = get_current_thread(); 354 void* oldval = curr_thread->tls[entry]; 355 curr_thread->tls[entry] = val; 356 return oldval; 357} 358 359// set the callback that is issued when the thread exits 360static inline void tls_set_callback(uint entry, thread_tls_callback_t cb) { 361 get_current_thread()->tls_callback[entry] = cb; 362} 363 364void thread_check_preempt_pending(void); 365 366static inline uint32_t thread_preempt_disable_count(void) { 367 return get_current_thread()->disable_counts & 0xffff; 368} 369 370static inline uint32_t thread_resched_disable_count(void) { 371 return get_current_thread()->disable_counts >> 16; 372} 373 374// thread_preempt_disable() increments the preempt_disable counter for the 375// current thread. While preempt_disable is non-zero, preemption of the 376// thread is disabled, including preemption from interrupt handlers. 377// During this time, any call to thread_reschedule() or sched_reschedule() 378// will only record that a reschedule is pending, and won't do a context 379// switch. 380// 381// Note that this does not disallow blocking operations 382// (e.g. mutex_acquire()). Disabling preemption does not prevent switching 383// away from the current thread if it blocks. 384// 385// A call to thread_preempt_disable() must be matched by a later call to 386// thread_preempt_reenable() to decrement the preempt_disable counter. 387static inline void thread_preempt_disable(void) { 388 DEBUG_ASSERT(thread_preempt_disable_count() < 0xffff); 389 390 thread_t* current_thread = get_current_thread(); 391 atomic_signal_fence(); 392 ++current_thread->disable_counts; 393 atomic_signal_fence(); 394} 395 396// thread_preempt_reenable() decrements the preempt_disable counter. See 397// thread_preempt_disable(). 398static inline void thread_preempt_reenable(void) { 399 DEBUG_ASSERT(!arch_blocking_disallowed()); 400 DEBUG_ASSERT(thread_preempt_disable_count() > 0); 401 402 thread_t* current_thread = get_current_thread(); 403 atomic_signal_fence(); 404 uint32_t new_count = --current_thread->disable_counts; 405 atomic_signal_fence(); 406 407 if (new_count == 0) { 408 thread_check_preempt_pending(); 409 } 410} 411 412// This is the same as thread_preempt_reenable(), except that it does not 413// check for any pending reschedules. This is useful in interrupt handlers 414// when we know that no reschedules should have become pending since 415// calling thread_preempt_disable(). 416static inline void thread_preempt_reenable_no_resched(void) { 417 DEBUG_ASSERT(thread_preempt_disable_count() > 0); 418 419 thread_t* current_thread = get_current_thread(); 420 atomic_signal_fence(); 421 --current_thread->disable_counts; 422 atomic_signal_fence(); 423} 424 425// thread_resched_disable() increments the resched_disable counter for the 426// current thread. When resched_disable is non-zero, preemption of the 427// thread from outside interrupt handlers is disabled. However, interrupt 428// handlers may still preempt the thread. 429// 430// This is a weaker version of thread_preempt_disable(). 431// 432// As with preempt_disable, blocking operations are still allowed while 433// resched_disable is non-zero. 434// 435// A call to thread_resched_disable() must be matched by a later call to 436// thread_resched_reenable() to decrement the preempt_disable counter. 437static inline void thread_resched_disable(void) { 438 DEBUG_ASSERT(thread_resched_disable_count() < 0xffff); 439 440 thread_t* current_thread = get_current_thread(); 441 atomic_signal_fence(); 442 current_thread->disable_counts += 1 << 16; 443 atomic_signal_fence(); 444} 445 446// thread_resched_reenable() decrements the preempt_disable counter. See 447// thread_resched_disable(). 448static inline void thread_resched_reenable(void) { 449 DEBUG_ASSERT(!arch_blocking_disallowed()); 450 DEBUG_ASSERT(thread_resched_disable_count() > 0); 451 452 thread_t* current_thread = get_current_thread(); 453 atomic_signal_fence(); 454 uint32_t new_count = current_thread->disable_counts - (1 << 16); 455 current_thread->disable_counts = new_count; 456 atomic_signal_fence(); 457 458 if (new_count == 0) { 459 thread_check_preempt_pending(); 460 } 461} 462 463// thread_preempt_set_pending() marks a preemption as pending for the 464// current CPU. 465// 466// This is similar to thread_reschedule(), except that it may only be 467// used inside an interrupt handler while interrupts and preemption 468// are disabled, between thread_preempt_disable() and 469// thread_preempt_reenable(). It is similar to sched_reschedule(), 470// except that it does not need to be called with thread_lock held. 471static inline void thread_preempt_set_pending(void) { 472 DEBUG_ASSERT(arch_ints_disabled()); 473 DEBUG_ASSERT(arch_blocking_disallowed()); 474 thread_t* current_thread = get_current_thread(); 475 DEBUG_ASSERT(thread_preempt_disable_count() > 0); 476 477 current_thread->preempt_pending = true; 478} 479 480__END_CDECLS 481 482#ifdef __cplusplus 483 484#include <fbl/macros.h> 485 486// AutoReschedDisable is an RAII helper for disabling rescheduling 487// using thread_resched_disable()/thread_resched_reenable(). 488// 489// A typical use case is when we wake another thread while holding a 490// mutex. If the other thread is likely to claim the same mutex when 491// runs (either immediately or later), then it is useful to defer 492// waking the thread until after we have released the mutex. We can 493// do that by disabling rescheduling while holding the lock. This is 494// beneficial when there are no free CPUs for running the woken thread 495// on. 496// 497// Example usage: 498// 499// AutoReschedDisable resched_disable; 500// AutoLock al(&lock_); 501// // Do some initial computation... 502// resched_disable.Disable(); 503// // Possibly wake another thread... 504// 505// The AutoReschedDisable must be placed before the AutoLock to ensure that 506// rescheduling is re-enabled only after releasing the mutex. 507class AutoReschedDisable { 508public: 509 AutoReschedDisable() {} 510 ~AutoReschedDisable() { 511 if (started_) { 512 thread_resched_reenable(); 513 } 514 } 515 516 void Disable() { 517 if (!started_) { 518 thread_resched_disable(); 519 started_ = true; 520 } 521 } 522 523 DISALLOW_COPY_ASSIGN_AND_MOVE(AutoReschedDisable); 524 525private: 526 bool started_ = false; 527}; 528 529#endif // __cplusplus 530