This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Synchronizing auxiliary mutex data
- From: Torvald Riegel <triegel at redhat dot com>
- To: Andreas Schwab <schwab at suse dot de>
- Cc: libc-alpha at sourceware dot org
- Date: Tue, 20 Jun 2017 12:45:51 +0200
- Subject: Re: Synchronizing auxiliary mutex data
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=triegel at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 8FD0080F7D
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8FD0080F7D
- References: <mvmtw3cflej.fsf@suse.de> <1497896660.18410.15.camel@redhat.com> <mvm1sqfdq86.fsf@suse.de> <1497952837.18410.24.camel@redhat.com> <mvmk247c5vl.fsf@suse.de>
On Tue, 2017-06-20 at 12:26 +0200, Andreas Schwab wrote:
> On Jun 20 2017, Torvald Riegel <triegel@redhat.com> wrote:
>
> > On Tue, 2017-06-20 at 10:21 +0200, Andreas Schwab wrote:
> >> On Jun 19 2017, Torvald Riegel <triegel@redhat.com> wrote:
> >>
> >> > * We write to __owner only when in the critical section, with relaxed
> >> > MO; we write TID after lock and 0 before unlock. Those writes are
> >> > ordered by the critical section.
> >>
> >> How does it guarantee that the thread calling pthread_mutex_lock see the
> >> change that the thread calling pthread_mutex_unlock did?
> >
> > I suppose you are referring to the writes? If so, because of the
> > unlock/lock synchronization.
>
> But the fields are independent of the lock field. How do the two cpus
> keep their caches coherent?
You were talking about ordering of the writes. to __owner. This happens
through the happens-before established through the unlock->lock
synchronization. Specifically, in unlock:
store(&owner, 0, mo_relaxed) ->sb store(&lock, 0, mo_release)
and in lock:
cas(&lock, expect==0, new==1, mo_acquire)==success
->sb store(&owner, TID, mo_relaxed)
where ->sb is sequenced-before, so essentially program order. The CAS
that succeeds is a load too that reads-from the store in unlock that
writes 0. Because the reads-from is on an release-store / acquire-load
pair, this creates an inter-thread-happens-before relation, which in
turn enforces that the store before unlock happens-before the store
after lock.
If you are concerned about the loads from __owner outside of the
critical sections, then see my first reply. The coherence rules in the
C11 memory model ensure that you'll read from your own store or more
recent, or the initial store and more recent. Whenever you read from
another more recent store, this store will not have written your TID.
If you want to become more familiar with the details, I'd suggest to
play with a few examples in the cppmem tool. This will show you what is
going on, and given that it's interactice, you can explore how the model
works quite well.
What happens on the particular HW architecture is then really just a
mapping from the C11 memory model.