(QNX Neutrino 7.0.4 or later) You can use the custom() callout to define a callout function to be invoked synchronously when a kernel call with the value __KER_SYS_CUSTOM (defined in <sys/kercalls.h>) is invoked by a process.
The function is called in privileged mode (EL1/Ring0) and using the kernel stack, but without entering the kernel. Interrupts are disabled. In general, the same rules and restrictions apply as for an ISR: keep it short, don't enable interrupts, and don't make any kernel calls.
The signature for the callout is
uintptr_t (*custom_callout)( struct syspage_entry *syspageptr, uint32_t type_id, uintptr_t *regs )
The arguments are as follows:
Note that there's no C library function wrapping the kernel call, as the C signature of the function depends on the implementation of the callout and is at the discretion of the author of the callout. The kernel only takes care to propagate the registers of the calling thread to and from the callout. The standard ABI should be followed when writing C wrappers for the kernel call.
Here's an example of a custom callout for AArch64:
#include "callout.ah" /* * ----------------------------------------------------------------------- * Routine to patch callout code * * On entry: * r0 - physical address of syspage * r1 - virtual address of syspage * r2 - offset from start of syspage to start of the callout routine * r3 - offset from start of syspage to read/write data used by callout * ----------------------------------------------------------------------- */ patch_custom: ret /* * ----------------------------------------------------------------------- * Sample implementation of a custom kernel call callout. * * On entry: * r0 - pointer to the system page * r1 - type ID for the calling process * r2 - pointer to the first position in an array of 64-bit values holding * the register context of the calling thread * ----------------------------------------------------------------------- */ CALLOUT_START(custom, 0, patch_custom) mov x5, #0xabcd movk x5, #0xabcd, lsl #16 movk x5, #0xabcd, lsl #32 movk x5, #0xabcd, lsl #48 /* * Reject processes with a type ID other than 47. */ cmp x1, #47 beq 1f mov x0, #-1 ret 1: /* * Return the sum of the values held in the caller's x0 and x1 registers. */ ldp x2, x3, [x2] add x0, x2, x3 ret CALLOUT_END(custom)
Here's a program that uses the callout by invoking a kernel call:
#include <stdio.h> extern unsigned long SysCustom(unsigned long a, unsigned long b); int main(int argc, char **argv) { unsigned long rc = SysCustom(3, 4); if (rc == -1) { perror("SysCustom"); } else { printf("rc=%ld\n", rc); } return 0; }