On Tue, Nov 19, 2013 at 11:38 AM, Andres Freund <and...@2ndquadrant.com> wrote:
> /*-------------------------------------------------------------------------
>  *
>  * atomics.h
>  *        Generic atomic operations support.
>  *
>  * Hardware and compiler dependent functions for manipulating memory
>  * atomically and dealing with cache coherency. Used to implement locking
>  * facilities and other concurrency safe constructs.
>  *
>  * There's three data types which can be manipulated atomically:
>  *
>  * * pg_atomic_flag - supports atomic test/clear operations, useful for
>  *      implementing spinlocks and similar constructs.
>  *
>  * * pg_atomic_uint32 - unsigned 32bit integer that can correctly manipulated
>  *      by several processes at the same time.
>  *
>  * * pg_atomic_uint64 - optional 64bit variant of pg_atomic_uint32. Support
>  *      can be tested by checking for PG_HAVE_64_BIT_ATOMICS.
>  *
>  * The values stored in theses cannot be accessed using the API provided in
>  * thise file, i.e. it is not possible to write statements like `var +=
>  * 10`. Instead, for this example, one would have to use
>  * `pg_atomic_fetch_add_u32(&var, 10)`.
>  *
>  * This restriction has several reasons: Primarily it doesn't allow non-atomic
>  * math to be performed on these values which wouldn't be concurrency
>  * safe. Secondly it allows to implement these types ontop of facilities -
>  * like C11's atomics - that don't provide direct access. Lastly it serves as
>  * a useful hint what code should be looked at more carefully because of
>  * concurrency concerns.
>  *
>  * To be useful they usually will need to be placed in memory shared between
>  * processes or threads, most frequently by embedding them in structs. Be
>  * careful to align atomic variables to their own size!

What does that mean exactly?

>  * Before variables of one these types can be used they needs to be
>  * initialized using the type's initialization function (pg_atomic_init_flag,
>  * pg_atomic_init_u32 and pg_atomic_init_u64) or in case of global
>  * pg_atomic_flag variables using the PG_ATOMIC_INIT_FLAG macro. These
>  * initializations have to be performed before any (possibly concurrent)
>  * access is possible, otherwise the results are undefined.
>  *
>  * For several mathematical operations two variants exist: One that returns
>  * the old value before the operation was performed, and one that that returns
>  * the new value. *_fetch_<op> variants will return the old value,
>  * *_<op>_fetch the new one.

Ugh.  Do we really need this much complexity?

>  * Use higher level functionality (lwlocks, spinlocks, heavyweight locks)
>  * whenever possible. Writing correct code using these facilities is hard.
>  *
>  * For an introduction to using memory barriers within the PostgreSQL backend,
>  * see src/backend/storage/lmgr/README.barrier

The extent to which these primitives themselves provide ordering
guarantees should be documented.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to