[cpp-threads] Slightly revised memory model proposal (D2300)

Nick Maclaren nmm1 at cus.cam.ac.uk
Wed Jun 6 09:38:11 BST 2007


"Boehm, Hans" <hans.boehm at hp.com> wrote:
> 
> > As far as the MEMORY model goes, it doesn't make a huge difference
> > to C++ whether the primary thread is interrupted and a handler run
> > in the same thread, or whether another thread is being executed.
> > Both need comparable specifications of atomicity, synchronisation
> > etc.
>
> Except of course that there are some major differences:

Oh, yes, indeed.

> - Signal handlers can't normally use mechanisms like locks or barriers
> (in the OpenMP sense) to synchronize with the main thread, since it
> is implicitly stopped until the handler completes.

Yes and no.  It is not necessarily stopped on all platforms, but I
have never even heard of one where synchronisation is permitted.
POSIX is right that asynchronous signal handlers are (or were!) used,
and some didn't stop the main thread.

> - Much cheaper mechanisms often suffice for enforcing memory visibility
> between a thread and a handler running in the same thread.  The hardware
> is usually no longer an issue; you only have to control compiler
> instruction reordering.

The former is true; the latter is most definitely NOT true.  If you
look at the code of most first-level interrupt handlers, you will see
lots of code to synchronise the memory, and often evidence of changes
where it used to get through to the application.  But the convention
is that the operating system and/or language run-time system will
do that, which is why C++ need not worry about it.

Whether that is entirely true on all embedded and real-time operating
systems, I can't say.  It may not be.  Anyone know?

> I think there is an interesting question as to whether atomics should
> be usable for communicating with signal handlers, in at least the
> same sense that volatile sigatomic_t is now.  I have been assuming that
> this applies at most if the atomics are not emulated.  Otherwise the
> emulation would require disabling signals.  Opinions?

Indeed, though that is not the only possible solution.  Another is
that the language run-time system recognises the incomplete update
and emulates completing or backing off the atomic update; that used
to be standard practice on mainframes.

But it is the reason why I favour having a basic set of atomic types
that include just an implementation-defined integer (of at least the
same size as int) and a 'void *' equivalent.  It isn't hard to handle
such a restricted set specially and get effective atomicity over
interrupts.  For example:

struct {unsigned char flag; int data1, data2;} atomic_int;

store expands into:

    flag = 1; data1 = <value>; flag = 2; data2 = <value>; flag = 3;

And with obvious code for load.  Not pretty, not efficient, but safe
over any interrupt where the system quiesces the main thread before
calling the handler.

It doesn't help for threading, of course :-)




More information about the cpp-threads mailing list