This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PR18457] Don't require rtld lock to compute DTV addr for static TLS


On Mon, 2015-06-22 at 03:39 -0300, Alexandre Oliva wrote:
> >> > We implement POSIX for users of glibc, but we do not implement on top of
> >> > POSIX inside of glibc
> 
> >> Is this documented anywhere?
> 
> > https://sourceware.org/glibc/wiki/Concurrency
> > says that we're using the C11 memory model.
> 
> Well, that's not exactly a true statement ATM.  We are *aiming* at it,
> but there are tons of code in GNU libc that aren't quite there yet.

Sure.

> 
> > Thus, there will be synchronizes-with (and thus happens-before) edges
> > between a release of a particular mutex instance and a subsequent
> > acquisition of the *same* mutex instance.   This creates a total order
> > on each particular mutex instance, but there is no happens-before
> > enforces with unrelated release or acquire operations (e.g., on
> > different mutex instances, atomics, ...).
> 
> ... because those don't introduce a synchronization with the release
> sequence that precedes releasing that specific mutex, whereas a memory
> fence would have more pervasive synchronization effects.

Fences create synchronizes with in combination with other atomic
accesses sequenced after them (in case of release fences, otherwise
sequenced before them).  See 7.17.4p1-4 in C11 (N1570 is a draft) for
how that's worded there.

Also, to see this in action, you can try the example below at
http://svr-pes20-cppmem.cl.cam.ac.uk/cppmem/ using a browser that has
javascript enabled:

int main() {
  atomic_int x = 0;
  atomic_int unrelated = 0;
  int y = 0;
  {{{ {
     y = 1;
     // won't work; will have data races:
     // unrelated.store(23, memory_order_release);
     // does work:
     atomic_thread_fence(memory_order_release);
     x.store(1, memory_order_relaxed);
  } ||| {
     r1 = x.load(memory_order_acquire).readsvalue(1);
     r2 = y.readsvalue(1);
  } }}};

This tries to access the non-atomic initialization of y safely by using
an atomic flag x.  The readsvalue calls are assertions basically, to
constrain which executions the cppmem tool looks at.
Using the release store instead of the release fence will result in data
races.  The plot at the bottom right shows the relationships that matter
in the possible executions found by the tool.

> Is this what
> you meant with "In C11, there's a distinction between a release-MO fence
> and a mutex unlock operation (i.e., a release-MO store)"?

Yes, basically.  More specifically, the difference between the fence and
a release store in cases similar to the example above.  And, as a
result, that a mutex unlock has not the same synchronization effects as
a release fence.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]