Summary
Start execution on a thread.
Declaration
#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
r15register. - 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:
[[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.