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