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