| // 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; |
| |
| @transport("Syscall") |
| closed protocol Task { |
| // TODO(scottmg): Need something like handle:TASK in this file to mean {job, process, thread}. |
| // Or otherwise some way to express multiple options for constraints on inputs in this protocol. |
| |
| /// ## Summary |
| /// |
| /// Suspend the given task. Currently only thread or process handles may be suspended. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_task_suspend(zx_handle_t handle, zx_handle_t* token); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_task_suspend()` causes the requested task to suspend |
| /// execution. Task suspension is not synchronous and the task might not |
| /// be suspended before the call returns. The task will be suspended soon |
| /// after `zx_task_suspend()` is invoked, unless it is currently blocked in |
| /// the kernel, in which case it will suspend after being unblocked. |
| /// |
| /// Tasks can be suspended and/or resumed before they are started. If a task is |
| /// started while suspended, it will enter suspension before executing any code. |
| /// Similarly, starting a new thread on a suspended process will suspend the thread |
| /// before it executes any code. |
| /// |
| /// Invoking [`zx_task_kill()`] on a task that is suspended will successfully kill |
| /// the task. |
| /// |
| /// A task cannot suspend itself or any of its parent tasks because it would never |
| /// receive the suspend token and would be unable to resume execution. |
| /// |
| /// ## RESUMING |
| /// |
| /// To allow the task to resume, close the suspend token handle. The task will |
| /// remain suspended as long as there are any open suspend tokens. Like suspending, |
| /// resuming is asynchronous so the thread may not be in a running state when the |
| /// [`zx_handle_close()`] call returns, even if no other suspend tokens |
| /// are open. |
| /// |
| /// ## SIGNALS AND EXCEPTIONS |
| /// |
| /// There are two relevant signals that a thread can assert: |
| /// |
| /// - `ZX_THREAD_RUNNING` |
| /// - `ZX_THREAD_SUSPENDED` |
| /// |
| /// Neither of these will be asserted until the thread is started via |
| /// [`zx_process_start()`] or [`zx_thread_start()`]. When |
| /// a thread starts, it will assert `ZX_THREAD_RUNNING` whether it is suspended |
| /// or not, but if it is suspended will then switch to `ZX_THREAD_SUSPENDED` |
| /// before executing any code. |
| /// |
| /// The `ZX_EXCP_PROCESS_STARTING` and `ZX_EXCP_THREAD_STARTING` debug |
| /// exceptions will also be sent on start whether the task is suspended or not. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type `ZX_OBJ_TYPE_THREAD` or `ZX_OBJ_TYPE_PROCESS` and have `ZX_RIGHT_WRITE`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_task_suspend()` 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 a thread or process handle. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *token* was an invalid pointer. |
| /// |
| /// `ZX_ERR_BAD_STATE` The task is already dying or dead and cannot be suspended. |
| /// |
| /// `ZX_ERR_NO_MEMORY` Failed to allocate memory. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` The calling thread is attempting to suspend itself or |
| /// one of its parent tasks. |
| /// |
| /// ## LIMITATIONS |
| /// |
| /// Currently only thread and process handles are supported. |
| /// |
| /// [`zx_handle_close()`]: handle_close.md |
| /// [`zx_process_start()`]: process_start.md |
| /// [`zx_task_kill()`]: task_kill.md |
| /// [`zx_thread_start()`]: thread_start.md |
| strict Suspend(resource struct { |
| handle Handle; |
| }) -> (resource struct { |
| token Handle; |
| }) error Status; |
| |
| /// This function replaces [task_suspend](task_suspend.md). When all callers are |
| /// updated, [`zx_task_suspend()`] will be deleted and this function will be renamed |
| /// [`zx_task_suspend()`]. |
| /// |
| /// ## Summary |
| /// |
| /// Suspend the given task. Currently only thread or process handles may be suspended. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_task_suspend_token(zx_handle_t handle, zx_handle_t* token); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_task_suspend_token()` causes the requested task to suspend execution. Task |
| /// suspension is not synchronous and the task might not be suspended before the |
| /// call returns. The task will be suspended soon after `zx_task_suspend_token()` is |
| /// invoked, unless it is currently blocked in the kernel, in which case it will |
| /// suspend after being unblocked. |
| /// |
| /// Invoking [`zx_task_kill()`] on a task that is suspended will successfully kill |
| /// the task. |
| /// |
| /// ## RESUMING |
| /// |
| /// The allow the task to resume, close the suspend token handle. The task will |
| /// remain suspended as long as there are any open suspend tokens. Like suspending, |
| /// resuming is asynchronous so the thread may not be in a running state when the |
| /// [`zx_handle_close()`] call returns, even if no other suspend tokens |
| /// are open. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type `ZX_OBJ_TYPE_THREAD` or `ZX_OBJ_TYPE_PROCESS` and have `ZX_RIGHT_WRITE`. |
| /// |
| /// ## Return value |
| /// |
| /// [`zx_task_suspend()`] 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 a thread handle. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *token* was an invalid pointer. |
| /// |
| /// `ZX_ERR_BAD_STATE` The task is not in a state where suspending is possible. |
| /// |
| /// ## LIMITATIONS |
| /// |
| /// Currently only thread handles are supported. |
| /// |
| /// [`zx_handle_close()`]: handle_close.md |
| /// [`zx_task_kill()`]: task_kill.md |
| /// [`zx_task_suspend()`]: task_suspend.md |
| strict SuspendToken(resource struct { |
| handle Handle; |
| }) -> (resource struct { |
| token Handle; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Create an exception channel for a given job, process, or thread. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_task_create_exception_channel(zx_handle_t handle, |
| /// uint32_t options, |
| /// zx_handle_t* out); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_task_create_exception_channel()` creates a channel that will receive |
| /// exceptions from the thread, process, or job. |
| /// |
| /// *handle* is the thread, process, or job handle to receive exceptions from. |
| /// |
| /// *options* can be 0 or `ZX_EXCEPTION_CHANNEL_DEBUGGER` to register for debug |
| /// exceptions (process or job only). |
| /// |
| /// *out* will be filled with the newly created channel endpoint on success. This |
| /// channel will be read-only with the following rights: |
| /// |
| /// * `ZX_RIGHT_TRANSFER` |
| /// * `ZX_RIGHT_WAIT` |
| /// * `ZX_RIGHT_READ` |
| /// |
| /// ### Number of Exception Channels |
| /// |
| /// Each task may have at most one regular exception channel and one debugger |
| /// exception channel, except for jobs. A single job may have up to |
| /// `ZX_EXCEPTION_CHANNEL_JOB_DEBUGGER_MAX_COUNT` debugger exception channels. |
| /// |
| /// Attempting to create an exception channel on a task that already has the maximum |
| /// number of channels for a given type will result in `ZX_ERR_ALREADY_BOUND`. |
| /// |
| /// ### Exception Messages |
| /// |
| /// When an exception occurs, the channel will receive a message containing one |
| /// exception handle and one `zx_exception_info_t` data. |
| /// |
| /// The thread will remain blocked in the exception until the received exception |
| /// handle is closed, at which point it will either resume or exception processing |
| /// will continue according to the chosen behavior (see `ZX_PROP_EXCEPTION_STATE` |
| /// in [`zx_object_get_property()`]). |
| /// |
| /// ### Unbinding |
| /// |
| /// Closing the created channel handle will unregister the exception handler. If |
| /// an exception message is waiting in the channel at the time it's closed, exception |
| /// handling will continue on to the next handler in the search order. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must have `ZX_RIGHT_INSPECT` and have `ZX_RIGHT_DUPLICATE` and have `ZX_RIGHT_TRANSFER` and have `ZX_RIGHT_MANAGE_THREAD`. |
| /// |
| /// If *handle* is of type `ZX_OBJ_TYPE_JOB` or `ZX_OBJ_TYPE_PROCESS`, it must have `ZX_RIGHT_ENUMERATE`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_task_create_exception_channel()` returns `ZX_OK` on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` The caller has a job policy in place preventing the |
| /// creation of new channels. |
| /// |
| /// `ZX_ERR_ALREADY_BOUND` The maximum number of exception channels of the given |
| /// type are already bound to *handle*. |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_BAD_STATE` *handle* is dying or dead. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` A bad value has been passed in *options*. |
| /// |
| /// `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_WRONG_TYPE` *handle* is not that of a job, process, or thread. |
| /// |
| /// ## See also |
| /// |
| /// - [exceptions] |
| /// - [`zx_channel_read()`] |
| /// |
| /// [exceptions]: /docs/concepts/kernel/exceptions.md |
| /// [`zx_channel_read()`]: channel_read.md |
| /// [`zx_object_get_property()`]: object_get_property.md |
| strict CreateExceptionChannel(resource struct { |
| handle Handle; |
| options uint32; |
| }) -> (resource struct { |
| out Handle:CHANNEL; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Kill the provided job or process. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_task_kill(zx_handle_t handle); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// This asynchronously kills the given process or job and its children recursively, |
| /// until the entire task tree rooted at *handle* is dead. |
| /// Killing a thread is not supported. |
| /// |
| /// It is possible to wait for the task to be dead via the `ZX_TASK_TERMINATED` |
| /// signal. When the procedure completes, as observed by the signal, the task and |
| /// all its children are considered to be in the dead state and most operations |
| /// will no longer succeed. |
| /// |
| /// If *handle* is a job and the syscall is successful, the job can no longer be |
| /// used to create new processes. |
| /// |
| /// When a process or job is killed via this syscall, the `return_code` is |
| /// `ZX_TASK_RETCODE_SYSCALL_KILL` as reported by [`zx_object_get_info()`] via |
| /// the `ZX_INFO_PROCESS` or `ZX_INFO_JOB` topic. |
| /// |
| /// Processes and Jobs can also be killed by other agents such as the Job policy with |
| /// `ZX_POL_ACTION_KILL` or when the system is running low on memory [OOM](/docs/development/kernel/memory/oom.md). |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must have `ZX_RIGHT_DESTROY`. |
| /// |
| /// ## Return value |
| /// |
| /// On success, `zx_task_kill()` returns `ZX_OK`. If a process uses |
| /// this syscall to kill itself, this syscall does not return. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* is not a task handle. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` *handle* does not have the `ZX_RIGHT_DESTROY` |
| /// right. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` *handle* is a thread handle. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_job_create()`] |
| /// - [`zx_process_create()`] |
| /// |
| /// [`zx_job_create()`]: job_create.md |
| /// [`zx_object_get_info()`]: object_get_info.md |
| /// [`zx_process_create()`]: process_create.md |
| strict Kill(resource struct { |
| handle Handle; |
| }) -> () error Status; |
| }; |