|
Syntax #include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); Threadsafe: Yes Signal Safe: Yes |
The pthread_mutex_lock() function acquires ownership of the mutex specified. If the mutex is currently locked by another thread, the call to pthread_mutex_lock() will block until that thread relinquishes ownership via a call to pthread_mutex_unlock().
If a signal is delivered to a thread while that thread is waiting for a mutex, when the signal handler returns, the wait will resume. pthread_mutex_lock() will not return EINTR like some other blocking function calls.
Use the CL command WRKJOB, option 20 for a screen that will aid in debugging mutex deadlocks.
Destroying a held mutex is a common way to serialize destruction of objects that are protected by that mutex, and is allowed. The call to pthread_mutex_lock() may fail with the EDESTROYED error if the mutex is destroyed by the thread that was currently holding it.
Note that mutex initialization using the PTHREAD_MUTEX_INITIALIZER does not immediately initialize the mutex. Instead, on first use, pthread_mutex_timedlock_np() or pthread_mutex_lock() or pthread_mutex_trylock() branches into a slow path and causes the initialization of the mutex. Because a mutex isn't just a simple memory object, and requires that some resources be allocated by the system, an attempt to call pthread_mutex_destroy() or pthread_mutex_unlock() on a mutex that has was statically initialized using PTHREAD_MUTEX_INITIALER and was not yet locked will result in an EINVAL error.
A pthread mutex is a structure of type pthread_mutex_t that implement a behavior based on the Pthread mutexes. An MI mutex is a structure built into the machine that implement a similar sort of serialization construct.
The maximum number of recursive locks by the owning thread is 32,767. After which, attempts to lock the mutex will return the ERECURSE error.
Mutex Types
A normal mutex cannot be locked repeatedly by the owner. Attempts by a thread to relock an already held mutex, or to lock a mutex that was held by another thread when that thread terminated result in a deadlock condition.
A recursive mutex can be locked repeatedly by the owner. The mutex doesn't become unlocked until the owner has called pthread_mutex_unlock() for each successful lock request that it has outstanding on the mutex.
An errorcheck mutex checks for deadlock conditions that occur when a thread re-locks an already held mutex. If a thread attempts to relock a mutex that it already holds, the lock request fails with the EDEADLK error
An ownerterm mutex is an OS/400 extension to the errorcheck mutex type. An ownerterm mutex checks for deadlock conditions that occur when a thread re-locks an already held mutex. If a thread attempts to relock a mutex that it already holds, the lock request fails with the EDEADLK error. An ownerterm mutex also checks for deadlock conditions that occur when a thread attempts to lock a mutex that was held by another thread when that thread terminated (an orphaned mutex). If a thread attempts to lock an orphaned mutex, the lock request fails with the EOWNERTERM error.
When a thread terminates holding a mutex lock on a normal or errorcheck mutex, other threads that wait for that mutex will block forever. The pthreads run-time simulates the deadlock that has occurred in your application. When attempting to debug these deadlock scenarios, the CL command WRKJOB, option 20 will show the thread as in a condition wait. Displaying the call stack will show that the function deadlockedOnOrphanedMutex is in the call stack.
When a thread attempts to acquire a normal mutex that it already holds, the thread will block forever. The pthreads run-time simulates the deadlock that has occurred in your application. When attempting to debug these deadlock scenarios, the CL command WRKJOB, option 20 will show the thread as in a condition wait. Displaying the call stack will show that the function deadlockedOnAlreadyLockedMutex is in the call stack.
In order to change these behaviors, use an errorcheck or ownerterm mutex type.
None.
If pthread_mutex_lock() was not successful, the error condition returned usually indicates one of the following errors. Under some conditions, the value returned could indicate an error other than those listed here.
#include <pthread.h>
#include <stdio.h>
#include "check.h"
/*
This example shows the corruption that can result if no
serialization is done and also shows the use of
pthread_mutex_lock(). Call it with no parameters
to use pthread_mutex_lock() to protect the critical section,
or 1 or more parameters to show data corruption that occurs
without locking.
*/
#define LOOPCONSTANT 100000
#define THREADS 10
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int i,j,k,l;
int uselock=1;
void *threadfunc(void *parm)
{
int loop = 0;
int rc;
for (loop=0; loop<LOOPCONSTANT; ++loop) {
if (uselock) {
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
}
++i; ++j; ++k; ++l;
if (uselock) {
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
}
}
return NULL;
}
int main(int argc, char **argv)
{
pthread_t threadid[THREADS];
int rc=0;
int loop=0;
pthread_attr_t pta;
printf("Entering testcase\n");
printf("Give any number of parameters to show data corruption\n");
if (argc != 1) {
printf("A parameter was specified, no serialization is being done!\n");
uselock = 0;
}
pthread_attr_init(&pta);
pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_JOINABLE);
printf("Creating %d threads\n", THREADS);
for (loop=0; loop<THREADS; ++loop) {
rc = pthread_create(&threadid[loop], &pta, threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait for results\n");
for (loop=0; loop<THREADS; ++loop) {
rc = pthread_join(threadid[loop], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Cleanup and show results\n");
pthread_attr_destroy(&pta);
pthread_mutex_destroy(&mutex);
printf("\nUsing %d threads and LOOPCONSTANT = %d\n",
THREADS, LOOPCONSTANT);
printf("Values are: (should be %d)\n", THREADS * LOOPCONSTANT);
printf(" ==>%d, %d, %d, %d\n", i, j, k, l);
printf("Main completed\n");
return 0;
}
Output
Entering testcase Give any number of parameters to show data corruption Creating 10 threads Wait for results Cleanup and show results Using 10 threads and LOOPCONSTANT = 100000 Values are: (should be 1000000) ==>1000000, 1000000, 1000000, 1000000 Main completedOutput
(data corruption without locking example)
Entering testcase Give any number of parameters to show data corruption A parameter was specified, no serialization is being done! Creating 10 threads Wait for results Cleanup and show results Using 10 threads and LOOPCONSTANT = 100000 Values are: (should be 1000000) ==>883380, 834630, 725131, 931883 Main completed