Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Processor Tools

Memory fences: Mfence

See Section 8.2 (Memory Ordering) in Intel 3a System Programming Manual. This suggests you can actually get away with a fair bit. I think it also says that the LOCK prefix and XCHG instruction act like an mfence (TODO: confirm).

Compiler Tools

Inline assembly

...

It does leave us with very few ways of saying that an asm can read memory, and so it might be good to have it clarified that "volatile" implies that (at least with the memory clobber).

Volatile keyword elsewhere

On data

...

So it seems the only safe way to make sure an asm block is not not moved or deleted by the compiler is to use volatile together with a memory clobber.

Volatile keyword on data or pointers

lkml emails from linus http://lwn.net/Articles/233481/:

If the memory barriers are right, then the "volatile" doesn't matter. And if the memory barriers aren't right, then "volatile" doesn't help.

Basically, a volatile on a data structure can NEVER be right. If it makes a difference, it's a sign of improper locking.

potentially make the compiler generate worse code for no reason (the "no reason" being that if there aren't any barriers in between, the compiler should merge accesses)

The only thing "volatile" can ever do is generate worse code, WITH NO UPSIDES.

actual accessor functions can use it in a cast to make one particular access follow the rules of "don't cache this one dereference". That is useful as part of a bigger set of rules about that access (i.e., it might be the internal implementation of a "readb()", for example).

On pointers

In Section 7.1.6.1 (The cv-qualifiers) of the C++ standard:

A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does.

So you can use a pointer marked volatile to signify volatile accesses, i.e., those that should be read from memory. However, this is useful for interacting with IO devices, not for concurrency where you need memory barriers anyway.

Survey of Existing Concurrency Primitives

...

where __volatile is defined as volatile in sys/cdefs.h. I couldn't find the definition for __asm, but I assume it's the same as asm.

Google perf tools

http://google-perftools.googlecode.com/svn/trunk/src/base/
They have a set of BSD-licensed atomic primitives, a spinlock, etc.

References

Extended Asm in the GCC manual describes how to use inline assembly in gcc. Unfortunately, it is not very precise or thorough. When describing the '+' constraint modifier, it says you should not use '+m', but Linus claims this is not true (see Re: [PATCH 3/8] i386: bitops: Rectify bogus "+m" constraints).

...

He changes his mind a bit in 2007, now believing that "memory" means that the asm instructions write to memory but do not read it.

In Section 6.7.3 Type Qualifiers of the C99 standard:

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously. (*) What constitutes an access to an object that has volatile-qualified type is implementation-defined.

(*) A volatile declaration may be used to describe an object corresponding to a memory-mapped input/output port or an object accessed by an asynchronously interrupting function. Actions on objects so declared shall not be "optimized out" by an implementation or reordered except as permitted by the rules for evaluating expressions.

Among other details, Section 5.12.3 (Program Execution) says:

At sequence points, volatile objects are stable in the sense that previous accesses are complete and subsequent accesses have not yet occurred.

In Section 7.1.6.1 (The cv-qualifiers) of the C++ standard:

A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does.

Volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C.