Manual Page Result
0
Command: cpu_copy_thread | Section: 9 | Source: FreeBSD | File: cpu_copy_thread.9.gz
cpu_machdep(9) FreeBSD Kernel Developer's Manual cpu_machdep(9)
NAME
cpu_machdep, cpu_copy_thread, cpu_exec_vmspace_reuse, cpu_exit,
cpu_fetch_syscall_args, cpu_fork, cpu_fork_kthread_handler, cpu_idle,
cpu_idle_wakeup, cpu_procctl, cpu_set_syscall_retval, cpu_set_upcall,
cpu_set_user_tls, cpu_switch, cpu_sync_core, cpu_thread_alloc,
cpu_thread_clean, cpu_thread_exit, cpu_thread_free, cpu_throw - machine-
dependent interfaces to handle CPU and thread state
SYNOPSIS
#include <sys/proc.h>
#include <sys/ptrace.h>
void
cpu_copy_thread(struct thread *td, struct thread *td0);
bool
cpu_exec_vmspace_reuse(struct proc *p, struct vm_map *map);
void
cpu_exit(struct thread *td);
int
cpu_fetch_syscall_args(struct thread *td);
void
cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2,
int flags);
void
cpu_fork_kthread_handler(struct thread *td, void (*func)(void *),
void *arg);
void
cpu_idle(int busy);
int
cpu_idle_wakeup(int cpu);
int
cpu_procctl(struct thread *td, int idtype, id_t id, int com, void *data);
int
cpu_ptrace(struct thread *_td, int req, void *addr, int data);
void
cpu_set_syscall_retval(struct thread *td, int error);
int
cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
stack_t *stack);
int
cpu_set_user_tls(struct thread *td, void *tls_base);
void
cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx);
void
cpu_sync_core(void);
void
cpu_thread_alloc(struct thread *td);
void
cpu_thread_clean(struct thread *td);
void
cpu_thread_exit(struct thread *td);
void
cpu_thread_free(struct thread *td);
void
cpu_throw(struct thread *old, struct thread *new);
DESCRIPTION
These functions provide architecture-specific implementations of machine-
independent abstractions.
cpu_exec_vmspace_reuse() returns true if exec_new_vmspace() can reuse an
existing struct vmspace (map) for the process p during execve(2). This
is only invoked if map is not shared with any other consumers. If this
returns false, exec_new_vmspace() will create a new struct vmspace.
cpu_exit() releases machine-dependent resources other than the address
space for the process containing td during process exit.
cpu_fork() copies and updates machine-dependent state (for example, the
pcb and user registers) from the forking thread td1 in an existing
process to the new thread td2 in the new process p2. This function must
set up the new thread's kernel stack and pcb so that td2 calls
fork_exit() when it begins execution passing a pointer to fork_return()
as the callout argument and td2 as the arg argument.
cpu_fork_kthread_handler() adjusts a new thread's initial pcb and/or
kernel stack to pass func and arg as the callout and arg arguments to
fork_exit(). This must be called before a new thread is scheduled to run
and is used to set the "main" function for kernel threads.
cpu_copy_thread() copies machine-dependent state (for example, the pcb
and user registers) from td to td0 when creating a new thread in the same
process. This function must set up the new thread's kernel stack and pcb
so that td0 calls fork_exit() when it begins execution passing a pointer
to fork_return() as the callout argument and td0 as the arg argument.
cpu_set_upcall() updates a new thread's initial user register state to
call entry with arg as the sole argument using the user stack described
in stack.
cpu_set_user_tls() sets a new thread's initial user thread pointer
register to reference the user TLS base pointer tls_base.
cpu_fetch_syscall_args() fetches the current system call arguments for
the native FreeBSD ABI from the current thread's user register state
and/or user stack. The arguments are saved in the td_sa member of td.
cpu_set_syscall_retval() updates the user register state for td to store
system call error and return values. If error is 0, indicate success and
return the two values in td_retval. If error is ERESTART, adjust the
user PC to re-invoke the current system call after returning to user
mode. If error is EJUSTRETURN, leave the current user register state
unchanged. For any other value of error, indicate error and return error
as the error code.
cpu_idle() waits for the next interrupt to occur on the current CPU. If
an architecture supports low power idling, this function should place the
CPU into a low power state while waiting. busy is a hint from the
scheduler. If busy is non-zero, the scheduler expects a short sleep, so
the CPU should prefer low-latency over maximum power savings. If busy is
zero, the CPU should maximumize power savings including deferring
unnecessary clock interrupts via cpu_idleclock().
cpu_idle_wakeup() awakens the idle CPU with the ID cpu from a low-power
state.
cpu_procctl() handles any machine-dependent procctl(2) requests.
cpu_ptrace() handles any machine-dependent ptrace(2) requests.
cpu_switch() switches the current CPU between threads by swapping
register state. This function saves the current CPU register state in
the pcb of old and loads register values from the pcb of new before
returning. While the pcb generally contains caller-save kernel register
state, it can also contain user registers that are not saved in the
trapframe.
After saving the current CPU register state of old, cpu_switch() stores
mtx in the td_lock member of old transferring ownership of the old
thread. No data belonging to old can be accessed after that store.
Specifically, the old thread's kernel stack must not be accessed after
this point.
When SCHED_ULE is being used, this function must wait (via spinning) for
the td_lock member of new to change to a value not equal to &blocked_lock
before loading register values from new or accessing its kernel stack.
From the caller's perspective, cpu_switch() returns when old is
rescheduled in the future, possibly on a different CPU. However, the
implementation of cpu_switch() returns immediately on the same CPU into
the previously-saved context of new.
cpu_throw() is similar to cpu_switch() but does not save any state for
old or write to the old thread's td_lock member.
cpu_sync_core() ensures that all possible speculation and out-of-order
execution is serialized on the current CPU. Note that this is called
from an IPI handler so only has to handle additional serialization beyond
that provided by handling an IPI.
Thread Object Lifecycle
These functions support the management of machine-dependent thread state
in conjunction with a thread object's lifecycle.
The general model is that a thread object is allocated each time a new
kernel thread is created either by system calls like fork(2) or
thr_new(2) or when kernel-only threads are created via kproc_create(9),
kproc_kthread_add(9), or kthread_add(9). When a kernel thread exits, the
thread object is freed. However, there is one special case to support an
optimization where each free process object caches a thread object. When
a process exits, the last thread object is not freed but remains attached
to the process. When the process object is later reused for a new
process in fork(2), the kernel recycles that last thread object and uses
it as the initial thread in the new process. When a thread is recycled,
some of the steps in the thread allocation and free cycle are skipped as
an optimization.
cpu_thread_alloc() initializes machine-dependent fields in td after
allocating a new kernel stack. This function typically sets the td_pcb
and initial td_frame pointers. cpu_thread_alloc() is called both when
allocating a new thread object and when a recycled thread allocates a new
kernel stack. Note that this function is not called if a recycled thread
reuses its existing kernel stack.
cpu_thread_clean() releases any machine-dependent resources for the last
thread in a process during wait(2). The thread is a candidate for
recycling so should be reset to run as a new thread in case it is
recycled by a future fork(2).
cpu_thread_exit() cleans any machine-dependent state in td while it is
exiting. This is called by the exiting thread so cannot free state
needed during in-kernel execution.
cpu_thread_free() releases any machine-dependent state in td when it is
being freed. This is called for any thread that was not the last thread
in a process once it has finished execution.
SEE ALSO
fork(2), procctl(2), ptrace(2), thr_new(2), wait(2), kproc_create(9),
kproc_kthread_add(9), kthread_add(9), mi_switch(9)
AUTHORS
This manual page was developed by SRI International, the University of
Cambridge Computer Laboratory (Department of Computer Science and
Technology), and Capabilities Limited under contract (FA8750-24-C-B047)
("DEC").
FreeBSD 14.1-RELEASE-p8 January 3, 2025 FreeBSD 14.1-RELEASE-p8