Thursday, October 29, 2009

comp.programming.threads - 21 new messages in 4 topics - digest

comp.programming.threads
http://groups.google.com/group/comp.programming.threads?hl=en

comp.programming.threads@googlegroups.com

Today's topics:

* C++1x: lock-free algos and blocking - 1 messages, 1 author
http://groups.google.com/group/comp.programming.threads/t/413742cae0d2dddf?hl=en
* Library requirement for mutex destroy - 15 messages, 8 authors
http://groups.google.com/group/comp.programming.threads/t/4a94e9df8d2f3e22?hl=en
* clock attribute of a condvar - 2 messages, 2 authors
http://groups.google.com/group/comp.programming.threads/t/0bd8148213fe6b17?hl=en
* syscalls - 3 messages, 2 authors
http://groups.google.com/group/comp.programming.threads/t/7db32595fcbaa497?hl=en

==============================================================================
TOPIC: C++1x: lock-free algos and blocking
http://groups.google.com/group/comp.programming.threads/t/413742cae0d2dddf?hl=en
==============================================================================

== 1 of 1 ==
Date: Mon, Oct 26 2009 7:30 am
From: Dmitriy Vyukov


On Oct 26, 5:01 pm, kibun <davide.rosse...@gmail.com> wrote:

> >     void prv_signal(key_type key)
> >     {
> >         if (key & 1)
> >         {
> >             m_mutex.lock($);
>
> I know it may be RTFM... but where is this '$' syntax documented. I
> feel like I missed something important on the cpp-threads mailing
> list...


It's the syntax of Relacy Race Detector - synchronization algorithm
verifier:
http://groups.google.com/group/relacy

--
Dmitriy V'jukov

==============================================================================
TOPIC: Library requirement for mutex destroy
http://groups.google.com/group/comp.programming.threads/t/4a94e9df8d2f3e22?hl=en
==============================================================================

== 1 of 15 ==
Date: Wed, Oct 28 2009 6:27 am
From: Noob


[ Cross-posted to c.p.t and c.u.p ]

Hello,

I'm using a proprietary library (no source code) which requires the user
to provide 4 mutex-related functions (create, delete, lock, unlock).

AFAICT, if I were using a POSIX OS, I could make trivial wrappers around

pthread_mutex_init
pthread_mutex_destroy
pthread_mutex_lock
pthread_mutex_unlock

But this library has specific requirements for the delete function:

If delete is called on a locked mutex, the function must return an error
code to signal the error to the function's caller.

However, the documentation for pthread_mutex_destroy explicitly states:
http://www.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html

"""
It shall be safe to destroy an initialized mutex that is unlocked.
Attempting to destroy a locked mutex results in undefined behavior.
"""

This means that my delete function can't just call pthread_mutex_destroy
because I would invoke UB if the mutex is locked, and I wouldn't be able
to return the requested error code, right?

So... Does this mean I have to keep track whether the mutex is locked?
(It would appear so.)

Or perhaps I could mess with the OS code? (shudder)

I'd like to tell the library author that it is unreasonable to impose
overhead on every lock and unlock operation just to catch an obvious (?)
programming error on delete. What do you think?

N.B. the library requires mutex with recursive semantic.

Regards.


== 2 of 15 ==
Date: Wed, Oct 28 2009 7:29 am
From: David Schwartz


On Oct 28, 6:27 am, Noob <r...@127.0.0.1> wrote:

> But this library has specific requirements for the delete function:
>
> If delete is called on a locked mutex, the function must return an error
> code to signal the error to the function's caller.

That is, IMO, fundamentally busted behavior, unless it only means
locked by the calling thread.

> This means that my delete function can't just call pthread_mutex_destroy
> because I would invoke UB if the mutex is locked, and I wouldn't be able
> to return the requested error code, right?
>
> So... Does this mean I have to keep track whether the mutex is locked?
> (It would appear so.)
> Or perhaps I could mess with the OS code? (shudder)
>
> I'd like to tell the library author that it is unreasonable to impose
> overhead on every lock and unlock operation just to catch an obvious (?)
> programming error on delete. What do you think?
>
> N.B. the library requires mutex with recursive semantic.

Since the mutex is recursive, one of two things are the case:

1) The requirement only applies if the calling thread holds the lock
on the mutex, in which case you have to keep track of the lock count
anyway. (Otherwise, how would you know what to do in the unlock
operation?) The library is being reasonable, though quirky.

2) The requirement applies even if another thread holds the mutex.
This is a real pain to implement, and the requirement is fundamentally
busted.

DS


== 3 of 15 ==
Date: Wed, Oct 28 2009 8:04 am
From: Noob


David Schwartz wrote:

> Noob wrote:
>
>> But this library has specific requirements for the delete function:
>>
>> If delete is called on a locked mutex, the function must return an error
>> code to signal the error to the function's caller.
>
> That is, IMO, fundamentally busted behavior, unless it only means
> locked by the calling thread.

Could you expand on /why/ you think it is busted behavior?
(I need ammo to try to convince the library authors.)

The exact requirements are:

1) Return an error when attempting to delete "a mutex currently owned by
another thread".
2) Return an error when attempting to delete "a mutex currently owned by
the calling thread".

NB: by "owned" I assume they mean "locked".

Since a locked mutex is so either by the calling thread, or by another
thread (duh!) it seems the two requirements boil down to:

Return an error (and, I assume, leave the mutex alone) when attempting
to delete a locked mutex.

>> This means that my delete function can't just call pthread_mutex_destroy
>> because I would invoke UB if the mutex is locked, and I wouldn't be able
>> to return the requested error code, right?
>>
>> So... Does this mean I have to keep track whether the mutex is locked?
>> (It would appear so.)
>> Or perhaps I could mess with the OS code? (shudder)
>>
>> I'd like to tell the library author that it is unreasonable to impose
>> overhead on every lock and unlock operation just to catch an obvious (?)
>> programming error on delete. What do you think?
>>
>> N.B. the library requires mutex with recursive semantic.
>
> Since the mutex is recursive, one of two things are the case:
>
> 1) The requirement only applies if the calling thread holds the lock
> on the mutex, in which case you have to keep track of the lock count
> anyway. (Otherwise, how would you know what to do in the unlock
> operation?) The library is being reasonable, though quirky.

The OS I'm using provides recursive mutex. Therefore, I don't think I
have to deal with lock counts, as the OS takes care of that.

Unless I need to know in delete whether the mutex is locked.

Trying to delete a locked mutex sounds like a serious programmer error.

Mutex destruction (and creation) should be done in well-defined parts of
the application, when one can be sure the mutex is not in use anymore,
right?

> 2) The requirement applies even if another thread holds the mutex.
> This is a real pain to implement, and the requirement is fundamentally
> busted.

According to the library's spec, delete may be called at any time, by
any thread, and it is the user's responsibility to return an error and
leave the mutex untouched if the mutex is currently locked...

Regards.


== 4 of 15 ==
Date: Wed, Oct 28 2009 8:40 am
From: Eric Sosman


Noob wrote:
> David Schwartz wrote:
>
>> Noob wrote:
>>
>>> But this library has specific requirements for the delete function:
>>>
>>> If delete is called on a locked mutex, the function must return an error
>>> code to signal the error to the function's caller.
>> That is, IMO, fundamentally busted behavior, unless it only means
>> locked by the calling thread.
>
> Could you expand on /why/ you think it is busted behavior?
> (I need ammo to try to convince the library authors.)
>
> The exact requirements are:
>
> 1) Return an error when attempting to delete "a mutex currently owned by
> another thread".

This is broken, period. Suppose thread T1 tries to delete the
mutex and discovers (somehow) that it is locked by T2. T1 leaves
the mutex alone, the deletion attempt returns an error, and all is
well.

But suppose T1 comes along at a moment when the mutex is unlocked,
and succeeds in deleting it. Two clock cycles later, T2 tries to lock
the destroyed mutex, and the fertilizer hits the fan. The fact that T1
found the mutex unlocked is no proof that the mutex is "unused," or
that T2 might not attempt to use it again.

If T1 deletes a mutex that T2 might still want to use, the
application is broken. If T1 can find the mutex locked by T2, it
must be the case that T2 still wants to use it. Therefore the mere
possibility that delete-while-locked-elsewhere could occur is proof
that the design is broken.

> 2) Return an error when attempting to delete "a mutex currently owned by
> the calling thread".

This isn't quite as clear-cut, but it still seems dubious.

> [...]
> Trying to delete a locked mutex sounds like a serious programmer error.

Yes, but the point is more general: Trying to delete an "in use"
mutex is a serious programmer error. A mutex in the locked state is
obviously in use, but it is a mistake to reason that a mutex in the
unlocked state is not in use.

> According to the library's spec, delete may be called at any time, by
> any thread, and it is the user's responsibility to return an error and
> leave the mutex untouched if the mutex is currently locked...

Broken. The danger isn't when deletion fails because the mutex is
locked, but when deletion succeeds because the mutex is unlocked -- but
is still in use.

--
Eric.Sosman@sun.com


== 5 of 15 ==
Date: Wed, Oct 28 2009 9:50 am
From: Måns Rullgård


David Schwartz <davids@webmaster.com> writes:

> On Oct 28, 6:27 am, Noob <r...@127.0.0.1> wrote:
>
>> But this library has specific requirements for the delete function:
>>
>> If delete is called on a locked mutex, the function must return an error
>> code to signal the error to the function's caller.
>
> That is, IMO, fundamentally busted behavior, unless it only means
> locked by the calling thread.

I agree. I wouldn't go anywhere near that library. Find another one
written by someone with half a brain.

That said, you could use pthread_mutex_trylock() to find out whether
or not the muxtex is locked.

--
Måns Rullgård
mans@mansr.com


== 6 of 15 ==
Date: Wed, Oct 28 2009 9:58 am
From: Noob


Eric Sosman wrote:

> Noob wrote:
>
>> David Schwartz wrote:
>>
>>> Noob wrote:
>>>
>>>> But this library has specific requirements for the delete function:
>>>>
>>>> If delete is called on a locked mutex, the function must return an
>>>> error code to signal the error to the function's caller.
>>>
>>> That is, IMO, fundamentally busted behavior, unless it only means
>>> locked by the calling thread.
>>
>> Could you expand on /why/ you think it is busted behavior?
>> (I need ammo to try to convince the library authors.)
>>
>> The exact requirements are:
>>
>> 1) Return an error when attempting to delete "a mutex currently owned by
>> another thread".
>
> This is broken, period. Suppose thread T1 tries to delete the
> mutex and discovers (somehow) that it is locked by T2. T1 leaves
> the mutex alone, the deletion attempt returns an error, and all is
> well.

Except that one is left to wonder why T1 ever thought it would be a good
idea to delete the mutex...

> But suppose T1 comes along at a moment when the mutex is unlocked,
> and succeeds in deleting it. Two clock cycles later, T2 tries to lock
> the destroyed mutex, and the fertilizer hits the fan.

The library also requires "return an error when attempting to lock an
uninitialized mutex".

I don't know what they do in that library... Perhaps this explains why
they do not provide the source code.

> The fact that T1
> found the mutex unlocked is no proof that the mutex is "unused," or
> that T2 might not attempt to use it again.

Obviously.

> If T1 deletes a mutex that T2 might still want to use, the
> application is broken. If T1 can find the mutex locked by T2, it
> must be the case that T2 still wants to use it. Therefore the mere
> possibility that delete-while-locked-elsewhere could occur is proof
> that the design is broken.
>
>> 2) Return an error when attempting to delete "a mutex currently owned by
>> the calling thread".
>
> This isn't quite as clear-cut, but it still seems dubious.
>
>> [...]
>> Trying to delete a locked mutex sounds like a serious programmer error.
>
> Yes, but the point is more general: Trying to delete an "in use"
> mutex is a serious programmer error. A mutex in the locked state is
> obviously in use, but it is a mistake to reason that a mutex in the
> unlocked state is not in use.

Are there situations, algorithms, where many mutexes are created then
deleted (in a loop). It seems to me that mutexes are typically long
lived objects, initialized at application start-up, and destroyed
shortly before termination.

>> According to the library's spec, delete may be called at any time, by
>> any thread, and it is the user's responsibility to return an error and
>> leave the mutex untouched if the mutex is currently locked...
>
> Broken. The danger isn't when deletion fails because the mutex is
> locked, but when deletion succeeds because the mutex is unlocked -- but
> is still in use.

Sigh.

Regards.


== 7 of 15 ==
Date: Wed, Oct 28 2009 10:06 am
From: Noob


Måns Rullgård wrote:

> David Schwartz wrote:
>
>> Noob wrote:
>>
>>> But this library has specific requirements for the delete function:
>>>
>>> If delete is called on a locked mutex, the function must return an error
>>> code to signal the error to the function's caller.
>>
>> That is, IMO, fundamentally busted behavior, unless it only means
>> locked by the calling thread.
>
> I agree. I wouldn't go anywhere near that library. Find another one
> written by someone with half a brain.

I have no such freedom. I must use that proprietary library.
It is a MAFIAA requirement (DVB Conditional Access).

> That said, you could use pthread_mutex_trylock() to find out whether
> or not the mutex is locked.

Any way I slice it, their requirement seems to impose high overhead
on lock and unlock operations for no gain whatsoever.

Regards.


== 8 of 15 ==
Date: Wed, Oct 28 2009 10:22 am
From: Dave Butenhof


Noob wrote:
> [ Cross-posted to c.p.t and c.u.p ]
>
> Hello,
>
> I'm using a proprietary library (no source code) which requires the user
> to provide 4 mutex-related functions (create, delete, lock, unlock).
>
> AFAICT, if I were using a POSIX OS, I could make trivial wrappers around
>
> pthread_mutex_init
> pthread_mutex_destroy
> pthread_mutex_lock
> pthread_mutex_unlock
>
> But this library has specific requirements for the delete function:
>
> If delete is called on a locked mutex, the function must return an error
> code to signal the error to the function's caller.
>
> However, the documentation for pthread_mutex_destroy explicitly states:
> http://www.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html
>
> """
> It shall be safe to destroy an initialized mutex that is unlocked.
> Attempting to destroy a locked mutex results in undefined behavior.
> """
>
> This means that my delete function can't just call pthread_mutex_destroy
> because I would invoke UB if the mutex is locked, and I wouldn't be able
> to return the requested error code, right?

Strictly speaking, what this means is that POSIX doesn't *require* an
implementation to know whether the mutex is already locked.

That's due to concerns over the performance of tracking mutex ownership
on some platforms... as well as (as you mention below) concerns that all
implementations be penalized by extra code that only helps broken
applications. Correct (production level) code doesn't destroy a mutex to
which any other thread might hold or request a reference. And as already
mentioned in a reply, once you get to that point you're lost anyway
because there are plenty of errors you won't be able to catch.

> So... Does this mean I have to keep track whether the mutex is locked?
> (It would appear so.)
>
> Or perhaps I could mess with the OS code? (shudder)
>
> I'd like to tell the library author that it is unreasonable to impose
> overhead on every lock and unlock operation just to catch an obvious (?)
> programming error on delete. What do you think?
>
> N.B. the library requires mutex with recursive semantic.

This requirement probably simplifies things. You really want a recursive
POSIX mutex (mutex type PTHREAD_MUTEX_RECURSIVE), and you have to track
mutex ownership to do that. Regardless of formal requirements, it's
highly unlikely a platform implementing recursive mutexes wouldn't
report EBUSY on an attempt to unlock a locked mutex.

But, again, your requirement is beyond the scope of the API standard and
into implementation defined territory. You need to check the
documentation for the platform(s) you care about to see what they'll
guarantee, or "roll your own".

If you're interested in a particular platform, this should be simple. If
you're interested in general portability, you'll pretty much need to
assume the answer is "roll your own" or "declare defeat and give up".


== 9 of 15 ==
Date: Wed, Oct 28 2009 10:50 am
From: Eric Sosman


Noob wrote:
> Eric Sosman wrote:
>
>> Noob wrote:
>>
>>> David Schwartz wrote:
>>>
>>>> Noob wrote:
>>>>
>>>>> But this library has specific requirements for the delete function:
>>>>>
>>>>> If delete is called on a locked mutex, the function must return an
>>>>> error code to signal the error to the function's caller.
>>>> That is, IMO, fundamentally busted behavior, unless it only means
>>>> locked by the calling thread.
>>> Could you expand on /why/ you think it is busted behavior?
>>> (I need ammo to try to convince the library authors.)
>>>
>>> The exact requirements are:
>>>
>>> 1) Return an error when attempting to delete "a mutex currently owned by
>>> another thread".
>> This is broken, period. Suppose thread T1 tries to delete the
>> mutex and discovers (somehow) that it is locked by T2. T1 leaves
>> the mutex alone, the deletion attempt returns an error, and all is
>> well.
>
> Except that one is left to wonder why T1 ever thought it would be a good
> idea to delete the mutex...

Right: This can only happen if there's something fundamentally
wrong with the T1/T2 program itself. The program is still using
something that it thinks it doesn't need; put differently, the
program believes that `X & !X' is true. A library that tries to
assist the program in such beliefs is at best quixotic.

>> But suppose T1 comes along at a moment when the mutex is unlocked,
>> and succeeds in deleting it. Two clock cycles later, T2 tries to lock
>> the destroyed mutex, and the fertilizer hits the fan.
>
> The library also requires "return an error when attempting to lock an
> uninitialized mutex".

Does it also require an error for attempting to lock a chunk of
memory containing random garbage that just sort of happens to look
like a mutex? What other miracles does this library demand?

No, look, seriously: malloc some memory, initialize a mutex M1 in
it, and let T1 and T2 use it for a while. Now T1 decides (erroneously)
that M1 is no longer needed, so it deletes it and frees the memory.
Now call malloc again, get the same chunk of memory back, and create a
brand-new mutex M2 at the same address where the now-defunct M1 used
to live. When T2 tries to lock M1, supplying an address that points to
the perfectly valid M2, you're supposed to be able to detect it?

Lotsa luck ...

> Are there situations, algorithms, where many mutexes are created then
> deleted (in a loop). It seems to me that mutexes are typically long
> lived objects, initialized at application start-up, and destroyed
> shortly before termination.

In an object-oriented design you might have a mutex inside each
instance of some class or other, protecting some of the instance's
own internals. If you create and destroy lots of instances of the
class, you'll create and destroy a lot of mutexes. (Mutices?)

This is pretty common in classes that represent containers or
collections or things of that sort, that tend to be fairly long-lived.
But even a short-lived object might need a mutex if it needs to preserve
an invariant involving two or more fields, or a field that can't be
updated atomically. You might have a Color class, for example, that
allows you to get/set any of RGB, HSV, CMYK, ... and needs to keep
all the representations in agreement; such a class might well have a
private mutex to serialize the getters and setters.

The good news on that sort of mutex, I guess, is that it's often
"internal" to the class, not accessible to J. Random Outsider. It
lives and dies with the class instance, so whenever it's safe to
delete the object it's also safe to delete the object's private mutex.

--
Eric.Sosman@sun.com


== 10 of 15 ==
Date: Wed, Oct 28 2009 11:18 am
From: scott@slp53.sl.home (Scott Lurndal)


=?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= <mans@mansr.com> writes:
>David Schwartz <davids@webmaster.com> writes:
>
>> On Oct 28, 6:27 am, Noob <r...@127.0.0.1> wrote:
>>
>>> But this library has specific requirements for the delete function:
>>>
>>> If delete is called on a locked mutex, the function must return an error
>>> code to signal the error to the function's caller.
>>
>> That is, IMO, fundamentally busted behavior, unless it only means
>> locked by the calling thread.
>
>I agree. I wouldn't go anywhere near that library. Find another one
>written by someone with half a brain.
>
>That said, you could use pthread_mutex_trylock() to find out whether
>or not the muxtex is locked.
>

My first thought too, use _trylock in the delete function. However, that
won't work for recursive mutexes, because it won't fail if the current thread
has the mutex.

scott


== 11 of 15 ==
Date: Wed, Oct 28 2009 12:57 pm
From: Måns Rullgård


scott@slp53.sl.home (Scott Lurndal) writes:

> =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= <mans@mansr.com> writes:
>>David Schwartz <davids@webmaster.com> writes:
>>
>>> On Oct 28, 6:27 am, Noob <r...@127.0.0.1> wrote:
>>>
>>>> But this library has specific requirements for the delete function:
>>>>
>>>> If delete is called on a locked mutex, the function must return an error
>>>> code to signal the error to the function's caller.
>>>
>>> That is, IMO, fundamentally busted behavior, unless it only means
>>> locked by the calling thread.
>>
>>I agree. I wouldn't go anywhere near that library. Find another one
>>written by someone with half a brain.
>>
>>That said, you could use pthread_mutex_trylock() to find out whether
>>or not the muxtex is locked.
>>
>
> My first thought too, use _trylock in the delete function. However,
> that won't work for recursive mutexes, because it won't fail if the
> current thread has the mutex.

Then don't use recursive mutexes. Using recursing mutexes is also a
strong indicator of design flaws.

--
Måns Rullgård
mans@mansr.com


== 12 of 15 ==
Date: Wed, Oct 28 2009 3:03 pm
From: scott@slp53.sl.home (Scott Lurndal)


=?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= <mans@mansr.com> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>
>> =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= <mans@mansr.com> writes:
>>>David Schwartz <davids@webmaster.com> writes:
>>>
>>>> On Oct 28, 6:27 am, Noob <r...@127.0.0.1> wrote:
>>>>
>>>>> But this library has specific requirements for the delete function:
>>>>>
>>>>> If delete is called on a locked mutex, the function must return an error
>>>>> code to signal the error to the function's caller.
>>>>
>>>> That is, IMO, fundamentally busted behavior, unless it only means
>>>> locked by the calling thread.
>>>
>>>I agree. I wouldn't go anywhere near that library. Find another one
>>>written by someone with half a brain.
>>>
>>>That said, you could use pthread_mutex_trylock() to find out whether
>>>or not the muxtex is locked.
>>>
>>
>> My first thought too, use _trylock in the delete function. However,
>> that won't work for recursive mutexes, because it won't fail if the
>> current thread has the mutex.
>
>Then don't use recursive mutexes. Using recursing mutexes is also a
>strong indicator of design flaws.
>

Talk to the vendor of the proprietary library used by the OP. They're
the ones that require recursive mutexes - I don't believe they should be
used either.

scott


== 13 of 15 ==
Date: Wed, Oct 28 2009 3:17 pm
From: "Chris M. Thomasson"


"Noob" <root@127.0.0.1> wrote in message news:hc9t7d$8c1$1@aioe.org...
> Eric Sosman wrote:
>
>> Noob wrote:
>>
>>> David Schwartz wrote:
>>>
>>>> Noob wrote:
>>>>
>>>>> But this library has specific requirements for the delete function:
>>>>>
>>>>> If delete is called on a locked mutex, the function must return an
>>>>> error code to signal the error to the function's caller.
>>>>
>>>> That is, IMO, fundamentally busted behavior, unless it only means
>>>> locked by the calling thread.
>>>
>>> Could you expand on /why/ you think it is busted behavior?
>>> (I need ammo to try to convince the library authors.)
>>>
>>> The exact requirements are:
>>>
>>> 1) Return an error when attempting to delete "a mutex currently owned by
>>> another thread".
>>
>> This is broken, period. Suppose thread T1 tries to delete the
>> mutex and discovers (somehow) that it is locked by T2. T1 leaves
>> the mutex alone, the deletion attempt returns an error, and all is
>> well.
>
> Except that one is left to wonder why T1 ever thought it would be a good
> idea to delete the mutex...
>
>> But suppose T1 comes along at a moment when the mutex is unlocked,
>> and succeeds in deleting it. Two clock cycles later, T2 tries to lock
>> the destroyed mutex, and the fertilizer hits the fan.
>
> The library also requires "return an error when attempting to lock an
> uninitialized mutex".
>
> I don't know what they do in that library... Perhaps this explains why
> they do not provide the source code.
[...]

Man! This sucks!! Anyway, I believe you could meet all the requirements,
however, it's not going to be pretty. Here is what I hacked together for you
so far:


http://cpt.pastebin.com/f540aaef5


This is crowbar proof except for the case when a thread unlocks a mutex that
it did not previously locked. This can be handled, but it will add even more
overhead. All other cases are handled gracefully. Please take a look at the
sample application. It should compile for you. I create N threads which sit
in a loop and basically create, lock, unlock and destroy a global mutex.
Conflicts are resolved by using a reference count and external hash lock
table.


Please study the code and tell me if it works for that nasty library you
have to work with.

== 14 of 15 ==
Date: Wed, Oct 28 2009 5:55 pm
From: David Schwartz


On Oct 28, 8:04 am, Noob <r...@127.0.0.1> wrote:

> >> If delete is called on a locked mutex, the function must return an error
> >> code to signal the error to the function's caller.

> > That is, IMO, fundamentally busted behavior, unless it only means
> > locked by the calling thread.

> Could you expand on /why/ you think it is busted behavior?
> (I need ammo to try to convince the library authors.)

Either they rely on this behavior or they don't. If they don't rely on
it, why do they make you implement it? If they do rely on it, what
happens when one thread destroys a mutex a split-second before another
thread acquires it?

The only way to make that sensible is to insist you detect an attempt
to lock a destroyed mutex. However, think about what this means. It
means you can never, ever reuse a mutex's identifier. It means a mutex
cannot be a pointer to a structure that is freed when that mutex
ceases to exist.

Basically, it means the library plans to use a mutex among threads
that cannot even agree on the lifespan of the mutex, and that's
nonsensical because, among other reasons, they have to agree on the
lifespan of what the data protects anyway.

> Since a locked mutex is so either by the calling thread, or by another
> thread (duh!) it seems the two requirements boil down to:
>
> Return an error (and, I assume, leave the mutex alone) when attempting
> to delete a locked mutex.

Even if it's locked by the calling thread?

> > Since the mutex is recursive, one of two things are the case:

> > 1) The requirement only applies if the calling thread holds the lock
> > on the mutex, in which case you have to keep track of the lock count
> > anyway. (Otherwise, how would you know what to do in the unlock
> > operation?) The library is being reasonable, though quirky.

> The OS I'm using provides recursive mutex. Therefore, I don't think I
> have to deal with lock counts, as the OS takes care of that.

It's not his fault you're using mutexes that don't provide his
semantics when his semantics are reasonable. If he had a requirement
that was specific to a mutex held by the calling thread for a
recursive mutex, the semantics would be reasonable (ignoring the
silliness of recursive mutexes to begin with) though odd. Your best
bet would be to use non-recusive mutexes (if available, otherwise, use
recursive mutexes but don't use them recusively) and implement the
recursion yourself.

It's not unusual to need different recursion semantics and have to
implement your own recursion even when the platform supplies recursive
mutexes. For example, someone might insist on reader/writer mutexes
where the write lock was recursive. That's not totally unreasonable,
but likely your platform doesn't provide them, so you would have to do
code it yours.

> Trying to delete a locked mutex sounds like a serious programmer error.

If it's locked by another thread, it must be. If it's locked by the
calling thread, it could be defined either way by the mutex semantics.
Some typical mutexes either say it will succeed and delete the mutex
(sort of unlocking it), some say it is undefined. Requiring specific
behavior in this case is a somewhat bad thing because it means custom
code will be needed in an operation that is best handled by the
platform's optimized code.

As you see, asking for special semantics when another thread holds the
mutex is fundamentally busted.

> Mutex destruction (and creation) should be done in well-defined parts of
> the application, when one can be sure the mutex is not in use anymore,
> right?

Well, it depends on the way you use mutexes. You can have mutexes
associated with objects dynamically created and destroyed all over the
place. But this will not work out sanely unless an "outer
synchronization" protects the public visibility of objects.

Create object with mutex, acquire global mutex, make object visible to
other threads. Acquire global mutex, find object, lock object, remove
object from collection, unlock global mutex, unlock object, delete
object. That kind of thing.

> > 2) The requirement applies even if another thread holds the mutex.
> > This is a real pain to implement, and the requirement is fundamentally
> > busted.

> According to the library's spec, delete may be called at any time, by
> any thread, and it is the user's responsibility to return an error and
> leave the mutex untouched if the mutex is currently locked...

This will require giving each mutex a 64-bit identifier that is looked
up in a global hash table protected by a global mutex. Mutex
identifiers can never be reused. YUCK!

DS


== 15 of 15 ==
Date: Wed, Oct 28 2009 7:26 pm
From: Eric Sosman


Noob wrote:
> [...]
> I have no such freedom. I must use that proprietary library.
> It is a MAFIAA requirement (DVB Conditional Access).

The only MAFIAA references I find are to the merger of
the Motion Picture Association of America (MPAA) with the
Recording Industry Association of America (RIAA) to form the
Music And Film Industry Association of America (MAFIAA). The
merger was announced on April First, 2006. The date and the
acronym suggest some amount of spoofery ...

And DVB must be either the Democratic Voice of Burma or
something to do with Victoria Beckham, aka Posh Spice.

--
Eric Sosman
esosman@ieee-dot-org.invalid

==============================================================================
TOPIC: clock attribute of a condvar
http://groups.google.com/group/comp.programming.threads/t/0bd8148213fe6b17?hl=en
==============================================================================

== 1 of 2 ==
Date: Wed, Oct 28 2009 10:30 am
From: Bartlomiej Jacek Kubica

Dear David,

Thanks a lot for your answer.

On Sat, 24 Oct 2009, David Schwartz wrote:

> ---
> It's useful to switch a condvar from wall time to elapsed time. This
> makes the condvar usable even against jumps in system time without ill
> effects.

OK, so what are possible values of this attribute? Is it something more
than CLOCK_REALTIME and CLOCK_MONOTONIC?

>> We can do a pthread_cond_timedwait(), but we do not any explicit clock id
>> to do that.
>
> If pthread_cond_timedwait took an explicit clock ID, then a condvar
> would have to support waits against system time and waits against
> elapsed time. This could mean that a change in the system time would
> change the thread wakeup order. That would be a bizarre requirement.
> So it makes more sense for the clock ID to be a condvar attribute.

But what is specified is an absolute deadline. So changing the time on the
clock would change the wakeup time.
Or do you mean creating a specific ``logical'' clock and not manipulating
its time even if the ``main'' system clock is being tuned?

> ---
> Because they don't have spurious (or apparently spurious) wakeups. You
> have to wait for a condition variable in a loop. If the wait took a
> delta time (wait up to 5 seconds), you would have to recalculate the
> wait time each pass, which would be irritating. So condvars take a
> fixed wakeup time, so you can keep calling them in a loop until either
> the thing you want happens or a timeout occurs.

They don't, indeed.
So, how does e.g. pthread_mutex_timedlock() behave when time on the
clock is changed while the thread is waiting?

> POSIX explicitly allows completely spurious wakeups. But you can also
> get an "apparently spurious" wakeup because another thread consumed
> the event that woke you up before you got to it.

Yes, indeed. I should have thought about it.

> ---
>
> Other synchronization tools don't take an absolute wakeup time. It's

Don't they? AFAIK we always specify the *absolute* time, not the time
interval - for pthread_mutex_timedlock(), pthread_rwlock_timedrdlock(),
sem_timedwiait(), etc.
Isn't it so?

Thanks and best regards
Bartlomiej


== 2 of 2 ==
Date: Wed, Oct 28 2009 6:17 pm
From: David Schwartz


On Oct 28, 10:30 am, Bartlomiej Jacek Kubica
<bkub...@mion.elka.pw.edu.pl> wrote:

> Dear David,

> Thanks a lot for your answer.

You're welcome.

> OK, so what are possible values of this attribute? Is it something more
> than CLOCK_REALTIME and CLOCK_MONOTONIC?

Those are the useful options on typical systems.

> >> We can do a pthread_cond_timedwait(), but we do not any explicit clock id
> >> to do that.

> > If pthread_cond_timedwait took an explicit clock ID, then a condvar
> > would have to support waits against system time and waits against
> > elapsed time. This could mean that a change in the system time would
> > change the thread wakeup order. That would be a bizarre requirement.
> > So it makes more sense for the clock ID to be a condvar attribute.

> But what is specified is an absolute deadline. So changing the time on the
> clock would change the wakeup time.

Yes, but not the *order* of wakeup.

> > Because they don't have spurious (or apparently spurious) wakeups. You
> > have to wait for a condition variable in a loop. If the wait took a
> > delta time (wait up to 5 seconds), you would have to recalculate the
> > wait time each pass, which would be irritating. So condvars take a
> > fixed wakeup time, so you can keep calling them in a loop until either
> > the thing you want happens or a timeout occurs.

> They don't, indeed.
> So, how does e.g. pthread_mutex_timedlock() behave when time on the
> clock is changed while the thread is waiting?

It is not affected because the time is an amount of time to wait. So
there's no issue.

But suppose I want to wait 5 seconds for a cv. I have to calculate an
absolute time because I may need to wait in a loop and don't want to
wait 5 seconds each time. But if I do that, what happens if the time
jumps back 5 seconds? Then I wait too long.

> > Other synchronization tools don't take an absolute wakeup time. It's

> Don't they? AFAIK we always specify the *absolute* time, not the time
> interval - for pthread_mutex_timedlock(), pthread_rwlock_timedrdlock(),
> sem_timedwiait(), etc.
> Isn't it so?

You're right! I'm so used to calling them through wrappers that take
relative times. Yes, I agree, it would be handy to be able to set them
to CLOCK_MONOTONIC.

DS

==============================================================================
TOPIC: syscalls
http://groups.google.com/group/comp.programming.threads/t/7db32595fcbaa497?hl=en
==============================================================================

== 1 of 3 ==
Date: Wed, Oct 28 2009 12:09 pm
From: "Bill Cunningham"


What syatem calls and posix family functions would be needed to work
with NNTP? Networking obviously.

Bill


== 2 of 3 ==
Date: Wed, Oct 28 2009 3:23 pm
From: "Chris M. Thomasson"


"Bill Cunningham" <nospam@nspam.invalid> wrote in message
news:4ae896e6$0$26501$bbae4d71@news.suddenlink.net...
> What syatem calls and posix family functions would be needed to work
> with NNTP? Networking obviously.

http://www.opengroup.org/onlinepubs/7990989775/xns/syssocket.h.html

http://www.opengroup.org/onlinepubs/7990989775/xsh/aio.h.html

http://www.opengroup.org/onlinepubs/7990989775/xsh/select.html

http://www.opengroup.org/onlinepubs/7990989775/xsh/poll.html

http://www.kegel.com/c10k.html

ect...


== 3 of 3 ==
Date: Wed, Oct 28 2009 6:10 pm
From: "Bill Cunningham"

"Chris M. Thomasson" <no@spam.invalid> wrote in message
news:on4Gm.113717$944.60201@newsfe09.iad...

http://www.opengroup.org/onlinepubs/7990989775/xns/syssocket.h.html
>
> http://www.opengroup.org/onlinepubs/7990989775/xsh/aio.h.html
>
> http://www.opengroup.org/onlinepubs/7990989775/xsh/select.html
>
> http://www.opengroup.org/onlinepubs/7990989775/xsh/poll.html
>
> http://www.kegel.com/c10k.html

Thanks I'll start out looking at these. A client is what I'm interested
in.

Bill


==============================================================================

You received this message because you are subscribed to the Google Groups "comp.programming.threads"
group.

To post to this group, visit http://groups.google.com/group/comp.programming.threads?hl=en

To unsubscribe from this group, send email to comp.programming.threads+unsubscribe@googlegroups.com

To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.programming.threads/subscribe?hl=en

To report abuse, send email explaining the problem to abuse@googlegroups.com

==============================================================================
Google Groups: http://groups.google.com/?hl=en

No comments: