| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library zx; |
| |
| @transport("Syscall") |
| closed protocol Thread { |
| /// ## Summary |
| /// |
| /// Terminate the current running thread. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// [[noreturn]] void zx_thread_exit(void); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_exit()` causes the currently running thread to cease |
| /// running and exit. |
| /// |
| /// The signal **ZX_THREAD_TERMINATED** will be asserted on the thread |
| /// object upon exit and may be observed via [`zx_object_wait_one()`] |
| /// or [`zx_object_wait_many()`] on a handle to the thread. |
| /// |
| /// ## Rights |
| /// |
| /// TODO(fxbug.dev/32253) |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_exit()` does not return. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_handle_close()`] |
| /// - [`zx_handle_duplicate()`] |
| /// - [`zx_object_wait_async()`] |
| /// - [`zx_object_wait_many()`] |
| /// - [`zx_object_wait_one()`] |
| /// - [`zx_thread_create()`] |
| /// - [`zx_thread_start()`] |
| /// |
| /// [`zx_handle_close()`]: handle_close.md |
| /// [`zx_handle_duplicate()`]: handle_duplicate.md |
| /// [`zx_object_wait_async()`]: object_wait_async.md |
| /// [`zx_object_wait_many()`]: object_wait_many.md |
| /// [`zx_object_wait_one()`]: object_wait_one.md |
| /// [`zx_thread_create()`]: thread_create.md |
| /// [`zx_thread_start()`]: thread_start.md |
| @noreturn |
| strict Exit(); |
| |
| /// ## Summary |
| /// |
| /// Create a thread. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_create(zx_handle_t process, |
| /// const char* name, |
| /// size_t name_size, |
| /// uint32_t options, |
| /// zx_handle_t* out); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_create()` creates a thread within the specified process. |
| /// |
| /// Upon success a handle for the new thread is returned. The thread |
| /// will not start executing until [`zx_thread_start()`] is called. |
| /// |
| /// *name* is silently truncated to a maximum of `ZX_MAX_NAME_LEN-1` characters. |
| /// |
| /// Thread handles may be waited on and will assert the signal |
| /// **ZX_THREAD_TERMINATED** when the thread stops executing (due to |
| /// [`zx_thread_exit()`] being called). |
| /// |
| /// *process* is the controlling [process object](/docs/reference/kernel_objects/process.md) for the |
| /// new thread, which will become a child of that process. |
| /// |
| /// For thread lifecycle details see [thread object](/docs/reference/kernel_objects/thread.md). |
| /// |
| /// ## Rights |
| /// |
| /// *process* must be of type **ZX_OBJ_TYPE_PROCESS** and have **ZX_RIGHT_MANAGE_THREAD**. |
| /// |
| /// ## Return value |
| /// |
| /// On success, `zx_thread_create()` returns **ZX_OK** and a handle (via *out*) |
| /// to the new thread. In the event of failure, a negative error value is |
| /// returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *process* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *process* is not a process handle. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *process* does not have the **ZX_RIGHT_MANAGE_THREAD** right. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *name* or *out* was an invalid pointer, or *options* was |
| /// non-zero. |
| /// |
| /// **ZX_ERR_NO_MEMORY** Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_handle_close()`] |
| /// - [`zx_handle_duplicate()`] |
| /// - [`zx_object_wait_async()`] |
| /// - [`zx_object_wait_many()`] |
| /// - [`zx_object_wait_one()`] |
| /// - [`zx_thread_exit()`] |
| /// - [`zx_thread_start()`] |
| /// |
| /// [`zx_handle_close()`]: handle_close.md |
| /// [`zx_handle_duplicate()`]: handle_duplicate.md |
| /// [`zx_object_wait_async()`]: object_wait_async.md |
| /// [`zx_object_wait_many()`]: object_wait_many.md |
| /// [`zx_object_wait_one()`]: object_wait_one.md |
| /// [`zx_thread_exit()`]: thread_exit.md |
| /// [`zx_thread_start()`]: thread_start.md |
| strict Create(resource struct { |
| process Handle:PROCESS; |
| name vector<uchar>:MAX_NAME_LEN; |
| options uint32; |
| }) -> (resource struct { |
| out Handle:THREAD; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Start execution on a thread. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_start(zx_handle_t handle, |
| /// zx_vaddr_t thread_entry, |
| /// zx_vaddr_t stack, |
| /// uintptr_t arg1, |
| /// uintptr_t arg2); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_start()` causes a thread to begin execution at the program counter |
| /// specified by *thread_entry* and with the stack pointer set to *stack*. The |
| /// arguments *arg1* and *arg2* are arranged to be in the architecture specific |
| /// registers used for the first two arguments of a function call before the thread |
| /// is started. All other registers are zero upon start. |
| /// |
| /// When the last handle to a thread is closed, the thread is destroyed. |
| /// |
| /// Thread handles may be waited on and will assert the signal |
| /// **ZX_THREAD_TERMINATED** when the thread stops executing (due to |
| /// [`zx_thread_exit()`] being called). |
| /// |
| /// *thread_entry* shall point to a function that must call [`zx_thread_exit()`] or |
| /// [`zx_futex_wake_handle_close_thread_exit()`] or |
| /// [`zx_vmar_unmap_handle_close_thread_exit()`] before reaching the last instruction. |
| /// Below is an example: |
| /// |
| /// ``` |
| /// void thread_entry(uintptr_t arg1, uintptr_t arg2) __attribute__((noreturn)) { |
| /// // do work here. |
| /// |
| /// zx_thread_exit(); |
| /// } |
| /// ``` |
| /// |
| /// Failing to call one of the exit functions before reaching the end of |
| /// the function will cause an architecture / toolchain specific exception. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_THREAD** and have **ZX_RIGHT_MANAGE_THREAD**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_start()` returns **ZX_OK** on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *thread* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *thread* is not a thread handle. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** The handle *thread* lacks **ZX_RIGHT_WRITE**. |
| /// |
| /// **ZX_ERR_BAD_STATE** *thread* is not ready to run or the process *thread* |
| /// is part of is no longer alive. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *thread_entry* is not a userspace address, is not a |
| /// [canonical address], or is not `0`. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_futex_wake_handle_close_thread_exit()`] |
| /// - [`zx_handle_close()`] |
| /// - [`zx_handle_duplicate()`] |
| /// - [`zx_object_wait_async()`] |
| /// - [`zx_object_wait_many()`] |
| /// - [`zx_object_wait_one()`] |
| /// - [`zx_thread_create()`] |
| /// - [`zx_thread_exit()`] |
| /// - [`zx_vmar_unmap_handle_close_thread_exit()`] |
| /// |
| /// [`zx_futex_wake_handle_close_thread_exit()`]: futex_wake_handle_close_thread_exit.md |
| /// [`zx_handle_close()`]: handle_close.md |
| /// [`zx_handle_duplicate()`]: handle_duplicate.md |
| /// [`zx_object_wait_async()`]: object_wait_async.md |
| /// [`zx_object_wait_many()`]: object_wait_many.md |
| /// [`zx_object_wait_one()`]: object_wait_one.md |
| /// [`zx_thread_create()`]: thread_create.md |
| /// [`zx_thread_exit()`]: thread_exit.md |
| /// [`zx_vmar_unmap_handle_close_thread_exit()`]: vmar_unmap_handle_close_thread_exit.md |
| strict Start(resource struct { |
| handle Handle:THREAD; |
| thread_entry Vaddr; |
| stack Vaddr; |
| arg1 uintptr64; |
| arg2 uintptr64; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Read one aspect of thread state. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_read_state(zx_handle_t handle, |
| /// uint32_t kind, |
| /// void* buffer, |
| /// size_t buffer_size); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_read_state()` reads one aspect of state of the thread. The thread |
| /// state may only be read when the thread is halted for an exception or the thread |
| /// is suspended. |
| /// |
| /// The thread state is highly processor specific. See the structures in |
| /// zircon/syscalls/debug.h for the contents of the structures on each platform. |
| /// |
| /// ## STATES |
| /// |
| /// ### ZX_THREAD_STATE_GENERAL_REGS |
| /// |
| /// The buffer must point to a `zx_thread_state_general_regs_t` structure that |
| /// contains the general registers for the current architecture. |
| /// |
| /// ### ZX_THREAD_STATE_FP_REGS |
| /// |
| /// The buffer must point to a `zx_thread_state_fp_regs_t` structure. On 64-bit |
| /// ARM platforms, float point state is in the vector registers and this structure |
| /// is empty. |
| /// |
| /// ### ZX_THREAD_STATE_VECTOR_REGS |
| /// |
| /// The buffer must point to a `zx_thread_state_vector_regs_t` structure. |
| /// |
| /// ### ZX_THREAD_STATE_DEBUG_REGS |
| /// |
| /// The buffer must point to a `zx_thread_state_debug_regs_t` structure. All input |
| /// fields will be ignored and overwritten with the actual values for the thread. |
| /// |
| /// ### ZX_THREAD_STATE_SINGLE_STEP |
| /// |
| /// The buffer must point to a `zx_thread_state_single_step_t` value, which |
| /// may contain either 0 (normal running), or 1 (single stepping enabled). |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_THREAD** and have **ZX_RIGHT_READ**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_read_state()` returns **ZX_OK** on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not that of a thread. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* lacks **ZX_RIGHT_READ**. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *kind* is not valid or *buffer* is an invalid pointer. |
| /// |
| /// **ZX_ERR_NO_MEMORY** Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// **ZX_ERR_BUFFER_TOO_SMALL** The buffer length *buffer_size* is too small to |
| /// hold the data required by *kind*. |
| /// |
| /// **ZX_ERR_BAD_STATE** The thread is not stopped at a point where state |
| /// is available. The thread state may only be read when the thread is stopped due |
| /// to an exception. |
| /// |
| /// **ZX_ERR_NOT_SUPPORTED** *kind* is not supported. |
| /// This can happen, for example, when trying to read a register set that |
| /// is not supported by the hardware the program is currently running on. |
| /// |
| /// ## See also |
| /// |
| /// [thread_write_state](thread_write_state.md). |
| strict ReadState(resource struct { |
| handle Handle:THREAD; |
| kind uint32; |
| }) -> (struct { |
| @voidptr |
| buffer vector<byte>:MAX; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Write one aspect of thread state. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_write_state(zx_handle_t handle, |
| /// uint32_t kind, |
| /// const void* buffer, |
| /// size_t buffer_size); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_write_state()` writes one aspect of state of the thread. The thread |
| /// state may only be written when the thread is halted for an exception or the |
| /// thread is suspended. |
| /// |
| /// The thread state is highly processor specific. See the structures in |
| /// zircon/syscalls/debug.h for the contents of the structures on each platform. |
| /// |
| /// To use the `zx_thread_write_state()` function with the `ZX_THREAD_STATE_DEBUG_REGS` |
| /// flag, you must specify `kernel.enable-serial-syscalls=true` on the kernel command line. |
| /// Otherwise, the function returns **ZX_ERR_NOT_SUPPORTED**. |
| /// |
| /// ## STATES |
| /// |
| /// See [`zx_thread_read_state()`] for the list of available states |
| /// and their corresponding values. |
| /// |
| /// ### ZX_THREAD_STATE_DEBUG_REGS |
| /// |
| /// #### ARM |
| /// |
| /// ARM has a variable amount of debug breakpoints and watchpoints. For this |
| /// architecture, `zx_thread_state_debug_regs_t` is big enough to hold the maximum |
| /// amount of breakpoints possible. But in most cases a given CPU implementation |
| /// holds a lesser amount, meaning that the upper values beyond the limit are not |
| /// used. |
| /// |
| /// The kernel will write all the available registers in the hardware independent of |
| /// the given breakpoint/watchpoint count value. This means that all the correct |
| /// state must be set for the call. |
| /// |
| /// You can get the current state of the registers by calling |
| /// [`zx_thread_read_state()`](thread_read_state.md#zx_thread_state_debug_regs). |
| /// |
| /// #### ARM Debug Hardware Debug Registers |
| /// |
| /// ARM debug registers are highly configurable via their DBGBCR<n> registers. |
| /// However, Zircon limits that functionality to _Unlinked Address Matching_ HW |
| /// breakpoints. This means that HW breakpoints will only issue exceptions upon |
| /// exception on the given address in the corresponding DBGBVR register. |
| /// |
| /// Because of this, all the values within DBGBCR will be ignored except for the E |
| /// bit, which is used to determine whether that particular breakpoint is activated |
| /// or not. Said in another way, in order to activate a HW breakpoint, all that is |
| /// needed is to set the correct address in DBGBVR and write 1 to DBGBCR. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_THREAD** and have **ZX_RIGHT_WRITE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_write_state()` returns **ZX_OK** on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not that of a thread. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* lacks **ZX_RIGHT_WRITE**. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *kind* is not valid, *buffer* is an invalid pointer, |
| /// *buffer_size* doesn't match the size of the structure expected for *kind* or |
| /// the given values to set are not valid. |
| /// |
| /// **ZX_ERR_NO_MEMORY** Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// **ZX_ERR_BAD_STATE** The thread is not stopped at a point where state |
| /// is available. The thread state may only be read when the thread is stopped due |
| /// to an exception. |
| /// |
| /// **ZX_ERR_NOT_SUPPORTED** *kind* is not supported. |
| /// This can happen, for example, when trying to read a register set that |
| /// is not supported by the hardware the program is currently running on, |
| /// or when using the `ZX_THREAD_STATE_DEBUG_REGS` kind without specifying |
| /// `kernel.enable-serial-syscalls=true` on the kernel command line. |
| /// |
| /// #### ARM |
| /// |
| /// **ZX_ERR_INVALID_ARGS** If the address provided to a DBGBVR register is not |
| /// valid (ie. not addressable from userspace). Also if any value is set for a HW |
| /// breakpoint beyond the number provided by the platform (see above for |
| /// information about retrieving that number). |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_thread_read_state()`] |
| /// |
| /// [`zx_thread_read_state()`]: thread_read_state.md |
| strict WriteState(resource struct { |
| handle Handle:THREAD; |
| kind uint32; |
| @voidptr |
| buffer vector<byte>:MAX; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Yield the CPU of the current thread back to the scheduler. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_legacy_yield(uint32_t options); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_legacy_yield()` causes the calling thread to yield the CPU back to the scheduler. |
| /// |
| /// Yield may result in other threads with similar importance running ahead of the current thread, |
| /// however, the exact behavior is unspecified. |
| /// |
| /// `options` must be zero. |
| /// |
| /// ## Rights |
| /// |
| /// TODO(fxbug.dev/32253) |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_legacy_yield(uint32_t options)` will always return `ZX_OK` for zero `options`. |
| /// Any other `options` value, will result in `ZX_ERR_INVALID_ARGS`. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_nanosleep()`] |
| /// |
| /// [`zx_nanosleep()`]: nanosleep.md |
| strict LegacyYield(resource struct { |
| options uint32; |
| }) -> () error Status; |
| }; |