blob: 0e00f161acb193fa9a62405e860765ac32e8faef [file] [log] [blame] [view]
<!--
Copyright 2023 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.
DO NOT EDIT. Generated from FIDL library zx by zither, a Fuchsia platform tool.
See //docs/reference/syscalls/README.md#documentation-generation for
regeneration instructions.
-->
# zx_thread_start
## 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