Well, let's find out:
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main ()
{
pthread_mutex_t mtx;
pid_t pid;
pthread_mutex_init (&mtx, NULL);
pid = getpid();
printf ("pid : %d\n", pid);
pthread_mutex_lock (&mtx);
// Double lock. This results in a dead-lock
pthread_mutex_lock (&mtx);
pthread_mutex_destroy (&mtx);
}
Compile with:
gcc -lpthread -o prog prog.c
And then run:
./prog
pid : 23537
(This is the pid in my particular case. Your run will result in a different one)
Now let's find out the state of this process:
ps aux | grep 23537
user 23537 0.0 0.0 6448 840 pts/4 S+ 16:29 0:00 ./prog
The S+ is the state of the process.
According to the man page
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a
process:
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
For BSD formats and when the stat keyword is used, additional characters may be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group
So it is interruptible sleep (waiting for an event to complete) in the foreground process group
Regarding your second question: when a thread tries to get a mutex that is already locked, the kernel removes that thread from the CPU and stores it in a queue. When the owner releases the lock, the kernel looks if there are any threads in the queue, and wakes them up (maybe).
This is different from a spinlock. A spinlock would be something similar to:
int lock = 1;
// 1 means locked, 0 means unlocked
while (lock) {};
// If we are here, it means the lock somehow changed to 0
lock = 1;
// We set it to one again to avoid another thread taking it
But this implementation is not atomic. The kernel provides some means to do this atomically.