Use real atomics for Interlocked.Increment ()/Decrement () in all cases.
Use InterlockedExchange64 () for Interlocked.Exchange () for double/long.

Avoids using a lock on 32-bit systems and makes the code saner.
Use InterlockedCompareExchange64 () for Interlocked.CompareExchange (double, ...).

Avoids using a lock on 32-bit systems and makes the code saner.
Use InterlockedAdd ()/InterlockedAdd64 () for the Interlocked.Add () overloads.
Use mono_atomic_load_seq_cst () in Interlocked.Read ().

This *ensures* that we do the right thing everywhere and also
makes the code less ugly for the 32-bit / 64-bit cases.
Use mono_memory_barrier () for Thread.MemoryBarrier ().

This gets rid of the rather hacky lock-based barrier.
Move the unaligned 64-bit CAS hack to atomic.c.

Since we now rely on InterlockedCompareExchange64 () in quite a few
places that involve managed references, it's better to just put this
in one place.

This moves the assembly for ARM into a separate function since a
naked function can only (safely) contain asm statements.

Also added a HACK note so we don't forget about it.
Get rid of the mono_interlocked_mutex.

No code paths use it anymore.
Correct our implementation of Thread.VolatileRead ()/VolatileWrite ().

We have various issues:

* All of the functions assumed that doing volatile loads/stores was
  enough, when load-acquire, store-release semantics were actually
  needed. This may have worked before purely by chance. We now use
  proper atomic operations so that we don't have to hope for the
  compiler and CPU to do the right thing.
* Removes the hack for 64-bit quantities on 32-bit systems. This is
  no longer needed now that we use explicit memory barriers in
  these functions.
* The VolatileWrite (object&, object) overload was not using the
  volatile qualifier at all, thus not getting volatile semantics
  as per: http://gcc.gnu.org/onlinedocs/gcc/Volatiles.html
Fix an ifdef in atomic.c to match the define in atomic.h.
Simplify the no-atomics and iOS/OS X fallbacks in atomic.{c,h}.

Now the header has two paths in the GCC atomics case: The one
where 64-bit atomics work, which does the obvious thing and uses
the intrinsics, and the one where they don't which relies on an
emulated or hand-implemented 64-bit cmpxchg that all other 64-bit
operations are then implemented in terms of. This ensures that
we use the somewhat faster intrinsics on platforms with sane
compilers. InterlockedExchange64 () is still implemented in terms
of a 64-bit cmpxchg in both paths, though, since GCC has no
intrinsic for it.

Further, things have been simplified such that only one define
needs to be set in the header if 64-bit atomics are broken, which
is BROKEN_64BIT_ATOMICS. It only has meaning in the GCC atomics
case, and means that 64-bit cmpxchg is implemented in atomic.c.
No define needs to be set to indicate that 64-bit atomics actually
work; this is the default assumption.

Finally, since the lock-based 64-bit cmpxchg fallback is needed
both with broken compilers and on systems with no atomics at all,
it has been factored into a section guarded by NEED_64BIT_CMPXCHG.
Use __sync_sub_and_fetch () for atomic decrements for clarity.
Use HAVE_ARMV7 in preprocessor check instead of explicitly listing archs.
Fix preprocessor architecture checks in atomic.c.

We want to check the host architecture, not the target architecture.
Use runtime ARM version detection in 64-bit cmpxchg on iOS.
Add mono_atomic_load_seq_cst () / mono_atomic_store_seq_cst () functions.