[cpp-threads] Re: Does pthread_mutex_lock() have release emantics?

Dave Butenhof david.butenhof at hp.com
Mon May 9 14:28:38 BST 2005


Boehm, Hans wrote:

>[Dave - if you would like to be added to the C++ threads/memory model
>list, I'm sure that wouldn't be a problem, and I think it would
>help us.]
>  
>
I'm certainly interested in helping, although little of my time is 
actually under my control these days. ;-)

>No. I really meant pthread_mutex_lock(&l), where l is a brand
>new pthread_mutex_t.
>  
>
"Brand new", as in not the same as the original pthread_mutex_lock(&l)? 
That's not what your description of the algorithm suggested to me, but 
otherwise I don't understand what you mean to imply by "brand new". 
Perhaps you could start again with a more consistent notation?

>>>For this to work, the pthread_mutex_lock() call must have RELEASE 
>>>semantics, instead of its usual acquire semantics.  (And
>>>pthread_mutex_trylock() must have acquire semantics when
>>>it FAILS.)
>>>      
>>>
>>Also, for what it's worth, POSIX specifically denies any guarantee of 
>>memory synchronization when a function FAILS.
>>    
>>
>Alexander Terekhov also pointed that out.  I agree.
>
>But I'm not convinced it's a fundamental issue.  Add an otherwise
>irrelevant call that "synchronizes memory" after the trylock in
>thread 2.  This code still breaks if the initialization code
>in thread 1 is executed after the pthread_mutex_lock().  Hence
>pthread_mutex_lock still needs release semantics in addition to
>its usual acquire semantics.
>  
>
Indeed; the current wording of the standard clearly requires full 
barrier behavior for each memory synchronization operation. There's no 
concept of ordering, unlock to lock or anything else. Each operation, 
independently, "synchronizes memory". Period.

>>>I think a reasonable reading of the pthreads standard would pretty 
>>>clearly conclude that this should work.  (Of course nobody would 
>>>recommend the programming style.)
>>>      
>>>
>>Aside from the ownership violation, yes, it would have been legal. POSIX memory synchronization is phrased very simply -- while nobody who understood the issues was entirely happy with that, it was sufficient, and simple enough to explain to most anyone. We have a much wider audience of far more sophisticated programmers now; most everyone understands at least the basics of concurrency and many have a reasonable grasp of the machine-level basis.
>>
>>So section 4.l0 of the UNIX spec says simply that "The following 
>>functions synchronize memory with respect to other threads:", not "a 
>>pthread_mutex_unlock in thread A makes previous writes from thread A 
>>visible to a thread B subsequently completing a pthread_mutex_lock 
>>operation", etc. As you infer, the standard clearly and unambiguously 
>>requires acquire/release for every one of the operations on which you 
>>can portably rely for memory synchronization. Unfortunate... 
>>but, again, simple, and sufficient. (At least for coarse grain concurrency.)
>>    
>>
>My mistaken impression was that there is no observable difference
>between this and the implementation in which lock has acquire semantics
>and unlock has release semantics.  I stil believe that's true in the
>absence of trylock.  I think the (patched version of the) above
>example is a counterexample with trylock.
>  
>
In theory there's a big difference. But, yeah; in practice it's hard to 
construct a conforming application that can exploit the differences in 
the case of a mutex. While that might be enough wiggle room to tighten 
the standard, I'm wary of that old advice about the ingenuity of fools. 
Incompatible changes that break something users (or vendors) see as 
useful generally does more damage than good.

>>Yes, "happens-before" type relationships are critical for a well-defined 
>>and useful synchronization protocol. Like I said, Alexander had made a 
>>start at a proposal for this. I think his initial proposal had a lot of 
>>problems, but the basic direction was a good start.
>>    
>>
>Interestingly, I think in the absence of trylock and atomic operations
>I think that isn't clear.  I think in that restricted environment,
>a refined version of the Posix formulation is probably equivalent.
>But trylock is there, and that's probably where we'll end up.
>I'd still like to convince myself that the added complexity is
>necessary, though.
>  
>
pthread_mutex_trylock() is not special. It's subject to the POSIX rules 
that failure need not provide any synchronization guarantee, and EBUSY 
('already locked') is clearly defined as "failure". So in terms of 
memory synchronization, it is just a mutex lock operation with an 
additional error condition.

>>C++ can start from scratch and "get it right", but you need to keep your eyes open to the real-world constraints on implementations and applications. A C++ application hosted on a conforming POSIX application may be over-synchronized, but should work, and it would provide a lot of incentive to fix POSIX.
>>    
>>
>Agreed. I would certainly like to see us avoid breaking pthreads applications. I'm not sure whether breaking code like the above example is a problem though.
>  
>
That is always the critical question -- what are we willing to break in 
order to improve things? How many people depend on hacky "dark corners" 
of the current standard and will care much more that the new standard 
breaks their previously conforming code than that there's now a better way.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: david.butenhof.vcf
Type: text/x-vcard
Size: 476 bytes
Desc: not available
Url : http://shadbolt.decadentplace.org.uk/pipermail/cpp-threads/attachments/20050509/00af253b/david.butenhof.vcf


More information about the cpp-threads mailing list