Re: better atomics - v0.2

From: Andres Freund <andres(at)2ndquadrant(dot)com>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Peter Geoghegan <pg(at)heroku(dot)com>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>, Ants Aasma <ants(at)cybertec(dot)at>
Subject: Re: better atomics - v0.2
Date: 2013-11-19 16:38:33
Message-ID: 20131119163833.GD19293@alap2.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On 2013-11-19 10:27:57 -0500, Robert Haas wrote:
> > Ok, I'll work on that. It would be useful to get feedback on the
> > "frontend" API in atomics.h though. If people are unhappy with the API
> > it might very well change how we can implement the API on different
> > architectures.
>
> Sure, but if people can't understand the API, then it's hard to decide
> whether to be unhappy with it.

Fair point, while there's already an explantory blurb ontop of atomics.h
and the semantics of the functions should all be documented, it doesn't
explain the API on a high level. I've expanded it a bit

The attached patches compile and make check successfully on linux x86,
amd64 and msvc x86 and amd64. This time and updated configure is
included. The majority of operations still rely on CAS emulation.

I've copied the introduction here for easier reading:

/*-------------------------------------------------------------------------
*
* 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!
*
* 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.
*
*
* To bring up postgres on a platform/compiler at the very least
* either one of
* * pg_atomic_test_set_flag(), pg_atomic_init_flag(), pg_atomic_clear_flag()
* * pg_atomic_compare_exchange_u32()
* * pg_atomic_exchange_u32()
* and all of
* * pg_compiler_barrier(), pg_memory_barrier()a
* need to be implemented. There exist generic, hardware independent,
* implementations for several compilers which might be sufficient, although
* possibly not optimal, for a new platform.
*
* To add support for a new architecture review whether the compilers used on
* that platform already provide adequate support in the files included
* "Compiler specific" section below. If not either add an include for a new
* file adding generic support for your compiler there and/or add/update an
* architecture specific include in the "Architecture specific" section below.
*
* Operations that aren't implemented by either architecture or compiler
* specific code are implemented ontop of compare_exchange() loops or
* spinlocks.
*
* 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
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/atomics.h
*
*-------------------------------------------------------------------------
*/

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachment Content-Type Size
0001-Try-to-make-HP-UX-s-ac-not-cause-warnings-about-unus.patch text/x-patch 726 bytes
0002-Very-basic-atomic-ops-implementation.patch text/x-patch 110.9 KB
0003-Convert-the-PGPROC-lwWaitLink-list-into-a-dlist-inst.patch text/x-patch 14.7 KB
0004-Wait-free-LW_SHARED-lwlock-acquiration.patch text/x-patch 30.4 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Robert Haas 2013-11-19 16:42:06 Re: Logging WAL when updating hintbit
Previous Message Tom Lane 2013-11-19 16:38:24 Re: Review: pre-commit triggers