TraceEvent()

Control the tracing of kernel events

Synopsis:

#include <sys/neutrino.h>
#include <sys/trace.h>

int TraceEvent( int cmd, 
                ... );

Arguments:

cmd
The control action that you want to make; one of the following:

Some commands require additional arguments, as described below. In general, the arguments are grouped logically as follows:

TraceEvent(cmd [,class [,event]] [,p1 [,p2 [,p3 ... [,pn]]]])

Aside from the cmd, these arguments are:

class
The category of events. All the events are logically grouped into the following classes:
  • _NTO_TRACE_COMM — events related to communication.
  • _NTO_TRACE_CONTROL — the set of control events (e.g. time-overflow event) that are used by the communication protocol between the microkernel and tracelogger .
  • _NTO_TRACE_INTENTER, _NTO_TRACE_INTEXIT — the set of interrupt entry/exit events.
  • _NTO_TRACE_INT_HANDLER_ENTER, _NTO_TRACE_INT_HANDLER_EXIT — entrances to and exits from interrupt handlers.
  • _NTO_TRACE_KERCALLENTER, _NTO_TRACE_KERCALLEXIT — the set of events for entries to and exits from kernel calls.
  • _NTO_TRACE_PROCESS — the set of events associated with process creation and destruction.
  • _NTO_TRACE_SYSTEM — events related to the system.
  • _NTO_TRACE_THREAD, _NTO_TRACE_VTHREAD — the set of events for the creation and destruction of threads (or virtual threads), and for state changes.

There are also "pseudo classes" defined as a convenience:

  • _NTO_TRACE_KERCALL — all of the kernel-call events: _NTO_TRACE_KERCALLENTER and _NTO_TRACE_KERCALLEXIT.
  • _NTO_TRACE_INT — all of the interrupt events: _NTO_TRACE_INTENTER, _NTO_TRACE_INTEXIT, _NTO_TRACE_INT_HANDLER_ENTER, and _NTO_TRACE_INT_HANDLER_EXIT.
event
The event. Because the events are grouped by class, the event must be a member of the class in order to be valid.
p1...pn
Any additional parameters that are required to perform the desired control action.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The TraceEvent() function lets you control all stages of the instrumentation process, including initializing, starting, stopping, controlling filters, and inserting events. These stages are broadly grouped into the following categories:

  • Filter and mode settings are made regardless of the previous settings. Use care to not accidentally override or delete previous configurations.
  • In order to add handlers for trace events or allocate the instrumented kernel's trace buffers, your process must have the PROCMGR_AID_TRACE ability enabled. For more information, see procmgr_ability() .

Buffer and execution control

These commands control the buffer setup, and start and stop logging:

_NTO_TRACE_ALLOCBUFFER, _NTO_TRACE_DEALLOCBUFFER

TraceEvent(_NTO_TRACE_ALLOCBUFFER, uint bufnum, void** linkliststart)
TraceEvent(_NTO_TRACE_DEALLOCBUFFER)

The allocation option creates and initializes the instrumented kernel's internal circular linked list of trace buffers. These buffers hold the emitted trace events. The extra arguments for the _NTO_TRACE_ALLOCBUFFER command are:

bufnum
Number of buffers to allocate.
*linkliststart
Physical address of the beginning of the circular linked list of allocated trace buffers.

Allocated trace buffers can store 1024 simple trace events.

If your application calls TraceEvent() with these commands, it must must have the PROCMGR_AID_TRACE ability enabled. For more information, see procmgr_ability() .

The deallocation option deallocates all of the previously allocated trace buffers. All events stored in the trace buffers are lost.

_NTO_TRACE_FLUSHBUFFER

TraceEvent(_NTO_TRACE_FLUSHBUFFER)

Forces flushing of the buffer regardless of the trace event number it contains.

_NTO_TRACE_QUERYEVENTS

TraceEvent(_NTO_TRACE_QUERYEVENTS)

Returns the number of simple trace events that are currently stored in the trace buffer.

_NTO_TRACE_START, _NTO_TRACE_STARTNOSTATE, _NTO_TRACE_STOP

TraceEvent(_NTO_TRACE_START)
TraceEvent(_NTO_TRACE_STARTNOSTATE)
TraceEvent(_NTO_TRACE_STOP)

These commands start and stop the instrumentation process. The event stream containing the trace events is opened or closed as appropriate.

The _NTO_TRACE_START and _NTO_TRACE_STARTNOSTATE options are similar, except that the latter suppresses the initial system state information (thread IDs and names of processes).

_NTO_TRACE_SETBUFFER

TraceEvent(_NTO_TRACE_SETBUFFER, paddr64_t addr, size_t size)

Use the previously allocated physical memory, at the given address and for the given size, as the trace buffer. The intended application is to place the buffer in an area of memory that will be preserved across system resets, facilitating post-crash analysis.

_NTO_TRACE_SETRINGMODE

TraceEvent(_NTO_TRACE_SETRINGMODE)

Use the internal circular linked list in ring mode. In ring mode, the kernel stores all events in a circular fashion inside the linked list without flushing them. The maximum capturing time (without history overwriting) is determined by the number of allocated buffers, as well as by the number of generated trace events.

_NTO_TRACE_SETLINEARMODE

TraceEvent(_NTO_TRACE_SETLINEARMODE)

Use the internal circular linked list in linear mode (the default). When you use this mode, every filled-up buffer is captured and flushed immediately.

Fast/wide mode configuration

These commands control whether fast or wide events are emitted:

_NTO_TRACE_SETALLCLASSESFAST, _NTO_TRACE_SETALLCLASSESWIDE

TraceEvent(_NTO_TRACE_SETALLCLASSESFAST)
TraceEvent(_NTO_TRACE_SETALLCLASSESWIDE)

Sets the fast/wide emitting mode for all classes and events.

_NTO_TRACE_SETCLASSFAST, _NTO_TRACE_SETCLASSWIDE

TraceEvent(_NTO_TRACE_SETCLASSFAST, int class)
TraceEvent(_NTO_TRACE_SETCLASSWIDE, int class)

Sets the fast/wide emitting mode for all events within the specified class.

_NTO_TRACE_SETEVENTFAST, _NTO_TRACE_SETEVENTWIDE

TraceEvent(_NTO_TRACE_SETEVENTFAST, int class, int event)
TraceEvent(_NTO_TRACE_SETEVENTWIDE, int class, int event)

Sets the fast/wide emitting mode for the specified event for the specified class.

Static rules filter configuration

These commands control the operation of the static rules filter:

_NTO_TRACE_ADDALLCLASSES, _NTO_TRACE_DELALLCLASSES

TraceEvent(_NTO_TRACE_ADDALLCLASSES)
TraceEvent(_NTO_TRACE_DELALLCLASSES)

Emit/suppress trace events for all classes and events.

_NTO_TRACE_ADDCLASS, _NTO_TRACE_DELCLASS

TraceEvent(_NTO_TRACE_ADDCLASS, class)
TraceEvent(_NTO_TRACE_DELCLASS, class)

Emit/suppress all trace events from a specific class.

_NTO_TRACE_ADDEVENT, _NTO_TRACE_DELEVENT

TraceEvent(_NTO_TRACE_ADDEVENT, class, event)
TraceEvent(_NTO_TRACE_DELEVENT, class, event)

Emit/suppress a trace event from a specific class.

_NTO_TRACE_SETCLASSPID, _NTO_TRACE_CLRCLASSPID, _NTO_TRACE_SETCLASSTID, _NTO_TRACE_CLRCLASSTID

TraceEvent(_NTO_TRACE_SETCLASSPID, int class, pid_t pid)
TraceEvent(_NTO_TRACE_CLRCLASSPID, int class)
TraceEvent(_NTO_TRACE_SETCLASSTID, int class, pid_t pid, tid_t tid)
TraceEvent(_NTO_TRACE_CLRCLASSTID, int class)

Emit/suppress all events from a specified process ID (and thread ID).

_NTO_TRACE_SETEVENTPID, _NTO_TRACE_CLREVENTPID, _NTO_TRACE_SETEVENTTID, _NTO_TRACE_CLREVENTTID

TraceEvent(_NTO_TRACE_SETEVENTPID, int class, int event, pid_t pid)
TraceEvent(_NTO_TRACE_CLREVENTPID, int class, int event)
TraceEvent(_NTO_TRACE_SETEVENTTID, int class, int event,
           pid_t pid, tid_t tid)
TraceEvent(_NTO_TRACE_CLREVENTTID, int class, int event)

Emit/suppress a specific event for a specified process ID (and thread ID).

Dynamic rules filter configuration

These commands control the operation of the dynamic rules filter, in which you set up handlers for the events you're interested in:

Accessing data in the event handler

You can access the trace event information from within the event handler by using members of the event_data_t structure.

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;

The bits of the member feature_mask are related to any additional features (arguments) that could be accessed 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:

  • _NTO_TRACE_FM*** — feature parameter masks
  • _NTO_TRACE_FI*** — feature index parameters

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.

Macros for use with the event header

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.

_NTO_TRACE_ADDEVENTHANDLER, _NTO_TRACE_DELEVENTHANDLER

TraceEvent(_NTO_TRACE_ADDEVENTHANDLER, 
           class, 
           event, 
           int (*event_hdlr)(event_data_t*), 
           event_data_t* data_struct)
TraceEvent(_NTO_TRACE_DELEVENTHANDLER, 
           class, 
           event)

Attaches/deletes the event handler for a specified class and event, where:

event_hdlr
Pointer to the event handler.
data_struct
Pointer to the data structure event_data_t.

Before attaching an event handler, the thread must:

  • have the PROCMGR_AID_TRACE and PROCMGR_AID_IO abilities enabled. For more information, see procmgr_ability() .
  • request I/O privileges by calling:
    ThreadCtl( _NTO_TCTL_IO, 0 );
      

If the thread doesn't do all of the above, the attachment fails with an error code of EPERM.

In order to emit an event data, a dynamic filter (event handler) has to return a non-zero value. If both types of the dynamic filters (event handler and class event handler) are applicable to a particular event, the event is emitted if both event handlers return non-zero values.

_NTO_TRACE_ADDCLASSEVHANDLER, _NTO_TRACE_DELCLASSEVHANDLER

TraceEvent(_NTO_TRACE_ADDCLASSEVHANDLER,
           class,
           int (*event_hdlr)(event_data_t*),
           event_data_t* data_struct)
       
TraceEvent(_NTO_TRACE_DELCLASSEVHANDLER,
           class)

Attaches/deletes the event handler for a specified class, where:

event_hdlr
Pointer to the event handler.
data_struct
Pointer to the data structure event_data_t.

Before attaching an event handler, the thread must:

  • have the PROCMGR_AID_TRACE and PROCMGR_AID_IO abilities enabled. For more information, see procmgr_ability() .
  • request I/O privileges by calling:
    ThreadCtl( _NTO_TCTL_IO, 0 );
      

If the thread doesn't do all of the above, the attachment fails with an error code of EPERM.

In order to emit an event data, a dynamic filter (event handler) has to return a non-zero value. If both types of the dynamic filters (event handler and class event handler) are applicable to a particular event, the event is emitted if both event handlers return non-zero values.

User-generated trace events

These commands let you insert your own events into the event stream:

_NTO_TRACE_INSERTEVENT

TraceEvent(_NTO_TRACE_INSERTEVENT, int head, int stamp,
           int data0, int data1)

Inserts an event of an arbitrary type and class into the event stream. It's powerful, but because the API doesn't do any of the interpretation for you, you should use this function (with care!) only if you're an advanced user. You'll have to modify the data-interpretation program to properly interpret the event.

The arguments are:

head
Header of the trace event.
stamp
Time stamp.
data0
Data d0.
data1
Data d1.

Instead of using the _NTO_TRACE_INSERTEVENT command directly, you can use the following convenience functions:

trace_func_enter()
Insert a trace event for the entry to a function
trace_func_exit()
Insert a trace event for the exit from a function
trace_here()
Insert a trace event for the current address
trace_logbc()
Insert a trace event of an arbitrary class and type with arbitrary data

_NTO_TRACE_INSERTSUSEREVENT, _NTO_TRACE_INSERTCUSEREVENT, _NTO_TRACE_INSERTUSRSTREVENT

TraceEvent(_NTO_TRACE_INSERTSUSEREVENT, int event, int data0,
           int data1)

TraceEvent(_NTO_TRACE_INSERTCUSEREVENT, int event,  unsigned * buf,
           unsigned len)

TraceEvent(_NTO_TRACE_INSERTUSRSTREVENT, int event, const char * str)

These commands insert user-created events into the event stream. Because the API handles details such as timestamping, they're reasonably easy to use. The class is _NTO_TRACE_USER.

_NTO_TRACE_INSERTSUSEREVENT
Add a user simple event containing the data defined by data0 and data1.
_NTO_TRACE_INSERTCUSEREVENT
Add a user combine event containing the data that buf holds.

The len argument represents the number of integers (not bytes) in buf.

_NTO_TRACE_INSERTUSRSTREVENT
Add a user string event containing the null-terminated string defined by str.

The event argument must be in the range from _NTO_TRACE_USERFIRST through _NTO_TRACE_USERLAST, but you can decide what each event means.

Instead of using these commands directly, you can use the following convenience functions:

trace_logb()
Insert a user combine trace event
trace_logf()
Insert a user string trace event
trace_logi()
Insert a user simple trace event
trace_nlogf()
Insert a user string trace event, specifying a maximum string length
trace_vnlogf()
Insert a user string trace event, using a variable argument list

Returns:

If cmd is set to _NTO_TRACE_QUERYEVENTS
Number of events in the buffer, or -1 if an error occurs ( errno is set).
If cmd isn't set to _NTO_TRACE_QUERYEVENTS
0 for success, or -1 if an error occurs ( errno is set).

Errors:

ECANCELED
The requested action has been canceled.
EFAULT
Bad internal trace buffer address. The requested action has been specified out of order.
ENOMEM
Insufficient memory to allocate the trace buffers.
ENOTSUP
The requested action isn't supported.
EPERM
The calling process doesn't have the required permission; see procmgr_ability() .

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler Read the Caveats
Signal handler Yes
Thread Yes

Caveats:

You can call TraceEvent() from an interrupt/event handler. However, not all commands are valid in this case. The valid commands are:

  • _NTO_TRACE_INSERTSUSEREVENT
  • _NTO_TRACE_INSERTCUSEREVENT
  • _NTO_TRACE_INSERTUSRSTREVENT
  • _NTO_TRACE_INSERTEVENT
  • _NTO_TRACE_STOP
  • _NTO_TRACE_STARTNOSTATE
  • _NTO_TRACE_START

Last modified: 2013-12-23

comments powered by Disqus