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: Thread-, Signal- and Cancellation-safety documentation


On May 17, 2013, Torvald Riegel <triegel@redhat.com> wrote:

> On Thu, 2013-04-04 at 16:04 -0300, Alexandre Oliva wrote:
>> On Mar 26, 2013, Rich Felker <dalias@aerifal.cx> wrote:
>> > The cleanest fix I can envision would be atomically replacing the
>> > pointer to the locale object once the new one is prepared.
>> 
>> If it was a single pointer, that would indeed be a good course of
>> action, but there are multiple pointers that may each change
>> independently *or* with a single setlocale call.

> Getting atomic snapshots of several memory locations without creating
> contention issues in the common case is doable, especially like in this
> case when you control the writers and assume that updates are rare
> (which I guess is the case for locales, right)?

This is the case indeed.  However, the exposed internal representation
doesn't seem to have been designed so as to enable this sort of
copy,modify,reset-pointer implementation.

>> Indeed, besides the ctype functions that don't take a locale object, and
>> use the active one (which might be the global locale object), there are
>> those that take a pointer to a locale object, and if this object is the
>> global locale object, it may change from under them.  Even callers of
>> these functions that attempt to read locale properties once as they
>> start are toast if they also call any of these interfaces, for then the
>> early-reading (presumably for internal consistency) won't guarantee that
>> the callees use the same locale information.

> And this is exactly an example why saying that "setlocale is
> thread-safe" isn't sufficient in terms of the definition.  That's not
> your fault; but I believe we need to be more precise here, even if POSIX
> isn't.

> For example, what you'd get with the atomic snapshots and indirection
> approach outlined above doesn't give you the ordering guarantees that
> one might expect

I'm not sure about what ordering guarantees one might expect, or even
whether such expectations are reasonable.  Can you quote any passage of
the relevant standards that might have set such set such expectations
are reasonable?

Indeed, it seems to me that âthread safeâ has very little to do with
ordering guarantees.  IMHO, setlocale (to keep in the current example)
has no global ordering requirements whatsoever, so it would be perfectly
legitimate for it to modify a global pointer in a local CPU cache and be
done with it; any happens-before relationship that might enable other
threads to get to see the effects of this pointer change would be
established by *other* behavior of the threads, such as explicit forms
of inter-thread synchronization, or system calls defined as atomic or
defining an implicit ordering (say, writing to and reading from opposite
ends of a pipe, sending and handling a signal, etc).

That's why I believe that the notion of thread safety NOT imposing
ordering is a conscious decision rather than incompleteness; it's a
strength rather than a weakness; not imposing ordering where no ordering
is required enables more efficient implementations.

Under this line of reasoning, calling setlocale in one thread while
another thread is in a long-running tight loop that keeps on using an
old locale pointer that remained in the cache in its CPU is perfectly
reasonable: when there's no ordering relationship between the setlocale
call in one thread and any of the iterations of the tight loop in the
other, why would it even make sense for the standards impose one?  In
any case, since there isn't any ordering established in the program
itself (no operations that establish happens-before), any such ordering
would have to do with implementation details of the hardware that would
enable such an ordering to be established.  Me, I think it would be a
mistake to bring that into a standard such as POSIX, for it would tie
the standard to specific hardware implementation choices.

Can you imagine how unfortunate it would be if POSIX had chosen to
specify say atomic, global clock-based ordering requirements for every
thread-safe function, which might have made sense for uniprocessors of a
decade ago, and we were now wasting tons of cycles trying to force
loosely-synchronized multi-distributed-processors with transactional
memory to abide by that standard?

IMHO, POSIX specifies operations that establish happens-before
relationships, and operations that are to be atomic, but those are the
exception, rather than the rule.  For everything else, no ordering
requirements exist, even for thread-safe functions, and IMHO that's how
it should be.

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer


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