gatomic: Reorder memory barriers in fallback atomic operations

If the compiler doesn’t provide modern (C++11) atomic builtins (which is
now quite unlikely), we implement our own using the `__sync_synchronize()`
memory barrier. As Behdad and others have pointed out, though, the
implementation didn’t follow the same semantics as we use with the C++11
builtins — `__ATOMIC_SEQ_CST`.

Fix the use of memory barriers to provide `__ATOMIC_SEQ_CST` semantics.
In particular, this fixes the following common pattern:
```
GObject *obj = my_object_new ();
g_atomic_pointer_set (&shared_ptr, obj);
```

Previously this would have expanded to:
```
GObject *obj = my_object_new ();
*shared_ptr = obj;
__sync_synchronize ();
```

While the compiler would not have reordered the stores to `obj` and
`shared_ptr` within the code on one thread (due to the dependency
between them), the memory system might have made the write to
`shared_ptr` visible to other threads before the write to `obj` — if
they then dereferenced `shared_ptr` before seeing the write to `obj`,
that would be a bug.

Instead, the expansion is now:
```
GObject *obj = my_object_new ();
__sync_synchronize ();
*shared_ptr = obj;
```

This ensures that the write to `obj` is visible to all threads before
any write to `shared_ptr` is visible to any threads. For completeness,
`__sync_synchronize()` is augmented with a compiler barrier to ensure
that no loads/stores can be reordered locally before or after it.

Tested by disabling the C++11 atomic implementation and running:
```
meson test --repeat 1000 atomic atomic-test
```

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #1449
12 jobs for 1449-atomic-fallback-safety in 26 minutes and 57 seconds (queued for 1 second)
Status Job ID Name Coverage
  Build
passed #440930
cross-android_api21_arm64

00:01:21

passed #440931
cross-android_api28_arm64

00:01:33

passed #440932
cross-mingw64

00:02:24

passed #440999
debian-stable-x86_64

00:03:23

passed #440927
fedora-x86_64

00:04:11

passed #440929
G_DISABLE_ASSERT

00:02:20

passed #440933
win32
msys2-mingw32

00:11:00

passed #440934
win32
vs2017-x64

00:09:17

failed #440928
debian-stable-x86_64

00:35:54

 
  Coverage
passed #440935
coverage

00:02:44

77.9%
 
  Analysis
passed #440937
scan-build

00:05:29

failed #440936
allowed to fail
valgrind

00:02:09

 
Name Stage Failure
failed
valgrind Analysis
Uploading artifacts...
_build/config.h: found 1 matching files
_build/glib/glibconfig.h: found 1 matching files

_build/meson-logs: found 5 matching files

Uploading artifacts to coordinator... ok
id=440936 responseStatus=201 Created token=ftxJtiU4
Uploading artifacts...
WARNING: _build/valgrind-report.xml: no matching files
ERROR: No files to upload
ERROR: Job failed: exit code 1