zx_thread_start

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 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:

[[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