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
