C++ Logo


Advanced search

Re: [wg14/wg21 liaison] UB

From: Martin Uecker <ma.uecker_at_[hidden]>
Date: Wed, 24 May 2023 08:05:21 +0200
Am Mittwoch, dem 24.05.2023 um 07:17 +0200 schrieb Martin Uecker:
> Am Dienstag, dem 23.05.2023 um 17:34 -0700 schrieb Hans Boehm:
> > >
> > > >
> > > > Yes, I also have difficulties to understand what the concept would
> > > > mean in the case of race conditions. The text in the C standard says
> > > >
> > > > The execution of a program contains a data race if it contains two
> > > > conflicting actions in different threads, at least one of which is
> > > > not atomic, and neither happens before the other. Any such data
> > > > race results in undefined behavior.
> > > >
> > > > So a concrete data race is even defined by the absence of ordering,
> > > > and for me it is not clear then which side effects can be considered
> > > > to have taken place. (E.g there may be side effects that are strictly
> > > > ordered with one of the racing accesses, but not with the other.)
> > >
> > > It is defined in the absence of ordering for two specific actions.
> > > Preferably, I would make both these actions have undefined behavior.
> > >
> > > One has to think a bit about whether this still gives strong
> > > enough semantics for all optimizations, but I think it does.
> > >
> >
> > Agreed. I think any observable behavior that you can count on has
> > to strongly happen before all accesses that can participate in a
> > data race. But the compiler implications are a bit subtle, since the
> > compiler may be able to infer something about concurrent
> > execution based on the absence of a data race later in the program.
> >
> My expecation is that it is not a problem for any existing compiler,
> because they do not explicitely reason about concurrency. Instead,
> that the optimizations they do perform should also work for
> concurrent programs further restricts what they can do (e.g.
> not create sprurious accesses to neighboring data).
> But I think discussing what concrete UB means for concurrent
> programs warrants another paper.

Just some thoughts: The definition of data race is already tied
to a concrete definition of having conflicting accesses in two
two threads for a actual execution. Fundamentally, I think it
fits well with a concrete definition of UB. Giving these two accesses
UB should do the job. I agree though that this still needs do
be analyzed carefully.

In the following example, if f() and g() do I/O (and assuming there
is no other synchronitzation) the I/O does not need to happen
because it is not ordered with respect to the access in the other
 thread which has UB.

int i;
// thread one
f(); // I/O
i = 1; //data race, UB

// thread two
g(); // I/O
x = i; // data race, UB

But on the same time, - if I not missing something - compiler today
need to carefully perform semantics up to and including the function
calls in both threads, because one of the calls or both might not return
and then there is no data race. So there might be a way to strengthen
semantics so that both I/O have to be preserved.

One could say that only the second access has UB, but obviously this
this does not work without defining an ordering. But there might be
some other way to express the idea that for any ordering, both functions
calls have to be performed before there is the opportunity for a data race.


Received on 2023-05-24 06:05:24