sigevent

Structure that describes an event

Synopsis:

#include <sys/siginfo.h>

union sigval {
    int         sival_int;
    void       *sival_ptr;
};

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;

# 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

    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_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:

This 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
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:

Note: The library uses some of the extra bits in sigev_notify for other purposes (see "Hidden 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) 

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. No other fields in the structure are used.

The initialization macro is:

SIGEV_INTR_INIT( &event )

SIGEV_MEMORY (QNX Neutrino extension)

(QNX Neutrino 6.6 or later) 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 )

One use for this type of event is to indicate when a local cache has been invalidated. For example, confstr(CS_TIMEZONE, ...) is called a lot, but the time zone hardly ever changes. You can call it once, cache the result, and then use procmgr_event_notify_add() like this:

procmgr_event_notify_add( PROCMGR_EVENT_CONFSTR, my_sigevent);

to 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, you need to call confstr(CS_TIMEZONE, ...) again.

Note: If a client program replaces its process image (e.g., by calling exec*()) with a setuid or setgid binary, the kernel sets the _NTO_COF_INSECURE flag on the channel. Until the process that owns the channel uses ConnectFlags() to clear this flag, calls to MsgDeliverEvent() with an event type of SIGEV_MEMORY or SIGEV_THREAD fail with an error of EACCES.

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 (in QNX Neutrino 6.6 or later) that process must have the PROCMGR_AID_PRIORITY ability enabled (see procmgr_ability()). In QNX Neutrino 6.6 or later, 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
A 32-bit value to be interpreted by the pulse handler.

The initialization macro is:

SIGEV_PULSE_INIT( &event, coid, priority, code, value )

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 this macro:

SIGEV_SIGNAL_VALUE_INIT( &event, signal, value )

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.
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_CODE_INIT( &event, signal, value, code )

SIGEV_SIGNAL_THREAD (QNX Neutrino extension)

Send a signal to a specific thread, depending on the situation:

In the case of timers, SyncMutexEvent(), and interrupts, if the thread dies before the event gets delivered, the kernel sends the signal to a random thread in the same process.

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.

Note: We don't recommend using this type of event. Pulses are more efficient.

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 structure initialized by pthread_attr_init() at the time of delivery.
void *sigev_value.sival_ptr
A value that's to be passed to the notification function.

The initialization macro is:

SIGEV_THREAD_INIT( &event, fn, value, attr )

The sigval union is defined as follows:

union sigval {
    int        sival_int;
    void     * sival_ptr;
};
Note: (QNX Neutrino 6.6 or later) If a client program replaces its process image (e.g., by calling exec*()) with a setuid or setgid binary, the kernel sets the _NTO_COF_INSECURE flag on the channel. Until the process that owns the channel uses ConnectFlags() to clear this flag, calls to MsgDeliverEvent() with an event type of SIGEV_MEMORY or SIGEV_THREAD fail with an error of EACCES.

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 )

Hidden 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_CRITICAL
(QNX Neutrino Core OS 6.3.2 or later) If you're using adaptive partitioning, you can use a sigevent to make a thread run as critical or not:
  • SIGEV_MAKE_CRITICAL( &event )
  • SIGEV_CLEAR_CRITICAL( &event )

The receiving thread doesn't have to do anything to make itself critical or noncritical; the adaptive partitioning scheduler does this automatically. For more information, see the Adaptive Partitioning User's Guide.

SIGEV_FLAG_UPDATEABLE
(QNX Neutrino 6.6 or later) 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 } 

Classification:

POSIX 1003.1, with QNX Neutrino extensions