2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 #ifndef NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_
9 #define NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_ 1
12 #include "native_client/src/include/nacl_base.h"
13 #include "native_client/src/include/portability.h"
15 #if NACL_WINDOWS && (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86)
20 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
22 static INLINE void NaClWriteMemoryBarrier(void) {
24 /* Inline assembly is not available in x86-64 MSVC. Use built-in. */
27 __asm__ __volatile__("sfence");
31 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
33 static INLINE void NaClWriteMemoryBarrier(void) {
34 /* Note that this depends on ARMv7. */
35 __asm__ __volatile__("dsb");
38 * We could support ARMv6 by instead using:
39 * __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 5"
40 * : : "r" (0) : "memory");
44 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
46 static INLINE void NaClWriteMemoryBarrier(void) {
47 __asm__ __volatile__("sync" : : : "memory");
52 #error "Define for other architectures"
57 static INLINE void NaClFlushCacheForDoublyMappedCode(uint8_t *writable_addr,
58 uint8_t *executable_addr,
60 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
62 * Clearing the icache explicitly is not necessary on x86. We could
63 * call gcc's __builtin___clear_cache() on x86, where it is a no-op,
64 * except that it is not available in Mac OS X's old version of gcc.
65 * We simply prevent the compiler from moving loads or stores around
68 UNREFERENCED_PARAMETER(writable_addr);
69 UNREFERENCED_PARAMETER(executable_addr);
70 UNREFERENCED_PARAMETER(size);
74 __asm__ __volatile__("" : : : "memory");
76 #elif defined(__GNUC__)
78 * __clear_cache() does two things:
80 * 1) It flushes the write buffer for the address range.
81 * We need to do this for writable_addr.
82 * 2) It clears the instruction cache for the address range.
83 * We need to do this for executable_addr.
85 * We do not need apply (1) to executable_addr or apply (2) to
86 * writable_addr, but the Linux kernel does not expose (1) and (2)
87 * as separate operations; it just provides a single syscall that
88 * does both. For background, see:
89 * http://code.google.com/p/nativeclient/issues/detail?id=2443
91 * We use __builtin___clear_cache since __clear_cache is only available
92 * with gnu extensions available.
94 * Casts are needed since clang's prototype for __builtin___clear_cache
95 * doesn't match gcc's.
97 __builtin___clear_cache((char *) writable_addr,
98 (char *) writable_addr + size);
99 __builtin___clear_cache((char *) executable_addr,
100 (char *) executable_addr + size);
103 * Give an error in case we ever target a non-gcc compiler for ARM
104 * or for some other architecture that we might support in the
107 # error "Don't know how to clear the icache on this architecture"
112 #endif /* NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_ */