Discussion:
find the owner of a pthread mutex
(too old to reply)
Paul Thomas
2006-04-02 09:47:59 UTC
Permalink
Does anyone know of a way to find which pthread currently has the lock
of a mutex? It doesn't have to be portable - maybe linux or some other
platform specific.

I only want to assert() that a lock is held by the caller so even if it
only works on one platform it's better than nothing.

cheers.
Casper H.S. Dik
2006-04-02 12:02:01 UTC
Permalink
Post by Paul Thomas
Does anyone know of a way to find which pthread currently has the lock
of a mutex? It doesn't have to be portable - maybe linux or some other
platform specific.
I only want to assert() that a lock is held by the caller so even if it
only works on one platform it's better than nothing.
Why don't you use PTHREAD_MUTEX_ERRORCHECK as mutex type?

That way, when you attempt to lock/unlock a mutex you will automatically
get an error return which will tell you what's up.

Note that obtaining the owner of a mutex which you do not own is a
meaningless operation; the owner returned may no longer own it when
you check it and the mutex may be relocked by another thread in
the interim.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Paul Pluzhnikov
2006-04-02 15:22:45 UTC
Permalink
Post by Paul Thomas
Does anyone know of a way to find which pthread currently has the lock
of a mutex? It doesn't have to be portable - maybe linux or some other
platform specific.
On solaris, dbx can do that:
(dbx) sync -info 0xff369b80
__uberdata+0xfc0 (0xff369b80): usync_? mutex(unlocked)
Lock is unowned
No threads are blocked by this lock
Post by Paul Thomas
I only want to assert() that a lock is held by the caller so even if it
only works on one platform it's better than nothing.
Ah, you want a programmatic way ...
Post by Paul Thomas
Why don't you use PTHREAD_MUTEX_ERRORCHECK as mutex type?
That way, when you attempt to lock/unlock a mutex you will automatically
get an error return which will tell you what's up.
I think he wants to assert that his caller has a particular lock
held:

int somefunc(..., pthread_mutex_t *mtx)
{
assert(pthread_equal(pthread_self(), mutex_owner(mtx)));
...
}

I don't see how ERRORCHECK would help him with that ...

If you always use your own lock/unlock wrapper function and
care about only one mutex, then storing lock owner in a global
variable just after pthread_mutex_lock, and clearing it just before
pthread_mutex_unlock will do the trick portably.

Otherwise, you'll have to grovel in libpthread internals (possible
on Linux and Solaris) -- the owner is (usually) stored somewhere
in the pthread_mutex_t ...

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
David Hopwood
2006-04-02 17:05:21 UTC
Permalink
Post by Paul Pluzhnikov
Post by Paul Thomas
I only want to assert() that a lock is held by the caller so even if it
only works on one platform it's better than nothing.
Ah, you want a programmatic way ...
Post by Paul Thomas
Why don't you use PTHREAD_MUTEX_ERRORCHECK as mutex type?
That way, when you attempt to lock/unlock a mutex you will automatically
get an error return which will tell you what's up.
I think he wants to assert that his caller has a particular lock
int somefunc(..., pthread_mutex_t *mtx)
{
assert(pthread_equal(pthread_self(), mutex_owner(mtx)));
...
}
I don't see how ERRORCHECK would help him with that ...
Why not just try to relock the mutex and assert that you get the error
return?
--
David Hopwood <***@blueyonder.co.uk>
David Schwartz
2006-04-03 21:09:54 UTC
Permalink
Post by David Hopwood
Why not just try to relock the mutex and assert that you get the error
return?
That might just lock up.

DS
Casper H.S. Dik
2006-04-02 18:44:46 UTC
Permalink
Post by Paul Pluzhnikov
I don't see how ERRORCHECK would help him with that ...
If he tries to lock again, he'd get EDEADLK, so he can:

assert(pthread_mutex_lock(&lock) == EDEADLK);

as that's the only time the lock should fail.

If it doesn't fail, the assert trips and the application
terminates.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Paul Thomas
2006-04-03 18:12:14 UTC
Permalink
Post by Casper H.S. Dik
Post by Paul Pluzhnikov
I don't see how ERRORCHECK would help him with that ...
assert(pthread_mutex_lock(&lock) == EDEADLK);
as that's the only time the lock should fail.
If it doesn't fail, the assert trips and the application
terminates.
Casper
That's what I was after - thanks (to all).

BTW: I'd thought that the other suggestion about another variable
holding the thread ID wouldn't work without memory barriers, but now I'm
thinking it might because I only want to check for the current thread's ID.

My mutex is actually a structure member so I can easily add:

class CMutex{
pthread_mutex_t m_mtx;
pthread_t m_owner;
public:
void lock(){
//...
m_owner = pthread_self();
}
void unlock(){
m_owner = 0;
//...
}
bool locked_by_self() {
return m_owner == pthread_self();
}
}

That should work, right?
I mean, other checks would be invalid - checking for 0 etc. But
locked_by_self() would work.

Ta,
Paul.
David Schwartz
2006-04-03 23:50:05 UTC
Permalink
Post by Paul Thomas
bool locked_by_self() {
return m_owner == pthread_self();
}
}
That should work, right?
No. There is no guarantee that pthread_t's are unique, that is, a thread
may have more than one pthread_t that references is. You need to at least
use 'pthread_equal' to see if two pthread_t's refer to the same thread.

DS
Marcin 'Qrczak' Kowalczyk
2006-04-04 00:43:22 UTC
Permalink
Post by David Schwartz
Post by Paul Thomas
bool locked_by_self() {
return m_owner == pthread_self();
}
No. There is no guarantee that pthread_t's are unique, that is,
a thread may have more than one pthread_t that references is.
This is unlikely. pthread_t may be copied by plain assignment.
And since it *may* be copied, it can't contain useful mutable
components. So memory representation could differ only if it
contained some ignored bits, and pthread_self returned different
values of those bits on different invocations, or different
values than pthread_create.

The rationale of pthread_equal is that pthread_t may be a struct.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
d***@webmaster.com
2006-04-05 09:40:37 UTC
Permalink
Post by Marcin 'Qrczak' Kowalczyk
This is unlikely. pthread_t may be copied by plain assignment.
And since it *may* be copied, it can't contain useful mutable
components. So memory representation could differ only if it
contained some ignored bits, and pthread_self returned different
values of those bits on different invocations, or different
values than pthread_create.
There is nothing in the pthreads standard that requires pthread_t to be
a normal type. It can be something totally unlike any normal type or
structure so long as the requirements of the pthreads standard are met.

You cannot use an argument like this:

1) POSIX requires X.
2) C only provides mechanisms A, B, and C for doing X.
3) Y is true of A, B, and C.
4) Thus Y is true of X.

Because POSIX does not require X to be done using a mechanism provided
by C. A completely new mechanism, D can be invented. And Y may not be
true of D.

DS
Casper H.S. Dik
2006-04-05 10:05:03 UTC
Permalink
Post by d***@webmaster.com
There is nothing in the pthreads standard that requires pthread_t to be
a normal type. It can be something totally unlike any normal type or
structure so long as the requirements of the pthreads standard are met.
It requires "pthread_t" to be an "arithmetic type of an appropriate length".


See:

http://www.opengroup.org/onlinepubs/007908799/xsh/systypes.h.html

But this may well be a bug in the standard.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
d***@webmaster.com
2006-04-06 11:11:00 UTC
Permalink
Post by Casper H.S. Dik
It requires "pthread_t" to be an "arithmetic type of an appropriate length".
http://www.opengroup.org/onlinepubs/007908799/xsh/systypes.h.html
But this may well be a bug in the standard.
That is somewhat baffling. That would suggest that implementations that
use some kind of magic for these types *is* violating the standard.

DS
Marcin 'Qrczak' Kowalczyk
2006-04-06 11:38:03 UTC
Permalink
Post by d***@webmaster.com
Post by Casper H.S. Dik
But this may well be a bug in the standard.
That is somewhat baffling. That would suggest that implementations that
use some kind of magic for these types *is* violating the standard.
It's definitely a bug because the rationale for pthread_equal says
that it may be a struct.

But I doubt that any existing implementation uses some "magic" type
with a non-standard copy semantics (not an integral type, nor a
pointer, nor a struct containing them), even if it theoretically
could.

I don't even believe that it could. In C assignment of a value of any
non-array type is equivalent to memcpy, if the representation is not a
trap representation. POSIX doesn't invalidate this assumption, so it
must still hold.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Patrick TJ McPhee
2006-04-07 04:25:43 UTC
Permalink
In article <***@qrnik.zagroda>,
Marcin 'Qrczak' Kowalczyk <***@knm.org.pl> wrote:

% But I doubt that any existing implementation uses some "magic" type
% with a non-standard copy semantics (not an integral type, nor a
% pointer, nor a struct containing them), even if it theoretically
% could.

Depending on what you mean by 'existing implementation'. The reference
DCE threads implementation (based on an early POSIX draft) used a
struct for pthread_t.
--
Patrick TJ McPhee
North York Canada
***@interlog.com
Dave Butenhof
2006-04-10 11:03:42 UTC
Permalink
Post by Casper H.S. Dik
Post by d***@webmaster.com
There is nothing in the pthreads standard that requires pthread_t to be
a normal type. It can be something totally unlike any normal type or
structure so long as the requirements of the pthreads standard are met.
It requires "pthread_t" to be an "arithmetic type of an appropriate length".
http://www.opengroup.org/onlinepubs/007908799/xsh/systypes.h.html
But this may well be a bug in the standard.
(I "overlooked" this discussion last week because I was too busy to look
up references, and then forgot about it. But thanks to the reminder of
newer activity, I've been reminded.)

Technically, there are no bugs in the standard. That is, "the standard
says what it says", right or wrong. ;-)

But the original intent of the working group was that pthread_t need not
be arithmetic. Nobody at the time noticed that there was a section
requiring all types to be arithmetic with specific exclusions, rather
than listing the types that must be arithmetic. The synchronization
types were added, but somehow pthread_t was omitted.

The omission of pthread_t was finally corrected in the 2004 "TC2"
edition, as such:

------------------
* Add to XBD sys/types.h CHANGE HISTORY

IEEE Std 1003.1-2001/Cor 2-2004, item XBD/TC2/D6/26 is applied,
adding pthread_t to the list of types that are not required to
be arithmetic types, thus allowing the pthread_t to be defined
as a structure.
------------------

Or for the final format (HTML):

http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/types.h.html#tag_13_67
Marcin 'Qrczak' Kowalczyk
2006-04-04 00:54:57 UTC
Permalink
Post by David Schwartz
Post by Paul Thomas
bool locked_by_self() {
return m_owner == pthread_self();
}
No. There is no guarantee that pthread_t's are unique, that is,
a thread may have more than one pthread_t that references is.
This is unlikely. Why would that be true?

Since pthread_t may be copied by plain assignment, it can't contain
useful mutable components, nor self-pointers. Equal representation
must imply logically equal values. This means that any differences
in the representation of some logically equal values are redundant.

They might result from "holes" in the representation, e.g. unused bits
which have different results in different invocations of pthread_self
(or different than in pthread_create), but I feel that this is unlikely.

The rationale of pthread_equal is that pthread_t may be a struct.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Paul Pluzhnikov
2006-04-04 02:26:05 UTC
Permalink
Post by Paul Thomas
BTW: I'd thought that the other suggestion about another variable
holding the thread ID wouldn't work without memory barriers,
pthread_mutex_{un}lock already performs all necessary barriers.
Post by Paul Thomas
but now I'm
thinking it might because I only want to check for the current thread's ID.
It will work regardless of wherher you check current thread ID or
some other, provided you read/write m_owner while holding some lock
(which doesn't have to be the m_mtx).
Post by Paul Thomas
bool locked_by_self() {
return pthread_equals(m_owner, pthread_self());
Post by Paul Thomas
}
}
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Paul Thomas
2006-04-04 06:01:27 UTC
Permalink
Post by Paul Pluzhnikov
Post by Paul Thomas
BTW: I'd thought that the other suggestion about another variable
holding the thread ID wouldn't work without memory barriers,
pthread_mutex_{un}lock already performs all necessary barriers.
Post by Paul Thomas
but now I'm
thinking it might because I only want to check for the current thread's ID.
It will work regardless of wherher you check current thread ID or
some other, provided you read/write m_owner while holding some lock
(which doesn't have to be the m_mtx).
Fair point, I should have mentioned that I wanted a solution that didn't
actually do any locking itself if the predicate is true. I want it for
an assert()ion that I can liberally sprinkle over the code without
people complaining. It's also self documenting.

If I protected m_owner, it would require a second mutex and then every
lock(), unlock() or locked_by_self() of the primary mutex would require
a lock/unlock pair on the secondary. I might get lynched.

Paul.
dhruv
2006-04-04 09:14:49 UTC
Permalink
I think pthread_recursive_np is what you need. When u create such a
mutex(iirc), you can re-lock the mutex from the same thread. So, if you
can do that, you are the owner. If you can't and the function returns
an error(assuming you are using the non-blocking version), then you are
obviously not the owner.
Loading...