forksafe_mutex_lock()
Lock a forksafe mutex
Synopsis:
#include <forksafe_mutex.h>
int forksafe_mutex_lock( forksafe_mutex_t* mutex );
Arguments:
- mutex
- A pointer to the forksafe_mutex_t object that you want to lock.
Library:
libc, libforksafe_mutex
There are two versions of the forksafe_mutex_*() functions:
- The functions in libc are declared as weak symbols and use a regular mutex, simply calling the corresponding pthread_mutex_*() functions. Use the -l c option to qcc to link against this library. This library is usually included automatically.
- The functions in libforksafe_mutex use a forksafe mutex. Use the -l forksafe_mutex option to qcc to link against this library.
Description:
The forksafe_mutex_lock() function locks the forksafe mutex referenced by mutex. If the mutex is already locked, then the calling thread blocks until it has acquired the mutex. When the function returns, the mutex object is locked and owned by the calling thread.
This function's behavior when you try to lock a mutex that you already own depends on the type of the mutex. For more information, see the entry for pthread_mutexattr_settype().
By default, if a thread with a higher priority than the mutex owner
attempts to lock a mutex, then the effective priority of the
current owner is increased to that of the
higher-priority blocked thread waiting for the mutex. The
owner returns to its real priority when it unlocks the mutex.
For more information, see
Mutexes: mutual exclusion locks
in the IDE Microkernel
chapter of the
System Architecture guide.
If the mutex is recursive, you must call forksafe_mutex_unlock() for each corresponding call to lock the mutex.
If a signal is delivered to a thread that's waiting for a mutex, the thread resumes waiting for the mutex on returning from the signal handler.
If, before initializing the mutex, you've called
pthread_mutexattr_setwakeup_np()
to enable wake-ups, you can later call
pthread_mutex_wakeup_np(),
to wake up any threads that are blocked on the mutex.
The np
in this function's name stands for
non-POSIX.
For more information about forksafe mutexes, see
Using fork() in a multithreaded process
in the Processes and Threads
chapter of Getting Started with the QNX OS.
Returns:
- EOK
- Success.
- EAGAIN
- The mutex couldn't be acquired because the maximum number of recursive locks for mutex has been exceeded.
- EDEADLK
- One of the following occurred:
- The mutex type is PTHREAD_MUTEX_ERRORCHECK, and the current thread already owns the mutex.
- A deadlock condition was detected.
- EFAULT
- A fault occurred when the kernel tried to access the buffers you provided.
- EINTR
- (QNX OS extension) The thread was unblocked by a call to pthread_mutex_wakeup_np().
- EINVAL
- One of the following occurred:
- The mutex was created with a protocol attribute of PTHREAD_PRIO_PROTECT, and the calling thread's priority is higher than the mutex's current priority ceiling.
- The mutex is invalid, or it has died.
- (QNX OS extension) You're using safe shared mutexes (see the -s option for procnto), and you tried to lock a PTHREAD_PRIO_INHERIT mutex whose owner isn't known to the kernel and that the locking thread claims is from a different process.
- ENOTRECOVERABLE
- The mutex is a robust mutex, and the state that it protects isn't recoverable. All you can do with the mutex is destroy it by calling forksafe_mutex_destroy().
- EOWNERDEAD
- The mutex is a robust mutex, and the process containing the previous owning thread terminated while holding the mutex lock. The calling thread acquires the mutex lock; it's up to the new owner to make the state consistent (see pthread_mutex_consistent()).
- ETIMEDOUT
- A kernel timeout unblocked the call.
Examples:
This example shows how you can use a mutex to synchronize access to a shared variable. In this example, function1() and function2() both attempt to access and modify the global variable count. Either thread could be interrupted between modifying count and assigning its value to the local tmp variable. Locking mutex prevents this from happening; if one thread has mutex locked, the other thread waits until it's unlocked, before continuing.
#include <stdio.h>
#include <stdlib.h>
#include <forksafe_mutex.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
forksafe_mutex_t mutex = FORKSAFE_MUTEX_INITIALIZER;
int count = 0;
void* function1( void* arg )
{
int tmp = 0, ret_code;
while( 1 ) {
ret_code = forksafe_mutex_lock( &mutex );
if (ret_code == EOK)
{
tmp = count++;
ret_code = forksafe_mutex_unlock( &mutex );
if (ret_code != EOK)
{
printf ("forksafe_mutex_unlock() failed: %s\n",
strerror(ret_code));
}
printf ("Count is %d\n", tmp );
}
else
{
printf ("forksafe_mutex_lock() failed: %s\n",
strerror(ret_code));
}
/* Snooze for 1 second */
sleep( 1 );
}
return 0;
}
void* function2( void* arg )
{
int tmp = 0, ret_code;
while( 1 ) {
ret_code = forksafe_mutex_lock( &mutex );
if (ret_code == EOK)
{
tmp = count--;
ret_code = forksafe_mutex_unlock( &mutex );
if (ret_code != EOK)
{
printf ("** forksafe_mutex_unlock() failed: %s\n",
strerror (ret_code));
}
printf ("** Count is %d\n", tmp );
}
else
{
printf ("** forksafe_mutex_lock() failed: %s\n",
strerror (ret_code));
}
/* Snooze for 2 seconds */
sleep( 2 );
}
return 0;
}
int main( void )
{
int ret_code;
ret_code = pthread_create( NULL, NULL, &function1, NULL );
if (ret_code != EOK)
{
printf ("Couldn't create first thread: %s\n",
strerror (ret_code));
}
ret_code = pthread_create( NULL, NULL, &function2, NULL );
if (ret_code != EOK)
{
printf ("Couldn't create second thread: %s\n",
strerror (ret_code));
}
/* Let the threads run for 60 seconds. */
sleep( 60 );
return EXIT_SUCCESS;
}
Classification:
Safety: | |
---|---|
Cancellation point | No |
Signal handler | No |
Thread | Yes |