~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to erts/include/internal/gcc/ethr_atomic.h

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * %CopyrightBegin%
 
3
 *
 
4
 * Copyright Ericsson AB 2010. All Rights Reserved.
 
5
 *
 
6
 * The contents of this file are subject to the Erlang Public License,
 
7
 * Version 1.1, (the "License"); you may not use this file except in
 
8
 * compliance with the License. You should have received a copy of the
 
9
 * Erlang Public License along with this software. If not, it can be
 
10
 * retrieved online at http://www.erlang.org/.
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS"
 
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
14
 * the License for the specific language governing rights and limitations
 
15
 * under the License.
 
16
 *
 
17
 * %CopyrightEnd%
 
18
 */
 
19
 
 
20
/*
 
21
 * Description: Native atomics ethread support using gcc's builtins
 
22
 * Author: Rickard Green
 
23
 */
 
24
 
 
25
#undef ETHR_INCLUDE_ATOMIC_IMPL__
 
26
#if !defined(ETHR_GCC_ATOMIC32_H__) && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
 
27
#define ETHR_GCC_ATOMIC32_H__
 
28
#define ETHR_INCLUDE_ATOMIC_IMPL__ 4
 
29
#undef ETHR_ATOMIC_WANT_32BIT_IMPL__
 
30
#elif !defined(ETHR_GCC_ATOMIC64_H__) && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
 
31
#define ETHR_GCC_ATOMIC64_H__
 
32
#define ETHR_INCLUDE_ATOMIC_IMPL__ 8
 
33
#undef ETHR_ATOMIC_WANT_64BIT_IMPL__
 
34
#endif
 
35
 
 
36
#ifdef ETHR_INCLUDE_ATOMIC_IMPL__
 
37
 
 
38
#ifndef ETHR_GCC_ATOMIC_COMMON__
 
39
#define ETHR_GCC_ATOMIC_COMMON__
 
40
 
 
41
#define ETHR_READ_AND_SET_WITHOUT_SYNC_OP__ 0
 
42
#if defined(__i386__) || defined(__x86_64__) || defined(__sparc__) \
 
43
    || defined(__powerpc__) || defined(__ppc__) || defined(__mips__)
 
44
#  undef ETHR_READ_AND_SET_WITHOUT_SYNC_OP__
 
45
#  define ETHR_READ_AND_SET_WITHOUT_SYNC_OP__ 1
 
46
#endif
 
47
 
 
48
#if defined(__x86_64__) || (defined(__i386__) \
 
49
                            && !defined(ETHR_PRE_PENTIUM4_COMPAT))
 
50
#  define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 1
 
51
#else
 
52
#  define ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__ 0
 
53
#endif
 
54
 
 
55
/*
 
56
 * According to the documentation this is what we want:
 
57
 *   #define ETHR_MEMORY_BARRIER __sync_synchronize()
 
58
 * However, __sync_synchronize() is known to erroneously be
 
59
 * a noop on at least some platforms with some gcc versions.
 
60
 * This has suposedly been fixed in some gcc version, but we
 
61
 * don't know from which version. Therefore, we only use
 
62
 * it when it has been verified to work. Otherwise
 
63
 * we use a workaround.
 
64
 */
 
65
#if defined(__mips__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
 
66
/* __sync_synchronize() has been verified to work here */
 
67
#define ETHR_MEMORY_BARRIER __sync_synchronize()
 
68
#define ETHR_READ_DEPEND_MEMORY_BARRIER __sync_synchronize()
 
69
#elif defined(__x86_64__) || (defined(__i386__) \
 
70
                              && !defined(ETHR_PRE_PENTIUM4_COMPAT))
 
71
/* Use fence instructions directly instead of workaround */
 
72
#define ETHR_MEMORY_BARRIER __asm__ __volatile__("mfence" : : : "memory")
 
73
#define ETHR_WRITE_MEMORY_BARRIER __asm__ __volatile__("sfence" : : : "memory")
 
74
#define ETHR_READ_MEMORY_BARRIER __asm__ __volatile__("lfence" : : : "memory")
 
75
#define ETHR_READ_DEPEND_MEMORY_BARRIER __asm__ __volatile__("" : : : "memory")
 
76
#else
 
77
/* Workaround */
 
78
#define ETHR_MEMORY_BARRIER \
 
79
do { \
 
80
    volatile ethr_sint32_t x___ = 0; \
 
81
    (void) __sync_val_compare_and_swap(&x___, (ethr_sint32_t) 0, (ethr_sint32_t) 1); \
 
82
} while (0)
 
83
#define ETHR_READ_DEPEND_MEMORY_BARRIER ETHR_MEMORY_BARRIER
 
84
#endif
 
85
 
 
86
#define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
 
87
 
 
88
#endif /* ETHR_GCC_ATOMIC_COMMON__ */
 
89
 
 
90
#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
 
91
#define ETHR_HAVE_NATIVE_ATOMIC32 1
 
92
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
 
93
#define ETHR_ATMC_T__ ethr_native_atomic32_t
 
94
#define ETHR_AINT_T__ ethr_sint32_t
 
95
#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
 
96
#define ETHR_HAVE_NATIVE_ATOMIC64 1
 
97
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
 
98
#define ETHR_ATMC_T__ ethr_native_atomic64_t
 
99
#define ETHR_AINT_T__ ethr_sint64_t
 
100
#else
 
101
#error "Unsupported integer size"
 
102
#endif
 
103
 
 
104
typedef struct {
 
105
    volatile ETHR_AINT_T__ counter;
 
106
} ETHR_ATMC_T__;
 
107
 
 
108
 
 
109
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
 
110
 
 
111
static ETHR_INLINE ETHR_AINT_T__ *
 
112
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
 
113
{
 
114
    return (ETHR_AINT_T__ *) &var->counter;
 
115
}
 
116
 
 
117
static ETHR_INLINE void
 
118
ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
 
119
{
 
120
#if ETHR_READ_AND_SET_WITHOUT_SYNC_OP__
 
121
    var->counter = value;
 
122
#else
 
123
    /*
 
124
     * Unfortunately no __sync_store() or similar exist in the gcc atomic
 
125
     * op interface. We therefore have to simulate it this way...
 
126
     */
 
127
    ETHR_AINT_T__ act = 0, exp;
 
128
    do {
 
129
        exp = act;
 
130
        act = __sync_val_compare_and_swap(&var->counter, exp, value);
 
131
    } while (act != exp);
 
132
#endif
 
133
}
 
134
 
 
135
static ETHR_INLINE void
 
136
ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ value)
 
137
{
 
138
    ETHR_NATMC_FUNC__(set)(var, value);
 
139
}
 
140
 
 
141
static ETHR_INLINE ETHR_AINT_T__
 
142
ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
 
143
{
 
144
#if ETHR_READ_AND_SET_WITHOUT_SYNC_OP__
 
145
    return var->counter;
 
146
#else
 
147
    /*
 
148
     * Unfortunately no __sync_fetch() or similar exist in the gcc atomic
 
149
     * op interface. We therefore have to simulate it this way...
 
150
     */
 
151
    return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 0);
 
152
#endif
 
153
}
 
154
 
 
155
static ETHR_INLINE void
 
156
ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
 
157
{
 
158
    (void) __sync_add_and_fetch(&var->counter, incr);
 
159
}
 
160
 
 
161
static ETHR_INLINE ETHR_AINT_T__
 
162
ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
 
163
{
 
164
    return __sync_add_and_fetch(&var->counter, incr);
 
165
}
 
166
 
 
167
static ETHR_INLINE void
 
168
ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
 
169
{
 
170
    (void) __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
 
171
}
 
172
 
 
173
static ETHR_INLINE void
 
174
ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
 
175
{
 
176
    (void) __sync_sub_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
 
177
}
 
178
 
 
179
static ETHR_INLINE ETHR_AINT_T__
 
180
ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
 
181
{
 
182
    return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
 
183
}
 
184
 
 
185
static ETHR_INLINE ETHR_AINT_T__
 
186
ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
 
187
{
 
188
    return __sync_sub_and_fetch(&var->counter, (ETHR_AINT_T__) 1);
 
189
}
 
190
 
 
191
static ETHR_INLINE ETHR_AINT_T__
 
192
ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
 
193
{
 
194
    return __sync_fetch_and_and(&var->counter, mask);
 
195
}
 
196
 
 
197
static ETHR_INLINE ETHR_AINT_T__
 
198
ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
 
199
{
 
200
    return (ETHR_AINT_T__) __sync_fetch_and_or(&var->counter, mask);
 
201
}
 
202
 
 
203
static ETHR_INLINE ETHR_AINT_T__
 
204
ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
 
205
                           ETHR_AINT_T__ new,
 
206
                           ETHR_AINT_T__ old)
 
207
{
 
208
    return __sync_val_compare_and_swap(&var->counter, old, new);
 
209
}
 
210
 
 
211
static ETHR_INLINE ETHR_AINT_T__
 
212
ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ new)
 
213
{
 
214
    ETHR_AINT_T__ exp, act = 0;
 
215
    do {
 
216
        exp = act;
 
217
        act = __sync_val_compare_and_swap(&var->counter, exp, new);
 
218
    } while (act != exp);
 
219
    return act;
 
220
}
 
221
 
 
222
/*
 
223
 * Atomic ops with at least specified barriers.
 
224
 */
 
225
 
 
226
static ETHR_INLINE ETHR_AINT_T__
 
227
ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
 
228
{
 
229
#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
 
230
    ETHR_AINT_T__ val = var->counter;
 
231
    ETHR_COMPILER_BARRIER;
 
232
    return val;
 
233
#else
 
234
    return __sync_add_and_fetch(&var->counter, (ETHR_AINT_T__) 0);
 
235
#endif
 
236
}
 
237
 
 
238
static ETHR_INLINE void
 
239
ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
 
240
{
 
241
#if ETHR_READ_ACQB_AND_SET_RELB_COMPILER_BARRIER_ONLY__
 
242
    ETHR_COMPILER_BARRIER;
 
243
    var->counter = i;
 
244
#else
 
245
    (void) ETHR_NATMC_FUNC__(xchg)(var, i);
 
246
#endif
 
247
}
 
248
 
 
249
static ETHR_INLINE ETHR_AINT_T__
 
250
ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
 
251
{
 
252
    return ETHR_NATMC_FUNC__(inc_return)(var);
 
253
}
 
254
 
 
255
static ETHR_INLINE void
 
256
ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
 
257
{
 
258
    ETHR_NATMC_FUNC__(dec)(var);
 
259
}
 
260
 
 
261
static ETHR_INLINE ETHR_AINT_T__
 
262
ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
 
263
{
 
264
    return ETHR_NATMC_FUNC__(dec_return)(var);
 
265
}
 
266
 
 
267
static ETHR_INLINE ETHR_AINT_T__
 
268
ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
 
269
                                ETHR_AINT_T__ new,
 
270
                                ETHR_AINT_T__ old)
 
271
{
 
272
    return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
 
273
}
 
274
 
 
275
static ETHR_INLINE ETHR_AINT_T__
 
276
ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
 
277
                                ETHR_AINT_T__ new,
 
278
                                ETHR_AINT_T__ old)
 
279
{
 
280
    return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
 
281
}
 
282
 
 
283
#endif
 
284
 
 
285
#undef ETHR_NATMC_FUNC__
 
286
#undef ETHR_ATMC_T__
 
287
#undef ETHR_AINT_T__
 
288
#undef ETHR_AINT_SUFFIX__
 
289
 
 
290
#endif