Event handler

The dynamic filter is an event handler that works like an interrupt handler. When this filter is used, a section of your custom code is executed. The code can test for a set of conditions before determining whether the event should be stored.

CAUTION:
The only library functions that you can call in your event handler are those that are safe to call from an interrupt handler. For a list of these functions, see the Full Safety Information appendix in the QNX Neutrino C Library Reference. If you call an unsafe function—such as printf()—in your event handler, you'll crash your entire system. Your event handler must also be reentrant.

If you want to log the current event, return a non-zero value; to discard the event, return 0. Here's a very simple event handler that says to log all of the given events:

int event_handler(event_data_t* dummy_pt)
{
 return(1);
}
Note: If you use both types of dynamic filters (event handler and class event handler), and they both apply to a particular event, the event is logged if both event handlers return a non-zero value.

In addition to deciding whether or not the event should be logged, you can use the dynamic rules filter to output events to external hardware or to perform other tasks—it's up to you because it's your code. Naturally, you should write the code as efficiently as possible in order to minimize the overhead.

You can access the information about the intercepted event within the event handler by examining the event_data_t structure passed as an argument to the event handler. The layout of the event_data_t structure (declared in <sys/trace.h>) is as follows:

/* event data filled by an event handler */
typedef struct 
{
   __traceentry header;      /* same as traceevent header    */
   uint32_t*    data_array;  /* initialized by the user      */
   uint32_t     el_num;      /* number of elements returned  */
   void*        area;        /* user data                    */
   uint32_t     feature_mask;/* bits indicate valid features */
   uint32_t     feature[_NTO_TRACE_FI_NUM]; /* feature array 
                                           - additional data */
} event_data_t;
CAUTION:
The event_data_t structure includes a pointer to an array for the data arguments of the event. You must provide an array, and it must be large enough to hold the data for the event or events that you're handling (see the Current Trace Events and Data appendix). For example:
event_data_t e_d_1;
uint32_t     data_array_1[20]; /* 20 elements for potential args. */

e_d_1.data_array = data_array_1;

If you don't provide the data array, or it isn't big enough, your data segment could become corrupted.

You can use the following macros, defined in <sys/trace.h>, to work with the header of an event:

_NTO_TRACE_GETEVENT_C(c)
Get the class.
_NTO_TRACE_GETEVENT(c)
Get the type of event.
_NTO_TRACE_GETCPU(h)
Get the number of the CPU that the event occurred on.
_NTO_TRACE_SETEVENT_C(c,cl)
Set the class in the header c to be cl.
_NTO_TRACE_SETEVENT(c, e)
Set the event type in the header c to be e.

The bits of the feature_mask member are related to any additional features (arguments) that you can access inside the event handler. All standard data arguments—the ones that correspond to the data arguments of the trace event—are delivered without changes within the data_array.

There are two constants associated with each additional feature:

The currently defined features are:

Feature Parameter mask Index
Process ID _NTO_TRACE_FMPID _NTO_TRACE_FIPID
Thread ID _NTO_TRACE_FMTID _NTO_TRACE_FITID

If any particular bit of the feature_mask is set to 1, then you can access the feature corresponding to this bit within the feature array. Otherwise, you must not access the feature. For example, if the expression:

feature_mask & _NTO_TRACE_FMPID

is TRUE, then you can access the additional feature corresponding to identifier _NTO_TRACE_FMPID as:

my_pid = feature[_NTO_TRACE_FIPID];