1 : /*
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.
5 : */
6 :
7 :
8 : #ifndef NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_
9 : #define NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_ 1
10 :
11 :
12 : #include "native_client/src/include/nacl_base.h"
13 : #include "native_client/src/include/portability.h"
14 :
15 : #if NACL_WINDOWS && (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86)
16 : #include <intrin.h>
17 : #include <mmintrin.h>
18 : #endif
19 :
20 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
21 :
22 : static INLINE void NaClWriteMemoryBarrier(void) {
23 : #if NACL_WINDOWS
24 : /* Inline assembly is not available in x86-64 MSVC. Use built-in. */
25 : _mm_sfence();
26 : #else
27 1106 : __asm__ __volatile__("sfence");
28 : #endif
29 1106 : }
30 :
31 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
32 :
33 : static INLINE void NaClWriteMemoryBarrier(void) {
34 : /* Note that this depends on ARMv7. */
35 : __asm__ __volatile__("dsb");
36 :
37 : /*
38 : * We could support ARMv6 by instead using:
39 : * __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 5"
40 : * : : "r" (0) : "memory");
41 : */
42 : }
43 :
44 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
45 :
46 : static INLINE void NaClWriteMemoryBarrier(void) {
47 : __asm__ __volatile__("sync" : : : "memory");
48 : }
49 :
50 : #else
51 :
52 : #error "Define for other architectures"
53 :
54 : #endif
55 :
56 :
57 1253 : static INLINE void NaClFlushCacheForDoublyMappedCode(uint8_t *writable_addr,
58 1253 : uint8_t *executable_addr,
59 1253 : size_t size) {
60 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
61 : /*
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
66 : * this function.
67 : */
68 2506 : UNREFERENCED_PARAMETER(writable_addr);
69 2506 : UNREFERENCED_PARAMETER(executable_addr);
70 2506 : UNREFERENCED_PARAMETER(size);
71 : #if NACL_WINDOWS
72 : _ReadWriteBarrier();
73 : #else
74 1253 : __asm__ __volatile__("" : : : "memory");
75 : #endif
76 : #elif defined(__GNUC__)
77 : /*
78 : * __clear_cache() does two things:
79 : *
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.
84 : *
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
90 : */
91 : __builtin___clear_cache(writable_addr, writable_addr + size);
92 : __builtin___clear_cache(executable_addr, executable_addr + size);
93 : #else
94 : /*
95 : * Give an error in case we ever target a non-gcc compiler for ARM
96 : * or for some other architecture that we might support in the
97 : * future.
98 : */
99 : # error "Don't know how to clear the icache on this architecture"
100 : #endif
101 1253 : }
102 :
103 :
104 : #endif /* NATIVE_CLIENT_SRC_INCLUDE_CONCURRENCY_OPS_H_ */
|