Implementation

Starting from PXROS-HR v8.x.x, there are two implementations of PxHndcall:

  • Original - based on GCC extension called "nested functions"

    • _PxHndcall() macro is defined in <pxdef.h>

    • Limited to be used only in C modules (not in C++) and only with GCC

  • New - Separate utility, GCC independent, both C and C++ compatible

    • Available as a source code or pre-compiled library in "utilities" folder

Original implementation (PXROS-HR API)

_PxHndcall() is implemented as a variadic macro in "pxdef.h" and is part of PXROS-HR API.

pxhndcall original
Fig. 1. Variadic macro
  1. "parms…​" makes the macro variadic, i.e. it would accept any number of arguments starting from 3 (3, 4, 5, …​ ).

  2. The return value of the handler is type-casted to type PxArg_t to be compatible with error code that might be eventually returned.

  3. Definition of the nested function "_" (3 underscores).

  4. The attribute "pxhndcall" tells the compiler to use special call mechanism.

  5. Function "_" accepts two arguments; first one is the service type (syscall number).

  6. Calling the handler itself with supervisor privileges. The handler accepts variable number of arguments (even zero).

  7. Calling the "_" function leads to syscall(SV_HNDCALL). This is an effect of a compiler-specific "pxhndcall" attribute.

Assumption of use

PxArg_t _PxHndcall(handler, task, varsize, parms...)
  • The handler will get variable number of arguments from "parms…​"

  • task and varsize arguments must be present but are not used

  • The return value should be considered only as an error status provided by the PxHndcall mechanism.

  • I.e., The return value shouldn’t be used for passing general value from the handler to a calling task (for example result of an ADC).

Error handling

The return value of the _PxHndcall() with respect to different situations:

Situation Returned value

PxHndcall is not called from the task level

PXERR_PXHND_ILLCALL

The calling task does not have the PXACCESS_HANDLERS right

PXERR_ACCESS_RIGHT

Handler has been executed correctly

Return value of the handler

As the calling task cannot distinguish between the return value of the handler and the potential error code, the return value cannot be used for passing general value from the handler. Passing general data from handler to task should be implemented by pointer(s).

New implementation (kernel utility)

A new implementation was introduced to ensure compatibility with both C and C++ while still maintaining the original interface.

Original _PxHndcall macro is redefined by including "pxhndcall.h" from utilities.

pxhndcall new implementation
Fig. 2. Variadic macro redefined with utility implementation

Additional interfaces provides more convenient usage of the PxHndcall:

  • no need to provide unused parameters

  • intuitive naming through suffixes: VA (variable number of arguments) or PTR (pointer argument)

pxhndcall new interfaces
Fig. 3. Additional interfaces

Migrating from original to new version

Even if the new implementation provides the same syntax of the _PxHndcall() macro, it is not in all cases 100% compatible with the original version. The handler prototype to be called by new implementation of PxHndcall (including VA and PTR versions) must use the C calling convention, i.e., there can be only one pointer argument in the handler prototype.

Example of allowed handler prototypes:

int handler(va_list va);
int handler(void *p);