sigevent
Structure that describes an event
Synopsis:
#include <sys/siginfo.h>
union __sigval32 {
int sival_int;
_Uintptr32t sival_ptr;
};
union __sigval64 {
int sival_int;
_Uintptr64t sival_ptr;
};
union sigval {
int sival_int;
void *sival_ptr;
};
struct __sigevent32 {
int sigev_notify;
union {
int __sigev_signo;
int __sigev_coid;
int __sigev_id;
_Uintptr32t __sigev_notify_function;
_Uintptr32t __sigev_addr;
unsigned __sigev_handle;
} __sigev_un1;
union __sigval32 sigev_value;
union {
struct {
short __sigev_code;
short __sigev_priority;
} __st;
_Uintptr32t __sigev_notify_attributes;
int __sigev_memop;
} __sigev_un2;
};
struct __sigevent64 {
int sigev_notify;
union {
int __sigev_signo;
int __sigev_coid;
int __sigev_id;
_Uintptr64t __sigev_notify_function;
_Uintptr64t __sigev_addr;
unsigned __sigev_handle;
} __sigev_un1;
union __sigval64 sigev_value;
union {
struct {
short __sigev_code;
short __sigev_priority;
} __st;
_Uintptr64t __sigev_notify_attributes;
int __sigev_memop;
} __sigev_un2;
};
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;
unsigned __sigev_handle;
} __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;
};
# define sigev_signo __sigev_un1.__sigev_signo
# define sigev_coid __sigev_un1.__sigev_coid
# define sigev_id __sigev_un1.__sigev_id
# define sigev_notify_function __sigev_un1.__sigev_notify_function
# define sigev_addr __sigev_un1.__sigev_addr
# define sigev_handle __sigev_un1.__sigev_handle
# define sigev_notify_attributes __sigev_un2.__sigev_notify_attributes
# define sigev_code __sigev_un2.__st.__sigev_code
# define sigev_priority __sigev_un2.__st.__sigev_priority
# define sigev_memop __sigev_un2.__sigev_memop
Description:
The sigevent structure describes an event. POSIX specifies the basic structure and allows a lot of leeway in extending it. It effectively includes these members (although they aren't all usable at the same time):
| Member | Classification |
|---|---|
| int sigev_notify | POSIX |
| int sigev_signo | POSIX |
| int sigev_coid | QNX Neutrino |
| int sigev_id (not currently used) | QNX Neutrino |
| void sigev_notify_function | POSIX |
| volatile unsigned *sigev_addr | QNX Neutrino |
| unsigned sigev_handle | QNX Neutrino |
| union sigval sigev_value | POSIX |
| short sigev_code | QNX Neutrino |
| short sigev_priority | QNX Neutrino |
| pthread_attr_t *sigev_notify_attributes | POSIX |
| int sigev_memop | QNX Neutrino |
The value of sigev_notify indicates how the notification is to occur and which of the other members are used:
- SIGEV_INTR
- SIGEV_MEMORY
- SIGEV_NONE
- SIGEV_PULSE
- SIGEV_SEM
- SIGEV_SIGNAL
- SIGEV_SIGNAL_CODE
- SIGEV_SIGNAL_THREAD
- SIGEV_THREAD
- SIGEV_UNBLOCK
Extra bits,below). After initializing an event, don't set sigev_notify directly; instead, use the SIGEV_SET_TYPE() macro. For example:
SIGEV_SET_TYPE( &my_event, SIGEV_PULSE )
If you want to test the value of this member, use the SIGEV_GET_TYPE() macro.
For example, instead of:
if( my_event.sigev_notify == SIGEV_PULSE )
use:
if( SIGEV_GET_TYPE(&my_event) == SIGEV_PULSE )
(QNX Neutrino 7.0.1 or later) The kernel uses the sigev_handle field for
registered events, which are more secure than regular sigevents.
For more information, see the entry for
MsgRegisterEvent(),
as well as
Events
in the Interprocess Communication (IPC)
chapter of the System Architecture guide.
By default in QNX Neutrino 7.1 or later, you can use only registered events, but
you can use the -U option to
procnto
to allow unregistered events to be used temporarily while you're converting your programs to use registered events.
The <sys/siginfo.h> file also defines some macros to make initializing the sigevent structure easier. All the macros take a pointer to a sigevent structure as their event argument and set the sigev_notify member to the appropriate value. These macros are QNX Neutrino extensions and are described below.
SIGEV_INTR (QNX Neutrino extension)
Send an interrupt notification to a specific thread, depending on the situation:
- If used with MsgSend*(), MsgReceive*(), and MsgDeliverEvent(), the thread is the one identified by the rcvid that MsgReceive*() returns.
- For timers, it's the thread that called timer_settime().
- For InterruptAttach(), InterruptAttachArray(), and InterruptAttachEvent(), it's the thread attaching to the interrupt.
- For SyncMutexEvent(), it's the thread that called the function.
No other fields in the structure are used.
The initialization macro is:
SIGEV_INTR_INIT( &event )
SIGEV_MEMORY (QNX Neutrino extension)
Directly manipulate a location in memory. The following fields are used:
- volatile unsigned *sigev_addr
- The address of the data that you want to manipulate.
- int sigev_value.sival_int
- The value to use in the operation.
- int sigev_memop
- The operation to perform; one of the following:
- SIGEV_MEM_ASSIGN — set the location in memory to the given value.
- SIGEV_MEM_ADD — use atomic_add() to add the value to the location in memory.
- SIGEV_MEM_SUB — use atomic_sub() to subtract the value from the location in memory.
- SIGEV_MEM_BITSET — use atomic_set() to set the bits in the location in memory.
- SIGEV_MEM_BITCLR — use atomic_clr() to clear the bits in the location in memory.
- SIGEV_MEM_BITTOGGLE — use atomic_toggle() to toggle the bits in the location in memory.
For the SIGEV_MEM_BIT* operations, the bits that are set in the value indicate which bits to set, clear, or toggle in the location in memory.
The initialization macro is:
SIGEV_MEMORY_INIT( &event, addr, value, operation )
confstr(CS_TIMEZONE, ...) is called a lot, but the time zone hardly ever changes.
A client can register an event to be delivered when the time zone configuration value changes, like this:
procmgr_event_notify_add( PROCMGR_EVENT_CONFSTR, my_sigevent );
and then call confstr(CS_TIMEZONE, ...) once and cache the result.
The process manager will notify the client by setting a memory location when the time zone string might have changed.
If somebody wants to get the time zone, and the memory location hasn't been set, the local cached value
is still current.
If the memory location is set, they need to call confstr(CS_TIMEZONE, ...) again.
SIGEV_NONE (POSIX)
Don't send any notification. No other fields in the structure are used.
The initialization macro is:
SIGEV_NONE_INIT( &event )
SIGEV_PULSE (QNX Neutrino extension)
Send a pulse. The following fields are used:
- int sigev_coid
- The connection ID. This should be attached to the channel with which the pulse will be received.
- short sigev_priority
- The priority of the pulse, or SIGEV_PULSE_PRIO_INHERIT
if you want the thread that receives the pulse to run at the initial priority of the process.
The priority of the pulse must be in the range for the target process, or that process must have the PROCMGR_AID_PRIORITY ability enabled (see procmgr_ability()). If procnto was started with an
s
appended to the -P option, then out-of-range priority requests use the maximum allowed value instead of resulting in an error. - short sigev_code
- A code to be interpreted by the pulse handler. Although sigev_code can be any 8-bit signed value, you should avoid sigev_code values less than zero in order to avoid conflict with kernel or pulse codes generated by a QNX Neutrino manager. These codes all start with _PULSE_CODE_ and are defined in <sys/neutrino.h>; for more information, see the documentation for the _pulse structure. A safe range of pulse values is _PULSE_CODE_MINAVAIL to _PULSE_CODE_MAXAVAIL.
- int sigev_value.sival_int or void *sigev_value.sival_ptr
- A 32-bit value or a pointer to be interpreted by the pulse handler.
The initialization macros are:
- SIGEV_PULSE_INIT( &event, coid, priority, code, value )
Store the value in sigev_value.sival_ptr.
- SIGEV_PULSE_INT_INIT( &event, coid, priority, code, value )
(QNX Neutrino 7.0 or later) Store the value in sigev_value.sival_int and set the SIGEV_FLAG_SIVAL_INT bit in the sigev_notify field.
- SIGEV_PULSE_PTR_INIT( &event, coid, priority, code, value )
(QNX Neutrino 7.0 or later) Store the value in sigev_value.sival_ptr.
SIGEV_SEM (QNX Neutrino extension)
(QNX Neutrino 7.1 or later) Increment a named semaphore; this is equivalent to calling sem_post(). The following field is used:
- int sigev_coid
- The connection ID.
The initialization macro is:
SIGEV_SEM_INIT( &event, &sem )
SIGEV_SIGNAL (POSIX)
Send a signal to a process. The following fields are used:
- int sigev_signo
- The signal to raise. This must be in the range from 1 through NSIG − 1.
The initialization macro is:
SIGEV_SIGNAL_INIT( &event, signal )
If you need to set the sigev_value for a SIGEV_SIGNAL event (for example if SA_SIGINFO is set), you can use one of these macros instead of SIGEV_SIGNAL_INIT():
- SIGEV_SIGNAL_VALUE_INIT( &event, signal, value )
Store the value in sigev_value.sival_ptr.
- SIGEV_SIGNAL_VALUE_INT_INIT( &event, signal, value )
(QNX Neutrino 7.0 or later) Store the value in sigev_value.sival_int and set the SIGEV_FLAG_SIVAL_INT bit in the sigev_notify field.
- SIGEV_SIGNAL_VALUE_PTR_INIT( &event, signal, value )
(QNX Neutrino 7.0 or later) Store the value in sigev_value.sival_ptr.
SIGEV_SIGNAL_CODE (QNX Neutrino extension)
This is similar to SIGEV_SIGNAL, except that SIGEV_SIGNAL_CODE also includes a value and a code. The following fields are used:
- int sigev_signo
- The signal to raise. This must be in the range from 1 through NSIG − 1.
- int sigev_value.sival_int or void *sigev_value.sival_ptr
- A 32-bit value or a pointer to be interpreted by the signal handler.
- short sigev_code
- A code to be interpreted by the signal handler. This must be in the range from SI_MINAVAIL through SI_MAXAVAIL.
The initialization macros are:
- SIGEV_SIGNAL_CODE_INIT( &event, signal, value, code )
Store the following values in the sigevent pointed to by event:
- signal in sigev_signo
- value in sigev_value.sival_ptr
- code in sigev_code
- SIGEV_SIGNAL_CODE_INT_INIT( &event, signal, value, code )
Store signal and code in the sigevent pointed to by event as described for the previous macro function, but store value in sigev_value.sival_int and set the SIGEV_FLAG_SIVAL_INT bit.
- SIGEV_SIGNAL_CODE_PTR_INIT( &event, signal, value, code )
Store signal, value, and code in the sigevent pointed to by event. This function has the same semantics as SIGEV_SIGNAL_CODE_INIT(). By providing both macro functions, QNX Neutrino lets programmers choose the one with the name that more accurately describes what they're doing in the calling context. Note that value is stored as a void* pointer.
SIGEV_SIGNAL_THREAD (QNX Neutrino extension)
Send a signal to a specific thread, depending on the situation:
- If used with MsgDeliverEvent(), the thread is the one identified by the rcvid that MsgReceive*() returned when you received a message (not a pulse).
- For timers, it's the thread that called timer_settime().
- For InterruptAttach(), InterruptAttachArray(), and InterruptAttachEvent(), it's the thread attaching to the interrupt.
- For SyncMutexEvent(), it's the thread that called the function.
In the case of timers, SyncMutexEvent(), and interrupts, if the thread dies before the event gets delivered, the kernel drops the event.
The following fields are used:
- int sigev_signo
- The signal to raise. This must be in the range from 1 through NSIG − 1.
- short sigev_code
- A code to be interpreted by the signal handler. This must be in the range from SI_MINAVAIL through SI_MAXAVAIL.
- int sigev_value.sival_int
- A 32-bit value to be interpreted by the signal handler.
The initialization macro is:
SIGEV_SIGNAL_THREAD_INIT( &event, signal, value, code )
SIGEV_THREAD (POSIX)
Create a new thread.
We don't recommend using this type of event. Pulses are more efficient.
(QNX Neutrino 7.0.4 or later) In order to register or use an event of type SIGEV_THREAD, your process must have the PROCMGR_AID_SIGEV_THREAD ability enabled. For more information, see procmgr_ability().
If the thread can't be created due to a lack of resources, SIGEV_THREAD is silently dropped.
The following fields are used:
- void (*sigev_notify_function) (union sigval)
- A pointer to the function to be notified.
- pthread_attr *sigev_notify_attributes
- A pointer to thread attributes. This must be NULL, or
point to a valid thread attribute structure; that is, a structure initialized by
pthread_attr_init()
and updated with the appropriate pthread_attr_set*() functions.
Note:This pointer is stored and then used at the time of event delivery, so the attribute structure must be valid at that time.
- void *sigev_value.sival_ptr
- A value to be passed to the notification function.
The initialization macro is:
SIGEV_THREAD_INIT( &event, fn, value, attr )
union sigval {
int sival_int;
void * sival_ptr;
};
SIGEV_UNBLOCK (QNX Neutrino extension)
Force a thread to become unblocked. No other fields in the structure are used.
The initialization macro is:
SIGEV_UNBLOCK_INIT( &event )
Extra bits (QNX Neutrino extension)
After you've set up the sigevent structure as appropriate, you can use some extra bits in sigev_notify for other purposes. The bits and their associated macros include:
- SIGEV_FLAG_HANDLE
- (QNX Neutrino 7.0.1 or later) The sigevent is a handle that represents a secure event that was registered with MsgRegisterEvent().
- SIGEV_FLAG_SIVAL_INT
- (QNX Neutrino 7.0 or later) The sigevent was initialized specifically to hold an integer with one of the SIGEV_*_INT_INIT() macros.
- SIGEV_FLAG_CODE_UPDATEABLE
- (QNX Neutrino 7.0.4 or later)
Allow the server to update the sigev_code member before the event is delivered.
The actual update depends on the server.
To determine if the bit is set, the server should just test it directly:
if (event.sigev_notify & SIGEV_FLAG_CODE_UPDATEABLE) { // may update event before delivering } else { // should not update event before delivering } - SIGEV_FLAG_UPDATEABLE
-
Allow the server to update the sigev_value member before the event is delivered:
- SIGEV_MAKE_UPDATEABLE( &event )
- SIGEV_CLEAR_UPDATEABLE( &event )
The actual update depends on the server. For information about the updated information for kernel events, see procmgr_event_notify_add().
To determine if the bit is set, the server should just test it directly:if (event.sigev_notify & SIGEV_FLAG_UPDATEABLE) { // may update event before delivering } else { // should not update event before delivering }
32- and 64-bit architectures
You'll typically use struct sigevent, unless your program needs to work with sigevents from 32- and 64-bit programs, in which case you'll also have to work with struct __sigevent32 and struct __sigevent64.
Since a sigevent might be passed between 32- and 64-bit programs, we've defined a SIGEV_64BIT flag that indicates which type of sigevent it is. We OR this flag into the sigev_notify types. For example, in addition to SIGEV_SIGNAL, we have SIGEV_SIGNAL32 and SIGEV_SIGNAL64:
- SIGEV_SIGNAL32 is the same value as SIGEV_SIGNAL was in earlier versions of the OS.
- SIGEV_SIGNAL64 is equal to SIGEV_SIGNAL32 with SIGEV_64BIT ORed in.
- In a 32-bit process, SIGEV_SIGNAL is equal to SIGEV_SIGNAL32; in a 64-bit process, it's equal to SIGEV_SIGNAL64.
Some programs use SIGEV_NONE to identify an empty sigevent. For compatibility, SIGEV_NONE is always the same as SIGEV_NONE32, no matter which architecture you compile for.
If your program stores sigevents from 32- and 64-bit programs, you should replace struct sigevent with a union:
union {
struct sigevent ev;
struct __sigevent32 ev32;
struct __sigevent64 ev64;
};
Your code can then check ev.sigev_notify, determine whether the sigevent is from a 32- or 64-bit program, and then use the ev32 or ev64 structure, as appropriate.
