Attach an event to a mutex
#include <sys/neutrino.h> int SyncMutexEvent( sync_t * sync, struct sigevent * event ); int SyncMutexEvent_r( sync_t * sync, struct sigevent * event );
- A pointer to the synchronization object for the mutex that you want to attach an event to.
- 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.
Use the -l c option to qcc to link against this library. This library is usually included automatically.
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 one of the following occurs:
- a process with a thread that owns the mutex unmaps the memory
- a process dies while holding the mutex in shared memory
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.
In order to use this function with a SIGEV_PULSE sigevent that's going to a channel that was created by a different process with a different user ID, your process must have the PROCMGR_AID_CONNECTION ability enabled. For more information, see procmgr_ability().
Managing the death of a mutex
Here's how you might use a mutex in shared memory between threads in two or more processes and attempt to deal with the untimely death of one of the processes while it's holding the mutex.
If a process dies while one of its threads owns a mutex, it's very likely because of a bug in the process. Although the OS provides a way to detect this situation and revive the mutex, the data that the mutex is protecting might be in an inconsistent state.
- Designate one process as the shared memory's owner/manager.
- This process creates and initializes the mutex, and attaches an event using SyncMutexEvent().
- This process marks the shared memory area and the mutex as usable.
- Everyone goes ahead and uses the mutex and shared memory area; it's all fun and games until someone dies.
- If a process dies, and one of its threads owns the mutex
(i.e., has locked it), then the kernel marks the mutex as DEAD and sends
the event registered with SyncMutexEvent() to the owner process.
If it's the owner process that died, then there's no event delivered, and the mutex is marked as DESTROYED; you can use procmgr_guardian() to try to handle this case. If there's no event registered, 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. If these threads have blocked SIGDEADLK, they're made READY, as are threads that are waiting on the mutex, but with a timeout.
- It's up to the owner process to handle the event. It should have some way of telling other threads that the shared memory area controlled by the mutex, and the mutex itself, are currently unusable, and should also have a mechanism to indicate when they again become usable.
- Other threads already waiting on the dead mutex continue to wait on it.
- The process acting on 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
The only difference between these functions is the way they indicate errors:
- If an error occurs, the function returns -1 and sets errno . Any other value returned indicates success.
- Returns EOK on success. This function does NOT set errno. If an error occurs, the function returns any value listed in the Errors section.
- All kernel synchronization event objects are in use.
- A fault occurred when the kernel tried to access sync.
- The synchronization object pointed to by sync doesn't exist.
- The calling process doesn't have the required permission; see procmgr_ability().
Last modified: 2014-06-24