OSDN Git Service

36af6aad93b633f07b6dda268afeb01319eb59b2
[pf3gnuchains/gcc-fork.git] / libgomp / config / linux / x86 / futex.h
1 /* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
2    Contributed by Richard Henderson <rth@redhat.com>.
3
4    This file is part of the GNU OpenMP Library (libgomp).
5
6    Libgomp is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as published by
8    the Free Software Foundation; either version 2.1 of the License, or
9    (at your option) any later version.
10
11    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
14    more details.
15
16    You should have received a copy of the GNU Lesser General Public License 
17    along with libgomp; see the file COPYING.LIB.  If not, write to the
18    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 /* As a special exception, if you link this library with other files, some
22    of which are compiled with GCC, to produce an executable, this library
23    does not by itself cause the resulting executable to be covered by the
24    GNU General Public License.  This exception does not however invalidate
25    any other reasons why the executable file might be covered by the GNU
26    General Public License.  */
27
28 /* Provide target-specific access to the futex system call.  */
29
30 #ifdef __LP64__
31 # ifndef SYS_futex
32 #  define SYS_futex     202
33 # endif
34
35 static inline void
36 futex_wait (int *addr, int val)
37 {
38   register long r10 __asm__("%r10");
39   long res;
40
41   r10 = 0;
42   __asm volatile ("syscall"
43                   : "=a" (res)
44                   : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wait),
45                     "d" (val), "r" (r10)
46                   : "r11", "rcx", "memory");
47   if (__builtin_expect (res == -ENOSYS, 0))
48     {
49       gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
50       gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
51       r10 = 0;
52       __asm volatile ("syscall"
53                       : "=a" (res)
54                       : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wait),
55                         "d" (val), "r" (r10)
56                       : "r11", "rcx", "memory");
57     }
58 }
59
60 static inline void
61 futex_wake (int *addr, int count)
62 {
63   long res;
64
65   __asm volatile ("syscall"
66                   : "=a" (res)
67                   : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wake),
68                     "d" (count)
69                   : "r11", "rcx", "memory");
70   if (__builtin_expect (res == -ENOSYS, 0))
71     {
72       gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
73       gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
74       __asm volatile ("syscall"
75                       : "=a" (res)
76                       : "0" (SYS_futex), "D" (addr), "S" (gomp_futex_wake),
77                         "d" (count)
78                       : "r11", "rcx", "memory");
79     }
80 }
81 #else
82 # ifndef SYS_futex
83 #  define SYS_futex     240
84 # endif
85
86 # ifdef __PIC__
87
88 static inline long
89 sys_futex0 (int *addr, int op, int val)
90 {
91   long res;
92
93   __asm volatile ("xchgl\t%%ebx, %2\n\t"
94                   "int\t$0x80\n\t"
95                   "xchgl\t%%ebx, %2"
96                   : "=a" (res)
97                   : "0"(SYS_futex), "r" (addr), "c"(op),
98                     "d"(val), "S"(0)
99                   : "memory");
100   return res;
101 }
102
103 # else
104
105 static inline long
106 sys_futex0 (int *addr, int op, int val)
107 {
108   long res;
109
110   __asm volatile ("int $0x80"
111                   : "=a" (res)
112                   : "0"(SYS_futex), "b" (addr), "c"(op),
113                     "d"(val), "S"(0)
114                   : "memory");
115   return res;
116 }
117
118 # endif /* __PIC__ */
119
120 static inline void
121 futex_wait (int *addr, int val)
122 {
123   long res = sys_futex0 (addr, gomp_futex_wait, val);
124   if (__builtin_expect (res == -ENOSYS, 0))
125     {
126       gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
127       gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
128       sys_futex0 (addr, gomp_futex_wait, val);
129     }
130 }
131
132 static inline void
133 futex_wake (int *addr, int count)
134 {
135   long res = sys_futex0 (addr, gomp_futex_wake, count);
136   if (__builtin_expect (res == -ENOSYS, 0))
137     {
138       gomp_futex_wait &= ~FUTEX_PRIVATE_FLAG;
139       gomp_futex_wake &= ~FUTEX_PRIVATE_FLAG;
140       sys_futex0 (addr, gomp_futex_wake, count);
141     }
142 }
143
144 #endif /* __LP64__ */
145
146 static inline void
147 cpu_relax (void)
148 {
149   __asm volatile ("rep; nop" : : : "memory");
150 }
151
152 static inline void
153 atomic_write_barrier (void)
154 {
155   __sync_synchronize ();
156 }