blob: 79c64bdd7f403c7baf670b4605be3234b7c7491f [file] [log] [blame]
// 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")
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
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
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
Start(resource struct {
handle handle:THREAD;
thread_entry vaddr;
stack vaddr;
arg1 uintptr;
arg2 uintptr;
}) -> () 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).
ReadState(resource struct {
handle handle:THREAD;
kind uint32;
}) -> (struct {
@voidptr
buffer vector<byte>;
}) 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
WriteState(resource struct {
handle handle:THREAD;
kind uint32;
@voidptr
buffer vector<byte>;
}) -> () 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
LegacyYield(resource struct {
options uint32;
}) -> () error status;
};