| XCALL(9) | Kernel Developer's Manual | XCALL(9) | 
xcall, xc_broadcast,
  xc_unicast, xc_wait,
  xc_barrier —
#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);
void
  
  xc_barrier(u_int
    flags);
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.
xc_broadcast(flags,
    func, arg1,
    arg2)xc_wait() on for the cross-call to complete.
      flags should be XC_HIGHPRI
      or
      XC_HIGHPRI_IPLXC_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)xc_broadcast(), but call
      func on only the CPU indicated by
      ci. xc_unicast() also
      returns a “ticket”.xc_wait(where)xc_broadcast() or
      xc_unicast() for the corresponding cross-call to
      complete. xc_wait() should be called from a thread
      context.xc_barrier(flags)This functions like a memory barrier that forces all prior operations in program order to globally happen before all subsequent operations in program order, as witnessed by every CPU.
This additionally waits for all higher-priority activity on the CPU to complete, according to flags:
xc_barrier(0); waits
          for any pending
          kpreempt_disable(9)
          sections or activity at interrupt priority level above
          IPL_NONE to finish on all CPUs.xc_barrier(XC_HIGHPRI_IPLxc_barrier() is much more expensive
        than membar_ops(3), so
        it should be used sparingly, only to publish information infrequently
        — for example, during module load and unload — when the
        cost of a memory barrier on the consumer side would be prohibitive.
xcall interface is implemented within the file
  sys/kern/subr_xcall.c.
xcall interface first appeared in
  NetBSD 5.0.
| February 1, 2020 | NetBSD 10.0 |