blob: d705ade8ab2b363a7d7308218d9a1113af0df115 [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;
type ExceptionContext = struct {
// TODO
};
@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(https://fxbug.dev/42107318)
///
/// ## 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
///
/// Raise a user-generated exception.
///
/// ## Declaration
///
/// ```c
/// #include <zircon/syscalls.h>
///
/// zx_status_t zx_thread_raise_exception(uint32_t options,
/// zx_excp_type_t type,
/// const zx_exception_context_t* context
/// size_t context_size);
/// ```
///
/// ## Description
///
/// `zx_thread_raise_exception()` raises a user-generated exception. The exception
/// will be delivered to the exception channels associated with the current thread.
///
/// Currently, the *options* argument must be `ZX_EXCEPTION_TARGET_JOB_DEBUGGER`,
/// which causes the exception to be delivered to the job debugger exception channels.
/// In the future, *options* may be expanded to enable targeting other types of
/// exception channels.
///
/// The the *type* argument must be be `ZX_EXCP_USER`. In the future, *type* may be
/// expanded to enable raising other types of exceptions.
///
/// The `arch` field in `zx_exception_context_t` is ignored. Instead, use the
/// `synth_code` and `synth_data` fields to communicate information about the exception.
/// Codes less than `ZX_EXCP_USER_CODE_USER0` are reserved for system-defined purposes.
/// Applications may use codes greater than or equal to `ZX_EXCP_USER_CODE_USER0` for
/// their own purposes.
///
/// ## Return value
///
/// `zx_thread_raise_exception()` returns `ZX_OK` on success.
/// In the event of failure, a negative error value is returned.
///
/// ## Errors
///
/// `ZX_ERR_INVALID_ARGS` *options* is a value other than
/// `ZX_EXCEPTION_TARGET_JOB_DEBUGGER` or *type* is a value other than
/// *ZX_EXCP_USER*.
///
/// `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_task_create_exception_channel()`]
///
/// [`zx_task_create_exception_channel()`]: task_create_exception_channel.md
strict RaiseException(struct {
options uint32;
type uint32;
context ExceptionContext;
}) -> () 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(https://fxbug.dev/42107318)
///
/// ## 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;
};