I was reading some documentation and trying out a few samples of code that issue the futex
system call in Linux. I read that if a mutex is acquired by thread_a
using FUTEX_LOCK_PI
, and say if another thread thread_b
tries to acquire the same, the latter(thread_b
) is blocked in the kernel.
What exactly is meant by "blocked in the kernel"? Is it that the execution of thread_b
in userspace does not resume? In the following example, the second thread seems to issue the printf after the syscall as well. Would that not suggest that it is not blocked in the kernel? What am I missing?
/*
* This example demonstrates that when futex_lock_pi is called twice, the
* second call is blocked inside the kernel.
*/
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int mutex = 0;
#define __NR_futex 240
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_FD 2
#define FUTEX_REQUEUE 3
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
void *thread(void *arg) {
int ret = 0;
pid_t tid = gettid();
printf("Entering thread[%d]\n", tid);
ret = syscall(__NR_futex, &mutex, FUTEX_LOCK_PI, 1, NULL, NULL, 0);
printf("Thread %d returned from kernel\n", tid);
printf("Value of mutex=%d\n", mutex);
printf("Return value from syscall=%d\n", ret);
}
int main(int argc, const char *argv[]) {
pthread_t t1, t2;
if (pthread_create(&t1, NULL, thread, NULL)) {
printf("Could not create thread 1\n");
return -1;
}
if (pthread_create(&t2, NULL, thread, NULL)) {
printf("Could not create thread 2\n");
return -1;
}
// Loop infinitely
while ( 1 ) { }
return 0;
}
The output can be found below :-
Entering thread[952]
Thread 952 returned from kernel
Entering thread[951]
Value of mutex=-2147482696
Return value from syscall=0
Thread 951 returned from kernel
Value of mutex=-1073740873
Return value from syscall=0
LOCK
substring in the futex operation name). In that mode futex values transition scheme is fully defined, and doesn't depends fromval
andval2
arguments offutex
system call. Value of futex in unlocked state must be 0. Check that. – Reardontid
value, stored in futex, exists and actually access it for perform priority-inversion. As I understand, if owner of the futex is exited, mutex treated as unlocked. Try to addsleep()
at the end of your thread function and check, whether the second thread returns fromfutex()
call while the first one(futex owner) sleeps. (This shouldn't be happen). – Reardonsleep(5); printf("Thread %d is exited\n", tid);
to the end of your thread function. And see order of messages in the output. – Reardon