This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Thread-, Signal- and Cancellation-safety documentation
- From: Torvald Riegel <triegel at redhat dot com>
- To: Rich Felker <dalias at aerifal dot cx>
- Cc: Alexandre Oliva <aoliva at redhat dot com>, libc-alpha at sourceware dot org
- Date: Wed, 05 Jun 2013 20:14:13 +0200
- Subject: Re: Thread-, Signal- and Cancellation-safety documentation
- References: <or38v6azhn dot fsf at livre dot home> <1368788184 dot 3054 dot 3161 dot camel at triegel dot csb> <orehd3h2j4 dot fsf at livre dot home> <1369588322 dot 16968 dot 2933 dot camel at triegel dot csb> <orip20qzua dot fsf at livre dot home> <1369936586 dot 16968 dot 9405 dot camel at triegel dot csb> <orehcmq122 dot fsf at livre dot home> <orehclih8s dot fsf at livre dot home> <ory5atgkyr dot fsf at livre dot home> <1370446078 dot 16968 dot 11156 dot camel at triegel dot csb> <20130605172116 dot GK29800 at brightrain dot aerifal dot cx>
On Wed, 2013-06-05 at 13:21 -0400, Rich Felker wrote:
> On Wed, Jun 05, 2013 at 05:27:58PM +0200, Torvald Riegel wrote:
> > On Sun, 2013-06-02 at 02:06 -0300, Alexandre Oliva wrote:
> > > On Jun 1, 2013, Alexandre Oliva <aoliva@redhat.com> wrote:
> > >
> > > > What must not happen is for mem synch primitives, called by users, to
> > > > fail to propagate effects of posix API calls executed locally to be
> > > > published to global memory, and make effects of API calls executed in
> > > > other threads before their latest mem synch primitives visible to the
> > > > local thread. Other than that, all bets are off.
> > >
> > > Now, bringing that back to the topic that matters to the project I'm on,
> > > and trying to show that the guarantees you're looking for are not
> > > given by posix, consider this:
> > >
> > > char a, b; // globals
> > > int pipefd[2]; // the two ends of a pipe internal to this process
> > >
> > > thread1 {
> > > a = 42;
> > > b = 6 * 9;
> > > write (pipefd[1], &b, 1);
> > > }
> > >
> > > thread2 {
> > > read (pipefd[0], &a, 1);
> > > printf ("%i\n", a);
> > > }
> > >
> > >
> > > Now, obviously there's a happens-before relationship between the write
> > > and the read, right?
> >
> > More precisely, there is an ordering implied between the return of the
> > read and the start of the write.
> > This would make the program have a data race because read() will access
> > a prior to this ordering.
> >
> > So let's use this example instead:
> >
> > thread1 {
> > a = 42;
> > b = a; // Reveal the program logic / intra-thread order to thread2
> > write (pipefd[1], &b, 1);
> > }
>
> This does not change anything. The compiler may freely reorder the
> writes to a and b.
The order of the writes to a and b is irrelevant (this piece of the
example was just change to highlight a potential program logic
relation). The key point is whether write() synchronizes or not. For
example, if it has a release fence or something similar (or if the
compiler can't prove that it doesn't), then both writes to a and b can't
be reordered to after the fence.