Attach an event to a mutex
Synopsis:
#include <sys/neutrino.h>
int SyncMutexEvent( sync_t * sync,
struct sigevent * event );
int SyncMutexEvent_r( sync_t * sync,
struct sigevent * event );
Arguments:
- sync
- A pointer to the synchronization object for the mutex that you want to attach an event to.
- event
- A pointer to the
sigevent
structure that describes the event that you want to attach, or
NULL if you want to detach the currently registered event.
Library:
libc
Use the -l c option to
qcc
to link against this library.
This library is usually included automatically.
Description:
The SyncMutexEvent() and SyncMutexEvent_r()
kernel calls attach the specified event to a mutex pointed
to by sync.
This event is delivered when the mutex enters the DEAD state, which happens
when a process holding the mutex removes its last mapping of the mutex without unlocking it
(including when the process dies while holding the mutex in shared memory).
Note:
This situation is likely caused by a bug in the process.
Although the OS provides a way to detect it and revive the
mutex, the data that the mutex is protecting might be in an inconsistent state.
SyncMutexEvent() and SyncMutexEvent_r()
are similar, except for the way they indicate errors.
See the Returns section for details.
When you're notified that a mutex has been put into the DEAD state, you can revive it with
SyncMutexRevive().
If you call SyncMutexEvent() with a NULL event,
the function deletes any existing event registration.
Note:
-
In order to use this function with a SIGEV_PULSE sigevent that's going to a channel
that was created by a different process whose real, effective, or saved user ID doesn't match your process's
effective user ID, your process must have the PROCMGR_AID_CONNECTION ability enabled.
For more information, see
procmgr_ability().
- You can't use SyncMutexEvent() with a robust mutex (see
pthread_mutexattr_setrobust()).
The two mechanisms achieve the same goal in different ways.
- Robust mutexes, mutexes with priority ceilings, and those using
SyncMutexEvent() use more system resources than other mutexes.
Managing the death of a mutex
Robust mutexes automate the notification about the termination of the current mutex owner,
but the recovery code must be spread over multiple functions, as explained in the
pthread_mutexattr_setrobust() reference.
It may be easier to use a non-robust mutex with a sigevent because it provides centralized recovery handling.
Here's how you can use a non-robust mutex in shared memory between threads in two or
more processes and deal with the death
of one of the processes while it's holding the mutex.
- Have a thread in one process create and initialize the mutex, and possibly attach an event
using SyncMutexEvent().
- This thread marks the shared memory area and the mutex as usable.
- Everyone goes ahead and uses the mutex and shared memory area;
everything goes well until a process dies.
- If the process that dies has a thread that holds the mutex
(i.e., it's the current owner), then the kernel marks the mutex as DEAD and sends
the event registered with SyncMutexEvent().
If the event target happens to be the process that's dying, the event is not sent; you can use
procmgr_guardian() to try to handle this case.
If you don't designate a guardian or if you don't register an event, the mutex is marked as DESTROYED.
In both these cases, the kernel sends a SIGDEADLK signal
to all threads that are waiting without a timeout on the mutex.
For any of these threads that have not blocked SIGDEADLK,
their pthread_mutex_lock() calls return with EINVAL.
For any threads waiting with a timeout on the mutex,
their pthread_mutex_timedlock*() calls return with
EINVAL.
- If an event was attached and the target process is still running (i.e., it was not the one that died),
threads that are already waiting on the dead mutex continue to wait on it.
The thread that received the event calls SyncMutexRevive()
on the dead mutex and revives and acquires the mutex in one atomic operation.
If you call
pthread_mutex_lock():
- on a destroyed mutex, the function returns EINVAL
- on a dead mutex, your thread
will be blocked until the mutex is revived and released, or
the process that has the SyncMutexEvent() event registered
dies, in which case the lock operation returns EINVAL
Returns:
The only difference between these functions is the way they indicate errors:
- SyncMutexEvent()
- If an error occurs, the function returns -1 and sets
errno.
Any other value returned indicates success.
- SyncMutexEvent_r()
- Returns EOK on success.
This function does NOT set errno.
If an error occurs, the function returns any value listed in the Errors section.
Errors:
- EAGAIN
- All kernel synchronization event objects are in use.
- EFAULT
- A fault occurred when the kernel tried to access sync.
- EINVAL
- The synchronization object pointed to by sync doesn't exist, or it's a robust mutex.
- EPERM
- The calling process doesn't have the required permission; see
procmgr_ability().
Classification:
QNX Neutrino
Safety: |
|
Cancellation point |
No |
Interrupt handler |
No |
Signal handler |
Yes |
Thread |
Yes |