1

Following are the Linux Process states;

R: running or runnable, it is just waiting for the CPU to process it
S: Interruptible sleep, waiting for an event to complete, such as input from the terminal
D: Uninterruptible sleep, processes that cannot be killed or interrupted with a signal, usually to make them go away you have to reboot or fix the issue
Z: Zombie, we discussed in a previous lesson that zombies are terminated processes that are waiting to have their statuses collected
T: Stopped, a process that has been suspended/stopped

I have two questions;

(1) When a mutex_lock() is called in a process/thread, and if it is waiting for the lock to acquire(another thread locked the mutex already), will the process go to S or D?

(2) I know that spinlock() will put the process in busy waiting and it checks to see if the lock is unlocked by other thread. However in mutex_lock() how it knows that the lock is unlocked and it is available to lock and proceed? i.e; How the process wakes up from sleep to lock the mutex when it is available(unlocked by other thread)?

1 Answer 1

3
+25

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .