How to fill in the struct sigevent structure
Let's take a quick look at how you fill in the struct sigevent structure.
Regardless of the notification scheme you choose, you'll need to fill in a struct sigevent structure. For details, see the C Library Reference; here's a simplified version:
struct sigevent {
int sigev_notify;
union {
int __sigev_signo;
int __sigev_coid;
int __sigev_id;
void (*__sigev_notify_function)(union sigval);
volatile unsigned *__sigev_addr;
} __sigev_un1;
union sigval sigev_value;
union {
struct {
short __sigev_code;
short __sigev_priority;
} __st;
pthread_attr_t *__sigev_notify_attributes;
int __sigev_memop;
} __sigev_un2;
};
The first field you have to fill in is the sigev_notify member. This determines the notification type you've selected:
- SIGEV_PULSE
- A pulse will be sent.
- SIGEV_SIGNAL, SIGEV_SIGNAL_CODE, or SIGEV_SIGNAL_THREAD
- A signal will be sent.
- SIGEV_UNBLOCK
- Not used in this case; used with kernel timeouts (see
Kernel timeouts
below). - SIGEV_INTR
- Not used in this case; used with interrupts (see the Interrupts chapter).
- SIGEV_THREAD
- Creates a thread.
Since we're going to be using the struct sigevent with timers, we're concerned only with the SIGEV_PULSE, SIGEV_SIGNAL* and SIGEV_THREAD values for sigev_notify; we'll see the other types as mentioned in the list above.
Pulse notification
To send a pulse when the timer fires, set the sigev_notify field to SIGEV_PULSE and provide some extra information:
| Field | Value and meaning |
|---|---|
| sigev_coid | A pulse gets sent to the channel associated with this connection ID. |
| sigev_value | A 32-bit value that gets sent to the connection identified in the sigev_coid field. |
| sigev_code | An 8-bit value that gets sent to the connection identified in the sigev_coid field. |
| sigev_priority | The pulse's delivery priority. The value zero is not allowed (too many people were getting bitten by running at priority zero when they got a pulse—priority zero is what the idle task runs at, so effectively they were competing with QNX Neutrino's IDLE process and not getting much CPU time :-)). |
Note that the sigev_coid could be a connection to any channel (usually, though not necessarily, the channel associated with the process that's initiating the event).
Signal notification
To send a signal, set the sigev_notify field to one of:
- SIGEV_SIGNAL
- Send a regular signal to the process.
- SIGEV_SIGNAL_CODE
- Send a signal containing an 8-bit code to the process.
- SIGEV_SIGNAL_THREAD
- Send a signal containing an 8-bit code to a specific thread.
For SIGEV_SIGNAL*, the additional fields you'll have to fill are:
| Field | Value and meaning |
|---|---|
| sigev_signo | Signal number to send (from <signal.h>, e.g., SIGALRM). |
| sigev_code | An 8-bit code (if using SIGEV_SIGNAL_CODE or SIGEV_SIGNAL_THREAD). |
Thread notification
To create a thread whenever the timer fires, set the sigev_notify field to SIGEV_THREAD and fill these fields:
| Field | Value and meaning |
|---|---|
| sigev_notify_function | Address of void * function that accepts a void * to be called when the event triggers. |
| sigev_value | Value passed as the parameter to the sigev_notify_function() function. |
| sigev_notify_attributes | Thread attributes structure (see the
Processes and Threads chapter, under
The thread attributes structurefor details). |
(QNX Neutrino 7.0.4 or later) In order to use an event of type SIGEV_THREAD, your process must have the PROCMGR_AID_SIGEV_THREAD ability enabled. For more information, see procmgr_ability().
General tricks for notification
There are some convenience macros in <sys/siginfo.h> to make filling in the notification structures easier (see the entry for sigevent in the QNX Neutrino C Library Reference):
- SIGEV_SIGNAL_INIT (eventp, signo)
- Fill eventp with SIGEV_SIGNAL, and the appropriate signal number signo.
- SIGEV_SIGNAL_CODE_INIT (eventp, signo, value, code)
- Fill eventp with SIGEV_SIGNAL_CODE, the signal number signo, and the value and code.
- SIGEV_SIGNAL_THREAD_INIT (eventp, signo, value, code)
- Fill eventp with SIGEV_SIGNAL_THREAD, the signal number signo, as well as the value and code.
- SIGEV_PULSE_INIT (eventp, coid, priority, code, value)
- Fill eventp with SIGEV_PULSE, the connection to the channel in coid and a priority, code, and value. Note that there is a special value for priority of SIGEV_PULSE_PRIO_INHERIT that causes the receiving thread to run at the process's initial priority.
- SIGEV_UNBLOCK_INIT (eventp)
- Fill eventp with SIGEV_UNBLOCK.
- SIGEV_INTR_INIT (eventp)
- Fill eventp with SIGEV_INTR.
- SIGEV_THREAD_INIT (eventp, func, val, attributes)
- Fill eventp with the thread function (func) and the attributes structure (attributes). The value in val is passed to the function in func when the thread is executed.
