1 // Copyright 2016 The Fuchsia Authors 2 // 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file or at 5 // https://opensource.org/licenses/MIT 6 7 #pragma once 8 9 #include <sys/types.h> 10 11 #include <arch/exception.h> 12 #include <kernel/dpc.h> 13 #include <kernel/event.h> 14 #include <kernel/thread.h> 15 #include <vm/vm_address_region.h> 16 #include <object/channel_dispatcher.h> 17 #include <object/dispatcher.h> 18 #include <object/excp_port.h> 19 #include <object/futex_node.h> 20 #include <object/thread_state.h> 21 22 #include <zircon/compiler.h> 23 #include <zircon/syscalls/debug.h> 24 #include <zircon/syscalls/exception.h> 25 #include <zircon/types.h> 26 #include <fbl/canary.h> 27 #include <fbl/intrusive_double_list.h> 28 #include <fbl/mutex.h> 29 #include <fbl/ref_counted.h> 30 #include <fbl/ref_ptr.h> 31 #include <fbl/string_piece.h> 32 33 class ProcessDispatcher; 34 35 class ThreadDispatcher final : 36 public SoloDispatcher<ThreadDispatcher, ZX_DEFAULT_THREAD_RIGHTS> { 37 public: 38 // Traits to belong in the parent process's list. 39 struct ThreadListTraits { node_stateThreadListTraits40 static fbl::DoublyLinkedListNodeState<ThreadDispatcher*>& node_state( 41 ThreadDispatcher& obj) { 42 return obj.dll_thread_; 43 } 44 }; 45 46 // When in a blocking syscall, or blocked in an exception, the blocking reason. 47 // There is one of these for each syscall marked "blocking". 48 // See syscalls.abigen. 49 enum class Blocked { 50 // Not blocked. 51 NONE, 52 // The thread is blocked in an exception. 53 EXCEPTION, 54 // The thread is sleeping (zx_nanosleep). 55 SLEEPING, 56 // zx_futex_wait 57 FUTEX, 58 // zx_port_wait 59 PORT, 60 // zx_channel_call 61 CHANNEL, 62 // zx_object_wait_one 63 WAIT_ONE, 64 // zx_object_wait_many 65 WAIT_MANY, 66 // zx_interrupt_wait 67 INTERRUPT, 68 }; 69 70 static zx_status_t Create(fbl::RefPtr<ProcessDispatcher> process, uint32_t flags, 71 fbl::StringPiece name, 72 fbl::RefPtr<Dispatcher>* out_dispatcher, 73 zx_rights_t* out_rights); 74 ~ThreadDispatcher(); 75 GetCurrent()76 static ThreadDispatcher* GetCurrent() { 77 return get_current_thread()->user_thread; 78 } 79 80 // Dispatcher implementation. get_type()81 zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_THREAD; } 82 zx_koid_t get_related_koid() const final; 83 84 // Performs initialization on a newly constructed ThreadDispatcher 85 // If this fails, then the object is invalid and should be deleted 86 zx_status_t Initialize(const char* name, size_t len); 87 zx_status_t Start(uintptr_t pc, uintptr_t sp, uintptr_t arg1, uintptr_t arg2, 88 bool initial_thread); 89 void Exit() __NO_RETURN; 90 void Kill(); 91 92 // Suspends the thread. 93 // Returns ZX_OK on success, or ZX_ERR_BAD_STATE iff the thread is dying or dead. 94 zx_status_t Suspend(); 95 void Resume(); 96 97 // accessors process()98 ProcessDispatcher* process() const { return process_.get(); } 99 100 // Returns true if the thread is dying or dead. Threads never return to a previous state 101 // from dying/dead so once this is true it will never flip back to false. 102 bool IsDyingOrDead() const; 103 104 zx_status_t set_name(const char* name, size_t len) final __NONNULL((2)); 105 void get_name(char out_name[ZX_MAX_NAME_LEN]) const final __NONNULL((2)); runtime_ns()106 uint64_t runtime_ns() const { return thread_runtime(&thread_); } 107 108 zx_status_t SetExceptionPort(fbl::RefPtr<ExceptionPort> eport); 109 // Returns true if a port had been set. 110 bool ResetExceptionPort(); 111 fbl::RefPtr<ExceptionPort> exception_port(); 112 113 // Send a report to the associated exception handler of |eport| and wait 114 // for a response. 115 // Note this takes a specific exception port as an argument because there are several: 116 // debugger, thread, process, and system. The kind of the exception port is 117 // specified by |eport->type()|. 118 // Returns: 119 // ZX_OK: the exception was handled in some way, and |*out_estatus| 120 // specifies how. 121 // ZX_ERR_INTERNAL_INTR_KILLED: the thread was killed (probably via zx_task_kill) 122 zx_status_t ExceptionHandlerExchange(fbl::RefPtr<ExceptionPort> eport, 123 const zx_exception_report_t* report, 124 const arch_exception_context_t* arch_context, 125 ThreadState::Exception* out_estatus); 126 127 // Record entry/exit to being in an exception. 128 void EnterException(fbl::RefPtr<ExceptionPort> eport, 129 const zx_exception_report_t* report, 130 const arch_exception_context_t* arch_context); 131 void ExitException(); 132 void ExitExceptionLocked() TA_REQ(get_lock()); 133 134 // Called when an exception handler is finished processing the exception. 135 // If |eport| is non-nullptr, then the exception is only continued if 136 // |eport| corresponds to the current exception port. 137 zx_status_t MarkExceptionHandled(PortDispatcher* eport); 138 zx_status_t MarkExceptionNotHandled(PortDispatcher* eport); 139 140 // Called when exception port |eport| is removed. 141 // If the thread is waiting for the associated exception handler, continue 142 // exception processing as if the exception port had not been installed. 143 void OnExceptionPortRemoval(const fbl::RefPtr<ExceptionPort>& eport); 144 145 // Assuming the thread is stopped waiting for an exception response, 146 // fill in |*report| with the exception report. 147 // Returns ZX_ERR_BAD_STATE if not in an exception. 148 zx_status_t GetExceptionReport(zx_exception_report_t* report); 149 150 // Fetch the state of the thread for userspace tools. 151 zx_status_t GetInfoForUserspace(zx_info_thread_t* info); 152 153 // Fetch per thread stats for userspace. 154 zx_status_t GetStatsForUserspace(zx_info_thread_stats_t* info); 155 156 // For debugger usage. 157 zx_status_t ReadState(zx_thread_state_topic_t state_kind, void* buffer, size_t buffer_len); 158 zx_status_t WriteState(zx_thread_state_topic_t state_kind, const void* buffer, 159 size_t buffer_len); 160 // Profile support 161 zx_status_t SetPriority(int32_t priority); 162 163 // For ChannelDispatcher use. GetMessageWaiter()164 ChannelDispatcher::MessageWaiter* GetMessageWaiter() { return &channel_waiter_; } 165 166 // Blocking syscalls, once they commit to a path that will likely block the 167 // thread, use this helper class to properly set/restore |blocked_reason_|. 168 class AutoBlocked final { 169 public: AutoBlocked(Blocked reason)170 explicit AutoBlocked(Blocked reason) 171 : thread_(ThreadDispatcher::GetCurrent()), 172 prev_reason(thread_->blocked_reason_) { 173 DEBUG_ASSERT(reason != Blocked::NONE); 174 thread_->blocked_reason_ = reason; 175 } ~AutoBlocked()176 ~AutoBlocked() { 177 thread_->blocked_reason_ = prev_reason; 178 } 179 private: 180 ThreadDispatcher* const thread_; 181 const Blocked prev_reason; 182 }; 183 184 private: 185 ThreadDispatcher(fbl::RefPtr<ProcessDispatcher> process, uint32_t flags); 186 ThreadDispatcher(const ThreadDispatcher&) = delete; 187 ThreadDispatcher& operator=(const ThreadDispatcher&) = delete; 188 189 // kernel level entry point 190 static int StartRoutine(void* arg); 191 192 // callback from kernel when thread is exiting, just before it stops for good. 193 void Exiting(); 194 195 // callback from kernel when thread is suspending 196 void Suspending(); 197 // callback from kernel when thread is resuming 198 void Resuming(); 199 200 // Return true if waiting for an exception response. 201 bool InExceptionLocked() TA_REQ(get_lock()); 202 203 // Helper routine to minimize code duplication. 204 zx_status_t MarkExceptionHandledWorker(PortDispatcher* eport, 205 ThreadState::Exception handled_state); 206 207 // Dispatch routine for state changes that LK tells us about 208 static void ThreadUserCallback(enum thread_user_state_change new_state, thread_t* arg); 209 210 // change states of the object, do what is appropriate for the state transition 211 void SetStateLocked(ThreadState::Lifecycle lifecycle) TA_REQ(get_lock()); 212 213 fbl::Canary<fbl::magic("THRD")> canary_; 214 215 // The containing process holds a list of all its threads. 216 fbl::DoublyLinkedListNodeState<ThreadDispatcher*> dll_thread_; 217 218 // a ref pointer back to the parent process 219 fbl::RefPtr<ProcessDispatcher> process_; 220 221 // User thread starting register values. 222 uintptr_t user_entry_ = 0; 223 uintptr_t user_sp_ = 0; 224 uintptr_t user_arg1_ = 0; 225 uintptr_t user_arg2_ = 0; 226 227 ThreadState state_ TA_GUARDED(get_lock()); 228 229 // This is only valid while |state_.is_running()|. 230 // This is just a volatile, and not something like an atomic, because 231 // the only writer is the thread itself, and readers can just pick up 232 // whatever value is currently here. This value is written when the thread 233 // is likely to be put on a wait queue, and the following context switch 234 // will force this value's visibility to other cpus. If the thread doesn't 235 // get put on a wait queue, the thread was never really blocked. 236 volatile Blocked blocked_reason_ = Blocked::NONE; 237 238 // A thread-level exception port for this thread. 239 fbl::RefPtr<ExceptionPort> exception_port_ TA_GUARDED(get_lock()); 240 241 // Support for sending an exception to an exception handler and then waiting for a response. 242 243 // The exception port of the handler the thread is waiting for a response from. 244 fbl::RefPtr<ExceptionPort> exception_wait_port_ TA_GUARDED(get_lock()); 245 const zx_exception_report_t* exception_report_ TA_GUARDED(get_lock()); 246 event_t exception_event_ = 247 EVENT_INITIAL_VALUE(exception_event_, false, EVENT_FLAG_AUTOUNSIGNAL); 248 249 // cleanup dpc structure 250 dpc_t cleanup_dpc_ = {LIST_INITIAL_CLEARED_VALUE, nullptr, nullptr}; 251 252 // Tracks the number of times Suspend() has been called. Resume() will resume this thread 253 // only when this reference count reaches 0. 254 int suspend_count_ TA_GUARDED(get_lock()) = 0; 255 256 // Used to protect thread name read/writes 257 mutable DECLARE_SPINLOCK(ThreadDispatcher) name_lock_; 258 259 // Per-thread structure used while waiting in a ChannelDispatcher::Call. 260 // Needed to support the requirements of being able to interrupt a Call 261 // in order to suspend a thread. 262 ChannelDispatcher::MessageWaiter channel_waiter_; 263 264 // LK thread structure 265 // put last to ease debugging since this is a pretty large structure 266 // (~1.5K on x86_64). 267 // Also, a simple experiment to move this to the first member (after the 268 // canary) resulted in a 1K increase in text size (x86_64). 269 thread_t thread_ = {}; 270 271 // If true and ancestor job has a debugger attached, thread will block on 272 // start and will send a process start exception. 273 bool is_initial_thread_ = false; 274 }; 275