12ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// Copyright 2006-2008 The RE2 Authors.  All Rights Reserved.
22ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// Use of this source code is governed by a BSD-style
32ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// license that can be found in the LICENSE file.
42ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
52ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#ifndef RE2_UTIL_ATOMICOPS_H__
62ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#define RE2_UTIL_ATOMICOPS_H__
72ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
82ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#if defined(__i386__)
92ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
102ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void WriteMemoryBarrier() {
112ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  int x;
122ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  __asm__ __volatile__("xchgl (%0),%0"  // The lock prefix is implicit for xchg.
132ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson                       :: "r" (&x));
142ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
152ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
162ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#elif defined(__x86_64__)
172ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
182ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// 64-bit implementations of memory barrier can be simpler, because
192ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// "sfence" is guaranteed to exist.
202ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void WriteMemoryBarrier() {
212ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  __asm__ __volatile__("sfence" : : : "memory");
222ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
232ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
242ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#elif defined(__ppc__)
252ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
262ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void WriteMemoryBarrier() {
272ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  __asm__ __volatile__("eieio" : : : "memory");
282ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
292ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
302ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#elif defined(__alpha__)
312ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
322ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void WriteMemoryBarrier() {
332ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  __asm__ __volatile__("wmb" : : : "memory");
342ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
352ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
362ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#else
372ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
382ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#include "util/mutex.h"
392ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
402ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void WriteMemoryBarrier() {
412ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // Slight overkill, but good enough:
422ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // any mutex implementation must have
432ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // a read barrier after the lock operation and
442ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // a write barrier before the unlock operation.
452ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  //
462ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // It may be worthwhile to write architecture-specific
472ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // barriers for the common platforms, as above, but
482ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  // this is a correct fallback.
492ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  re2::Mutex mu;
502ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  re2::MutexLock l(&mu);
512ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
522ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
532ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson/*
542ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#error Need WriteMemoryBarrier for architecture.
552ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
562ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// Windows
572ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsoninline void WriteMemoryBarrier() {
582ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  LONG x;
592ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  ::InterlockedExchange(&x, 0);
602ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
612ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson*/
622ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
632ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#endif
642ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
652ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// Alpha has very weak memory ordering. If relying on WriteBarriers, must one
662ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson// use read barriers for the readers too.
672ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#if defined(__alpha__)
682ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
692ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void MaybeReadMemoryBarrier() {
702ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson  __asm__ __volatile__("mb" : : : "memory");
712ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson}
722ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
732ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#else
742ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
752ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodsonstatic inline void MaybeReadMemoryBarrier() {}
762ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
772ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#endif // __alpha__
782ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson
792ee91b4af4353b9e6a9d591c32fedfc58fd4ef35Ian Hodson#endif  // RE2_UTIL_ATOMICOPS_H__
80