XCALL(9) | Kernel Developer's Manual | XCALL(9)

# NAME

`xcall`, `xc_broadcast`, `xc_unicast`, `xc_wait` —
cross-call interface

# SYNOPSIS

`#include <sys/xcall.h>`

typedef void (*xcfunc_t)(void *, void *);

uint64_t
`xc_broadcast`(u_int flags, xcfunc_t func, void *arg1, void *arg2);

uint64_t
`xc_unicast`(u_int flags, xcfunc_t func, void *arg1, void *arg2, struct cpu_info *ci);

void
`xc_wait`(uint64_t where);

# DESCRIPTION

The machine-independent `xcall` interface allows any CPU in the system to request that an arbitrary function be executed on any other CPU.

Sometimes it is necessary to modify hardware state that is tied directly to individual CPUs (such as a CPU's local timer), and these updates can not be done remotely by another CPU. The LWP requesting the update may be unable to guarantee that it will be running on the CPU where the update must occur, when the update occurs.

Additionally, it is sometimes necessary to modify per-CPU software state from a remote CPU. Where these update operations are so rare or the access to the per-CPU data so frequent that the cost of using locking or atomic operations to provide coherency is prohibitive, another way must be found.

Cross calls help to solve these types of problem. However, since this facility is heavyweight, it is expected that it will not be used often.

`xcall` provides a mechanism for making “low priority” cross calls. The function to be executed runs on the remote CPU within a thread context, and not from a software interrupt, so it can ensure that it is not interrupting other code running on the CPU, and so has exclusive access to the CPU. Keep in mind that unless disabled, it may cause a kernel preemption.

`xcall` also provides a mechanism for making “high priority” cross calls. The function to be executed runs on the remote CPU within a software interrupt context, possibly interrupting other lower-priority code running on the CPU.

# NOTES

Functions being called should be relatively lightweight. They may block on locks, but carefully and minimally, to not interfere with other cross calls in the system.

# FUNCTIONS

`xc_broadcast`(flags, func, arg1, arg2)
  Call `(*func)`(arg1, arg2); on all CPUs in the system. Return a uint64_t “ticket” to `xc_wait`() on for the cross-call to complete. flags should be `XC_HIGHPRI` or `XC_HIGHPRI_IPL`(ipl); for a "high priority" call, and 0 for a "low priority" call. `XC_HIGHPRI` uses an `IPL_SOFTSERIAL` software interrupt while `XC_HIGHPRI_IPL`() uses a software interrupt with an IPL specified by ipl. `xc_broadcast`() should not be called from interrupt context.
`xc_unicast`(flags, func, arg1, arg2, ci)
  Like `xc_broadcast`(), but call `(*func)`() on only the CPU indicated by ci. `xc_unicast`() also returns a “ticket”.
`xc_wait`(where)
  Wait on the “ticket” returned by a prior `xc_broadcast`() or `xc_unicast`() for the corresponding cross-call to complete. `xc_wait`() should be called from a thread context.

# CODE REFERENCES

The `xcall` interface is implemented within the file sys/kern/subr_xcall.c.

# SEE ALSO

kpreempt(9), percpu(9), softint(9)

# HISTORY

The `xcall` interface first appeared in NetBSD 5.0.

# AUTHORS

Andrew Doran <ad@NetBSD.org>

February 1, 2018 | NetBSD 9.5