| // 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_regs(zx_handle_t handle, |
| /// uint64_t pc, |
| /// uint64_t sp, |
| /// uint64_t arg1, |
| /// uint64_t arg2, |
| /// uint64_t tp, |
| /// uint64_t abi_reg); |
| /// zx_status_t zx_thread_start(zx_handle_t handle, |
| /// zx_vaddr_t pc, |
| /// zx_vaddr_t sp, |
| /// uintptr_t arg1, |
| /// uintptr_t arg2); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// _**TODO(https://fxbug.dev/478347581):** The new signature with *tp* and |
| /// *abi_reg* arguments is the preferred ABI in Fucshia API level 31 and |
| /// later. This will eventually be renamed to `zx_thread_start` when |
| /// API levels before 31 are no longer supported. The older signature |
| /// behaves exactly the same, with zero used for the new arguments._ |
| /// |
| /// `zx_thread_start()` causes a thread to begin execution. Its initial |
| /// registers are set as follows: |
| /// |
| /// * The program counter is set to the *pc* argument. |
| /// * The stack pointer is set to the *sp* argument. |
| /// * The first two argument registers in the machine's C calling |
| /// convention are set to *arg1* and *arg2*, respectively. |
| /// * The machine's thread pointer register is set to the *tp* argument. |
| /// * The register used by the machine ABI for the shadow call stack |
| /// pointer is set to *abi_reg*. On x86 where there is no shadow call |
| /// stack ABI, this value goes into the `r15` register. |
| /// * All other general registers are zero. |
| /// * All floating-point and/or vector registers are in the machine's |
| /// initial state (usually mostly zero). |
| /// |
| /// Each register value given must be some value that it's possible for |
| /// normal code to get into that register somehow. If not, the call fails |
| /// with `ZX_ERR_INVALID_ARGS`. For example, the PC on some machines can |
| /// only be set to a "canonical" address: it doesn't have to be a _valid_ |
| /// address--it can be something that will cause a fault when the thread |
| /// actually executes at that PC, just like a normal jump instruction would |
| /// set the PC and then fault; but it cannot be a "noncanonical" address, |
| /// where a jump instruction _itself_ would fault without changing the PC. |
| /// Similarly, the stack pointer might need to be a pointer with valid |
| /// machine-required alignment (even if not an _actually valid_ address); |
| /// or the thread pointer might need to be a canonical address. For all |
| /// these registers on all machines, zero is always a valid argument value. |
| /// |
| /// 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). |
| /// |
| /// *pc* 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: |
| /// |
| /// ```c |
| /// [[noreturn]] void thread_entry(uint64_t arg1, uint64_t arg2) { |
| /// // 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` One of the register values is impossible for the |
| /// machine to use. |
| /// |
| /// ## 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 |
| |
| // TODO(https://fxbug.dev/478347581): The new signature now called |
| // StartRegs will be renamed back to Start after API levels <= 30 are |
| // retired, with StartRegs left as an alias until all later API levels that |
| // still had the old Start signature are retired. |
| |
| @vdsocall |
| strict Start(resource struct { |
| handle Handle:THREAD; |
| thread_entry Vaddr; |
| stack Vaddr; |
| arg1 uintptr64; |
| arg2 uintptr64; |
| }) -> () error Status; |
| |
| strict StartRegs(resource struct { |
| handle Handle:THREAD; |
| pc uint64; |
| sp uint64; |
| arg1 uint64; |
| arg2 uint64; |
| tp uint64; |
| abi_reg uint64; |
| }) -> () 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); |
| /// ``` |
| /// |
| /// ## 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`, *type* is a value other than |
| /// *ZX_EXCP_USER*, or *context* 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. |
| /// |
| /// ## 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 |
| /// |
| /// Register a restartable sequence for a thread. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_thread_set_rseq(zx_handle_t vmo, uint64_t offset, uint64_t size); |
| /// |
| /// ## Description |
| /// |
| /// `zx_thread_set_rseq()` registers a restartable sequence for the current thread. The |
| /// restartable sequence is defined by a `zx_rseq_t` structure in the VMO starting at |
| /// *offset* and of length *size*. |
| /// |
| /// Zircon will keep the `cpu_id` field in the `zx_rseq_t` structure up to date with the |
| /// current CPU ID of the thread. If the thread is migrated to a different CPU while the |
| /// instruction pointer is in the restartable sequence defined by the `start_ip` and |
| /// `post_commit_offset` fields, the thread will resume execution at the address |
| /// specified by the `abort_ip` field. |
| /// |
| /// Userspace should use volatile reads and writes to access the `zx_rseq_t` structure because |
| /// the kernel may modify the `cpu_id` field at any time, and the `start_ip`, |
| /// `post_commit_offset`, and `abort_ip` fields may be read by the kernel at any time. |
| /// |
| /// At most one restartable sequence may be registered at a time. If the thread is already |
| /// has a restartable sequence registered, `zx_thread_set_rseq()` will return |
| /// `ZX_ERR_ALREADY_EXISTS`. |
| /// |
| /// The *offset* must be 0 mod `alignof(zx_rseq_t)` and the region of size `sizeof(zx_rseq_t)` |
| /// starting at *offset* must not span a page boundary. |
| /// |
| /// To unregister a restartable sequence, call `zx_thread_set_rseq()` with `ZX_HANDLE_INVALID` |
| /// for the *vmo* argument. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_thread_set_rseq()` returns `ZX_OK` on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *offset* is not a multiple of `alignof(zx_rseq_t)`, |
| /// *size* is not `sizeof(zx_rseq_t)`, or the region of memory defined by |
| /// *offset* and *size* spans a page boundary. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *vmo* is not directly writable, has been |
| /// marked as uncached, or is backed by a user pager. |
| /// |
| /// `ZX_ERR_ALREADY_EXISTS` The thread already has a restartable sequence registered. |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *vmo* is neither a valid handle nor `ZX_HANDLE_INVALID`. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *vmo* is not a VMO. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` *vmo* is missing `ZX_RIGHT_READ`, `ZX_RIGHT_WRITE`, or |
| /// `ZX_RIGHT_DUPLICATE`. |
| strict SetRseq(resource struct { |
| vmo Handle:VMO; |
| offset uint64; |
| size uint64; |
| }) -> () 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; |
| }; |