[Fontconfig] fontconfig: Branch 'master' - 23 commits
Raimund Steger
rs at mytum.de
Tue Jan 8 18:44:10 PST 2013
Behdad Esfahbod wrote:
> Raimund,
>
> Can we use these:
>
> http://docs.oracle.com/cd/E18659_01/html/821-1383/gjzmf.html
>
> I have your patch in my tree, waiting to see if we can resolve this part.
> Without correct memory barrier, undefined behavior can result, though, it's
> only known to happen for Alpha architectures.
I believe we could use these instructions. Though they seem to be rather
recent additions and some people (not including me) might still use
older Sun Studio versions, but well, the non-threadsafe behavior will
always continue to work.
At first glance, __memory_rw_barrier seems to be what we need. I've now
compared disassembly of a few relevant routines on SPARC:
Sun Studio translates __machine_rw_barrier() into:
[ 5] 10684: membar #StoreStore | #LoadStore |
#StoreLoad | #LoadLoad
6. __machine_rw_barrier();
GCC translates __sync_synchronize() into the same:
4. __sync_synchronize();
[ 4] 106f8: membar #StoreStore | #LoadStore |
#StoreLoad | #LoadLoad
As for the Solaris atomic ops (add/compare-exchange), they are library
functions but they can be looked up here:
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/atomic/sparc/atomic.s
What GCC does in comparison:
- translates __sync_fetch_and_add() into:
8. return __sync_fetch_and_add(ai,v);
[ 8] 10710: ld [%fp + 72], %o5
[ 8] 10714: ld [%fp + 68], %g3
[ 8] 10718: ld [%g3], %g2
[ 8] 1071c: mov %g2, %g1
[ 8] 10720: mov %g1, %g4
[ 8] 10724: add %g1, %o5, %g2
[ 8] 10728: membar #StoreStore | #LoadStore |
#StoreLoad | #LoadLoad
[ 8] 1072c: cas [%g3] , %g1, %g2
[ 8] 10730: cmp %g2, %g1
[ 8] 10734: bne,pt %icc,0x1071c
[ 8] 10738: nop
[ 8] 1073c: mov %g4, %g1
- translates __sync_bool_compare_and_swap() into:
12. return __sync_bool_compare_and_swap(p,o,n);
[12] 1075c: ld [%fp + 72], %g1
[12] 10760: ld [%fp + 76], %g2
[12] 10764: ld [%fp + 68], %g3
[12] 10768: membar #StoreStore | #LoadStore |
#StoreLoad | #LoadLoad
[12] 1076c: cas [%g3] , %g1, %g2
[12] 10770: xor %g2, %g1, %g1
[12] 10774: cmp %g0, %g1
[12] 10778: subc %g0, -1, %g1
[12] 1077c: and %g1, 255, %g1
So this looks like it is necessary to add __machine_rw_barrier() before
the atomic ops.
Interestingly though, GCC on amd64 (still Solaris) translates
__sync_synchronize() into 'mfence' but includes no fence instruction for
the atomic add and compare-exchange operations.
I should add that there are memory barrier operations in libc on Solaris
as well. They are from atomic.s, too (see link, at the end of the page).
They (more or less, it differs between SPARC and amd64) provide
individual access to the above 'membar' flavors. Hence to achieve the
same effect as __machine_rw_barrier(), a sequence of such function calls
were required.
Well in the end I suppose if we want to follow GCC's example we should
probably use __machine_rw_barrier(). It's a macro that expands to an
inline assembly statement.
So, maybe like the following in fcatomic.h:
[...]
#elif !defined(FC_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
#include <atomic.h>
#include <mbarrier.h>
typedef unsigned int fc_atomic_int_t;
#define fc_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}),
atomic_add_int_nv (&(AI), (V)) - (V))
#define fc_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
#define fc_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}),
atomic_cas_ptr ((P), (O), (N)) == (void *) (O) ? FcTrue : FcFalse)
#elif !defined(FC_NO_MT)
[...]
Raimund
--
Worringer Str 31 Duesseldorf 40211 DE home: <rs at mytum.de>
+49-179-2981632 icq 16845346 work: <rs at interface-ag.de>
More information about the Fontconfig
mailing list