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: Async-signal-safe access to __thread variables from dlopen()ed libraries?


On Mon, 2013-10-07 at 14:16 -0400, Rich Felker wrote:
> On Mon, Oct 07, 2013 at 08:48:20PM +0300, Torvald Riegel wrote:
> > On Mon, 2013-10-07 at 10:14 -0400, Rich Felker wrote:
> > > On Sun, Oct 06, 2013 at 11:56:00PM +0200, Torvald Riegel wrote:
> > > > On Sun, 2013-10-06 at 17:40 -0400, Rich Felker wrote:
> > > > > On Sun, Oct 06, 2013 at 11:36:41PM +0200, Torvald Riegel wrote:
> > > > > > > My point is that char seems to automatically have this property on any
> > > > > > > sane hardware, because, per the the POSIX and C11 memory models, you
> > > > > > > can't access char objects as a read-modify-write sequence on a larger
> > > > > > > unit of storage; you must perform single-byte accesses.
> > > > > > 
> > > > > > The compiler could still do "arbitrary" stuff to non-atomic and
> > > > > > non-volatile char variables (reordering accesses, ...), provided that
> > > > > > when assuming a sequential program, the program would behave as if the
> > > > > > abstract machine would execute it.  The atomics tell the compiler to not
> > > > > > assume that this is sequential code; therefore, a char-typed variable
> > > > > > doesn't have the stronger properties automatically.
> > > > > 
> > > > > Adding volatile (which, BTW, also needs to be added to sig_atomic_t)
> > > > > would avoid these ordering issues.
> > > > 
> > > > It would prevent some of them -- but then we're talking not about plain
> > > > char-typed variables anymore.  Also, volatiles and atomics aren't the
> > > > same thing; 
> > > 
> > > I'm quite aware. None of this discussion has been about atomics in the
> > > C11 or C++11 sense. The word "atomic" here has nothing to do with
> > > synchronization between cores. In sig_atomic_t, it's just a part of
> > > the name; in other usages, it's described the property whereby partial
> > > changes to the object are never observed (described more precisely
> > > earlier in this thread).
> > 
> > IIRC, it's not specified on which thread a signal handler will be
> > executed, so it might execute concurrent accesses.
> 
> This is a separate issue which is actually easier to deal with (using
> atomics in the C11 sense) if needed. For the purposes of this
> discussion, we can assume the signal handler and other accessess to
> the object are occurring in the same thread, which is guaranteed in
> any of the following situations (and possibly others I missed):
> 
> 1. All other threads have the signal masked.
> 2. The signal is generated by pthread_kill.
> 3. The signal is generated synchronously by an action of the thread
>    (e.g. SIGFPE, SIGPIPE, SIGBUS, SIGSEGV, etc.).
> 
> > > > > > multi-byte accesses with atomic read-modify-write ops as long as it
> > > > > > makes sure that those don't overlap with volatiles or similar.
> > > > > 
> > > > > Is that observably different from a single-byte write? I don't think
> > > > > so.
> > > > 
> > > > That's the point: The compiler must not necessarily use single-byte
> > > > accesses, as you seemed to say (see above).
> > > 
> > > The physical mechanism is irrelevant. If something is not observably
> > > different from a single-byte write, then, for purposes of this
> > > discussion, it's a single-byte write. The point, in any case, is that
> > > the observable behavior must be as if single-byte writes exist and are
> > > used for writing char-type objects. Of course, in some cases (e.g. if
> > > multiple chars at adjacent addresses are written) then the compiler
> > > can combine them without any observable effect.
> > 
> > There is a difference whether the observer can only be the same thread
> > (ie, as with types that are neither atomic, sig_atomic, nor volatile) or
> > whether observers can include other threads or signal handlers.  You
> > cannot just throw char into the same bucket as atomics, sig_atomic_t, or
> > volatiles.
> 
> I'm not throwing any of them into the same bucket. What I'm saying is
> that, for the purpose of defining a memory model for access to objects
> from signal handlers, char type objects should be on equal ground as
> sig_atomic_t. Previously they weren't, presumably because
> implementations could theoretically implement char writes as a
> read-modify-write cycle where the signal handler could be invoked
> between the read and the write. With C11 or POSIX, such an
> implementation is not valid

I don't think it matters whether we're dealing with a char type or, say,
an int; both don't require the compiler to ensure that observations by
signal handlers return meaningful values.  Let's look at an example:

char foo = 1;

void handler() { x = foo; } // Can it read 42?

foo = 2;
*p = 0; // This causes a signal to be handled.
foo = 3;

Can the handler read a value of 42 for foo?  I think this is allowed
behavior because the compiler can assume that the accesses to foo are
sequential; thus, it could for example reuse the variable's memory
location for other stuff (eg, it's stack slot).  The handler could
probably also read 1, because the compiler could just remove the (dead)
store of 2.

Why do you think that optimizations like those mentioned above would be
disallowed for char types?

This may be different for raise(), given that this behaves like a
function call directly to the handler AFAIU.


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