On Sat, 19 Mar 2016, Tobias Ulmer wrote:
> On Fri, Mar 18, 2016 at 09:01:00PM +0000, Kári Tristan Helgason wrote:
> > Ok, that makes sense. 
> > 
> > Can you explain why you think it's better to return EBUSY rather than
> > blocking on the mutex in -destroy, instead of relying on the user checking 
> > the
> > return code?
> 
> Well, lets start at the beginning. The program you showed isn't
> correctly using barrier_destroy according to the latest Posix standard:
...
> > The results are undefined if pthread_barrier_destroy() is called when
> > any thread is blocked on the barrier, or if this function is called with
> > an uninitialized barrier.
> 
> They removed the EBUSY requirement and made it optional. We try to keep
> that behavior because it's a sensible thing to do that costs little to
> implement.
> 
> What we can't do is invent our own semantics and make 
> pthread_barrier_destroy() wait. That's clearly not acceptable.

And yet, that's what everyone does.

There's a requirement on *_wait() that when the count is reached that it 
unblocks the threads in the barrier.  Since they're unblocked, any one 
thread that returns from *_wait() may call *_destroy(), *including the 
first one*!

If you look at how freebsd and glibc implement barriers, you'll see they 
implement that requirement by having *_destroy() wait as *_wait() callers 
count themselves out, with the *last* thread to return from *_wait() 
unblocking the *_destroy().  So yes, *_destroy() can wait.

The alternative would be to make it so that no thread can return from 
*_wait() as long as any other thread in *_wait() might still access the 
pthread_barrier_t or anything destroyed by *_destroy().  I belive that to 
implement that synchronization in the presence of signals would require 
the core of *_wait() to be a syscall and have the kernel do all the 
tracking.  Even futexes aren't enough for that.


Philip Guenther

Reply via email to