Yusuf Husainy
Yusuf Husainy

Reputation: 635

How to get thread id of owning thread for a locked mutex in pthreads

A thread has a mutex of type pthread_mutex_t locked for itself. Another thread wants to know the thread id of the thread holding this locked mutex.

There are two types of thread ids as I understand. The POSIX/pthread thread id, returned by pthread_self(), and the linux thread id returned by the system call gettid(). These two are independent and have no relation, AFAIK (please correct me If I am wrong).

There is a field in the structure pthread_mutex_t, int __owner which stores the thread id of the thread that current holds the lock. This field can be accessed by,

pthread_mutex_t mutex;
int tid;
tid = mutex.__data.__owner;

As described here - Is it possible to determine the thread holding a mutex?.

This __owner field has the linux system thread id (as would be returned by gettid()) and not the POSIX/pthread thread id (as would be returned by pthread_self()) .

I want to compare whether the current scheduled thread is owning the mutex or not. So, I should be comparing pthread_self() with the __owner value.

I could use gettid() instead of pthread_self(), but I am restricted to use pthread_self() only. (some portability features).

Is there any way to correctly determine the thread id of the locked mutex which would return pthread_t and not the system thread id?

I will appreciate any help, Thanks!

Regards,

Yusuf Husainy.

Upvotes: 3

Views: 5146

Answers (2)

Mark Kica
Mark Kica

Reputation: 1

How about using the stack trace for this? For example, if I use the pstack command on my multi-threaded app with a locked mutex I see the following:

# pstack <PID>

Thread 3 (Thread 0x7fb94a4f4700 (LWP 25157)):
#0  0x00000034a7e0e264 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00000034a7e09508 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x00000034a7e093d7 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x000000000040af63 in read_from_pbx_loop(void*) ()
#4  0x00000034a7e079d1 in start_thread () from /lib64/libpthread.so.0
#5  0x00000034a7ae88fd in clone () from /lib64/libc.so.6
Thread 2 (Thread 0x7fb949cf3700 (LWP 25158)):
#0  0x00000034a7aaca3d in nanosleep () from /lib64/libc.so.6
#1  0x00000034a7ae1be4 in usleep () from /lib64/libc.so.6
#2  0x00000000004074f0 in read_from_agent_loop(void*) ()
#3  0x00000034a7e079d1 in start_thread () from /lib64/libpthread.so.0
#4  0x00000034a7ae88fd in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7fb94a4f6720 (LWP 25156)):
#0  0x00000034a7aaca3d in nanosleep () from /lib64/libc.so.6
#1  0x00000034a7ae1be4 in usleep () from /lib64/libc.so.6
#2  0x000000000040c600 in main ()

So you can get a stack trace of your thread and use some simple heuristic checks to see if the last step of the stack trace for your thread is __lll_lock_wait.

Upvotes: 0

user184968
user184968

Reputation:

1)

These two are independent and have no relation, AFAIK (please correct me If I am wrong).

That is correct. from man pthread_self:

The thread ID returned by pthread_self() is not the same thing as the kernel thread ID returned by a call to gettid(2).

2)

so, I should be comparing pthread_self() with the __owner value

That is incorrect, man pthread_self:

Thread identifiers should be considered opaque: any attempt to use a thread ID other than in pthreads calls is non-portable and can lead to unspecified results.

3)

Is there any way to correctly determine the thread id of the locked mutex which would return pthread_t and not the system thread id?

I guess, no. pthread_mutex_t has the field int __owner; and does not have any field like pthread_owner that would contain pthread_t of the thread:

/* Data structures for mutex handling.  The structure of the attribute
   type is not exposed on purpose.  */
typedef union
{
  struct __pthread_mutex_s
  {
    int __lock;
    unsigned int __count;
    int __owner;
#if __WORDSIZE == 64
    unsigned int __nusers;
#endif
    /* KIND must stay at this position in the structure to maintain
       binary compatibility.  */
    int __kind;
#if __WORDSIZE == 64
    int __spins;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
#else
    unsigned int __nusers;
    __extension__ union
    {
      int __spins;
      __pthread_slist_t __list;
    };
#endif
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;

Upvotes: 2

Related Questions