Updated: April 19, 2023 |
Lock a forksafe mutex
#include <forksafe_mutex.h> int forksafe_mutex_lock( forksafe_mutex_t* mutex );
libc, libforksafe_mutex
In QNX Neutrino 7.1 or later, there are two versions of the forksafe_mutex_*() functions:
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 QNX Neutrino 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 QNX Neutrino.
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; }
Safety: | |
---|---|
Cancellation point | No |
Interrupt handler | No |
Signal handler | No |
Thread | Yes |