How to use

Original implementation

The original implementation uses a variadic macro defined in PXROS-HR API.

Code 1. Handler definitions
#include <stdarg.h>

int myHandler0()
{
    return 0; /* indicate success */
}

int myHandler1(int arg1)
{
    return 0; /* indicate success */
}

int myHandler2(int arg1, int arg2)
{
    return 0; /* indicate success */
}

int myHandlerX(int arg_cnt, ...)
{
    va_list list;
    va_start(list, arg_cnt);
    int sum = 0;
    int *out_arg = va_arg(list, int *);

    for (int i = 0; i < (arg_cnt - 1); i++)
        sum += va_arg(list, int);

    va_end(list);
    *out_arg = sum;
    return 0; /* indicate success */
}
Code 2. Example of calling different handlers
 /* The _PxHndcall() expects at least three arguments:
  *   1) the function/handler to be called
  *   2) the Task ID (required even if not used)
  *   3) size of the arguments (required even if not used)
  * There can be any number of additional arguments that
  * will be passed to the handler. */

#define UNUSED_TID	0  /* TASK ID - argument not used */
#define UNUSED_VARSIZE	0  /* VARIABLE SIZE - argument not used */

int arg1, arg2, arg3, arg4, arg5, sum; /* Handler's arguments */

PxArg_t retval; /* Handler's return value. For simplicity not checked here. */

/* Calling myHandler0(void), i.e. handler that does not take arguments */
retval = _PxHndcall(myHandler0, UNUSED_TID, UNUSED_VARSIZE);

/* Calling myHandler1(int), i.e. handler accepting one argument */
retval = _PxHndcall(myHandler1, UNUSED_TID, UNUSED_VARSIZE, arg1);

/* Calling myHandler2(int, int), i.e. handler accepting two arguments */
retval = _PxHndcall(myHandler2, UNUSED_TID, UNUSED_VARSIZE, arg1, arg2);

/* Calling myHandlerX(int, ...), i.e. handler accepting any number of arguments */
retval = _PxHndcall(myHandlerX, UNUSED_TID, UNUSED_VARSIZE,
                    6 /* nr. of args */, &sum, arg1, arg2, arg3, arg4, arg5);

New implementation

PxHndcallVA

Pass a variadic function as a handler

int _PxHndcallVA(int (*hnd)(va_list), ...);

Parameters:

  • hnd — function to execute with supervisor privileges

  • …​ — argument list of the variadic handler function

Return value:

  • Return value of the function executed in supervisor mode

Description:

The function hnd will be called with supervisor privileges with the pointer to the arguments passed on the stack as its argument.

Code 3. Example definition and usage of a variadic handler function
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* The handler function must use the C calling convention */
int handler_function(va_list ap);

#ifdef __cplusplus
}
#endif /* __cplusplus */

/* A sample handler function using 3 arguments */
int handler_function(va_list ap)
{
    int arg1 = va_arg(ap, int);
    int arg2 = va_arg(ap, int);
    int arg3 = va_arg(ap, int);

    ...

    return 0; /* indicate success */
}


/* A task function */
void task_function(PxTask_t myID, PxMbx_t myMailbox, PxEvents_t myActEvents)
{
    ...

    /* Call the handler function with 3 arguments */
    _PxHndcallVA(handler_function, arg1, arg2, arg3);

    ...
}

PxHndcallPTR

Pass a function with pointer argument as a handler

int _PxHndcallPTR(int (*hnd)(void *), void *arg);

Parameters:

  • hnd — function to execute with supervisor privileges

  • arg — argument of the handler function (pointer)

Return value:

  • Return value of the function executed in supervisor mode

Description:

The function hnd will be called in supervisor mode with arg as its argument.

Code 4. Example definition and usage of a handler function with one pointer argument
/* Structure to pass several values to the handler function */
typedef struct {
    int arg1;
    int arg2;
    int arg3;
} hndarg_t;

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* The handler function must use the C calling convention */
int handler_function(hndarg_t *p);

#ifdef __cplusplus
}
#endif /* __cplusplus */

/* A sample handler function expecting pointer to a structure */
int handler_function(hndarg_t *p)
{
    int arg1 = p->arg1; /* Readning input value from calling task */
    p->arg2 = OUTPUT_VALUE; /* Passing output value to calling task */
    return 0; /* indicate success */
}


/* A task function */
void task_function(PxTask_t myID, PxMbx_t myMailbox, PxEvents_t myActEvents)
{
    ...

    /* Initialize the argument structure */
    hndarg_t arg;
    arg.arg1 = INPUT_VALUE;

    /* Call the handler function with a pointer to the argument structure */
    _PxHndcallPTR(handler_function, &arg);

    ...
}