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

« back to all changes in this revision

Viewing changes to erts/include/internal/i386/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
1
/*
2
2
 * %CopyrightBegin%
3
 
 * 
4
 
 * Copyright Ericsson AB 2005-2009. All Rights Reserved.
5
 
 * 
 
3
 *
 
4
 * Copyright Ericsson AB 2005-2010. All Rights Reserved.
 
5
 *
6
6
 * The contents of this file are subject to the Erlang Public License,
7
7
 * Version 1.1, (the "License"); you may not use this file except in
8
8
 * compliance with the License. You should have received a copy of the
9
9
 * Erlang Public License along with this software. If not, it can be
10
10
 * retrieved online at http://www.erlang.org/.
11
 
 * 
 
11
 *
12
12
 * Software distributed under the License is distributed on an "AS IS"
13
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
 * the License for the specific language governing rights and limitations
15
15
 * under the License.
16
 
 * 
 
16
 *
17
17
 * %CopyrightEnd%
18
18
 */
19
19
 
23
23
 *
24
24
 * This code requires a 486 or newer processor.
25
25
 */
26
 
#ifndef ETHREAD_I386_ATOMIC_H
27
 
#define ETHREAD_I386_ATOMIC_H
28
 
 
29
 
/* An atomic is an aligned long accessed via locked operations.
 
26
 
 
27
#undef ETHR_INCLUDE_ATOMIC_IMPL__
 
28
#if !defined(ETHR_X86_ATOMIC32_H__) && defined(ETHR_ATOMIC_WANT_32BIT_IMPL__)
 
29
#define ETHR_X86_ATOMIC32_H__
 
30
#define ETHR_INCLUDE_ATOMIC_IMPL__ 4
 
31
#undef ETHR_ATOMIC_WANT_32BIT_IMPL__
 
32
#elif !defined(ETHR_X86_ATOMIC64_H__) && defined(ETHR_ATOMIC_WANT_64BIT_IMPL__)
 
33
#define ETHR_X86_ATOMIC64_H__
 
34
#define ETHR_INCLUDE_ATOMIC_IMPL__ 8
 
35
#undef ETHR_ATOMIC_WANT_64BIT_IMPL__
 
36
#endif
 
37
 
 
38
#ifdef ETHR_INCLUDE_ATOMIC_IMPL__
 
39
 
 
40
#ifndef ETHR_X86_ATOMIC_COMMON__
 
41
#define ETHR_X86_ATOMIC_COMMON__
 
42
 
 
43
#define ETHR_ATOMIC_HAVE_INC_DEC_INSTRUCTIONS 1
 
44
 
 
45
#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
 
46
#define ETHR_MEMORY_BARRIER __asm__ __volatile__("mfence" : : : "memory")
 
47
#define ETHR_WRITE_MEMORY_BARRIER __asm__ __volatile__("sfence" : : : "memory")
 
48
#define ETHR_READ_MEMORY_BARRIER __asm__ __volatile__("lfence" : : : "memory")
 
49
#define ETHR_READ_DEPEND_MEMORY_BARRIER __asm__ __volatile__("" : : : "memory")
 
50
#else
 
51
#define ETHR_MEMORY_BARRIER \
 
52
do { \
 
53
    volatile ethr_sint32_t x___ = 0; \
 
54
    __asm__ __volatile__("lock; incl %0" : "=m"(x___) : "m"(x___) : "memory"); \
 
55
} while (0)
 
56
#endif
 
57
 
 
58
#endif /* ETHR_X86_ATOMIC_COMMON__ */
 
59
 
 
60
#if ETHR_INCLUDE_ATOMIC_IMPL__ == 4
 
61
#define ETHR_HAVE_NATIVE_ATOMIC32 1
 
62
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic32_ ## X
 
63
#define ETHR_ATMC_T__ ethr_native_atomic32_t
 
64
#define ETHR_AINT_T__ ethr_sint32_t
 
65
#define ETHR_AINT_SUFFIX__ "l"
 
66
#elif ETHR_INCLUDE_ATOMIC_IMPL__ == 8
 
67
#define ETHR_HAVE_NATIVE_ATOMIC64 1
 
68
#define ETHR_NATMC_FUNC__(X) ethr_native_atomic64_ ## X
 
69
#define ETHR_ATMC_T__ ethr_native_atomic64_t
 
70
#define ETHR_AINT_T__ ethr_sint64_t
 
71
#define ETHR_AINT_SUFFIX__ "q"
 
72
#else
 
73
#error "Unsupported integer size"
 
74
#endif
 
75
 
 
76
/* An atomic is an aligned ETHR_AINT_T__ accessed via locked operations.
30
77
 */
31
78
typedef struct {
32
 
    volatile long counter;
33
 
} ethr_native_atomic_t;
34
 
 
35
 
#ifdef ETHR_TRY_INLINE_FUNCS
36
 
 
37
 
#ifdef __x86_64__
38
 
#define LONG_SUFFIX "q"
39
 
#else
40
 
#define LONG_SUFFIX "l"
41
 
#endif
42
 
 
43
 
static ETHR_INLINE void
44
 
ethr_native_atomic_init(ethr_native_atomic_t *var, long i)
45
 
{
46
 
    var->counter = i;
47
 
}
48
 
#define ethr_native_atomic_set(v, i)    ethr_native_atomic_init((v), (i))
49
 
 
50
 
static ETHR_INLINE long
51
 
ethr_native_atomic_read(ethr_native_atomic_t *var)
 
79
    volatile ETHR_AINT_T__ counter;
 
80
} ETHR_ATMC_T__;
 
81
 
 
82
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
 
83
 
 
84
static ETHR_INLINE ETHR_AINT_T__ *
 
85
ETHR_NATMC_FUNC__(addr)(ETHR_ATMC_T__ *var)
 
86
{
 
87
    return (ETHR_AINT_T__ *) &var->counter;
 
88
}
 
89
 
 
90
static ETHR_INLINE void
 
91
ETHR_NATMC_FUNC__(init)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
 
92
{
 
93
    var->counter = i;
 
94
}
 
95
 
 
96
static ETHR_INLINE void
 
97
ETHR_NATMC_FUNC__(set)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
 
98
{
 
99
    var->counter = i;
 
100
}
 
101
 
 
102
static ETHR_INLINE ETHR_AINT_T__
 
103
ETHR_NATMC_FUNC__(read)(ETHR_ATMC_T__ *var)
52
104
{
53
105
    return var->counter;
54
106
}
55
107
 
56
108
static ETHR_INLINE void
57
 
ethr_native_atomic_add(ethr_native_atomic_t *var, long incr)
 
109
ETHR_NATMC_FUNC__(add)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
58
110
{
59
111
    __asm__ __volatile__(
60
 
       "lock; add" LONG_SUFFIX " %1, %0"
 
112
       "lock; add" ETHR_AINT_SUFFIX__ " %1, %0"
61
113
       : "=m"(var->counter)
62
114
       : "ir"(incr), "m"(var->counter));
63
115
}      
64
116
       
65
117
static ETHR_INLINE void
66
 
ethr_native_atomic_inc(ethr_native_atomic_t *var)
 
118
ETHR_NATMC_FUNC__(inc)(ETHR_ATMC_T__ *var)
67
119
{
68
120
    __asm__ __volatile__(
69
 
        "lock; inc" LONG_SUFFIX " %0"
 
121
        "lock; inc" ETHR_AINT_SUFFIX__ " %0"
70
122
        : "=m"(var->counter)
71
123
        : "m"(var->counter));
72
124
}
73
125
 
74
126
static ETHR_INLINE void
75
 
ethr_native_atomic_dec(ethr_native_atomic_t *var)
 
127
ETHR_NATMC_FUNC__(dec)(ETHR_ATMC_T__ *var)
76
128
{
77
129
    __asm__ __volatile__(
78
 
        "lock; dec" LONG_SUFFIX " %0"
 
130
        "lock; dec" ETHR_AINT_SUFFIX__ " %0"
79
131
        : "=m"(var->counter)
80
132
        : "m"(var->counter));
81
133
}
82
134
 
83
 
static ETHR_INLINE long
84
 
ethr_native_atomic_add_return(ethr_native_atomic_t *var, long incr)
 
135
static ETHR_INLINE ETHR_AINT_T__
 
136
ETHR_NATMC_FUNC__(add_return)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ incr)
85
137
{
86
 
    long tmp;
 
138
    ETHR_AINT_T__ tmp;
87
139
 
88
140
    tmp = incr;
89
141
    __asm__ __volatile__(
90
 
        "lock; xadd" LONG_SUFFIX " %0, %1" /* xadd didn't exist prior to the 486 */
 
142
        "lock; xadd" ETHR_AINT_SUFFIX__ " %0, %1" /* xadd didn't exist prior to the 486 */
91
143
        : "=r"(tmp)
92
144
        : "m"(var->counter), "0"(tmp));
93
145
    /* now tmp is the atomic's previous value */
94
146
    return tmp + incr;
95
147
}
96
148
 
97
 
#define ethr_native_atomic_inc_return(var) ethr_native_atomic_add_return((var), 1)
98
 
#define ethr_native_atomic_dec_return(var) ethr_native_atomic_add_return((var), -1)
99
 
 
100
 
static ETHR_INLINE long
101
 
ethr_native_atomic_cmpxchg(ethr_native_atomic_t *var, long new, long old)
 
149
static ETHR_INLINE ETHR_AINT_T__
 
150
ETHR_NATMC_FUNC__(inc_return)(ETHR_ATMC_T__ *var)
 
151
{
 
152
    return ETHR_NATMC_FUNC__(add_return)(var, (ETHR_AINT_T__) 1);
 
153
}
 
154
 
 
155
static ETHR_INLINE ETHR_AINT_T__
 
156
ETHR_NATMC_FUNC__(dec_return)(ETHR_ATMC_T__ *var)
 
157
{
 
158
    return ETHR_NATMC_FUNC__(add_return)(var, (ETHR_AINT_T__) -1);
 
159
}
 
160
 
 
161
static ETHR_INLINE ETHR_AINT_T__
 
162
ETHR_NATMC_FUNC__(cmpxchg)(ETHR_ATMC_T__ *var,
 
163
                           ETHR_AINT_T__ new,
 
164
                           ETHR_AINT_T__ old)
102
165
{
103
166
    __asm__ __volatile__(
104
 
      "lock; cmpxchg" LONG_SUFFIX " %2, %3"
 
167
      "lock; cmpxchg" ETHR_AINT_SUFFIX__ " %2, %3"
105
168
      : "=a"(old), "=m"(var->counter)
106
169
      : "r"(new), "m"(var->counter), "0"(old)
107
170
      : "cc", "memory"); /* full memory clobber to make this a compiler barrier */
108
171
    return old;
109
172
}
110
173
 
111
 
static ETHR_INLINE long
112
 
ethr_native_atomic_and_retold(ethr_native_atomic_t *var, long mask)
113
 
{
114
 
    long tmp, old;
115
 
 
116
 
    tmp = var->counter;
117
 
    do {
118
 
        old = tmp;
119
 
        tmp = ethr_native_atomic_cmpxchg(var, tmp & mask, tmp);
120
 
    } while (__builtin_expect(tmp != old, 0));
121
 
    /* now tmp is the atomic's previous value */
122
 
    return tmp;
123
 
}
124
 
 
125
 
static ETHR_INLINE long
126
 
ethr_native_atomic_or_retold(ethr_native_atomic_t *var, long mask)
127
 
{
128
 
    long tmp, old;
129
 
 
130
 
    tmp = var->counter;
131
 
    do {
132
 
        old = tmp;
133
 
        tmp = ethr_native_atomic_cmpxchg(var, tmp | mask, tmp);
134
 
    } while (__builtin_expect(tmp != old, 0));
135
 
    /* now tmp is the atomic's previous value */
136
 
    return tmp;
137
 
}
138
 
 
139
 
static ETHR_INLINE long
140
 
ethr_native_atomic_xchg(ethr_native_atomic_t *var, long val)
 
174
static ETHR_INLINE ETHR_AINT_T__
 
175
ETHR_NATMC_FUNC__(and_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
 
176
{
 
177
    ETHR_AINT_T__ tmp, old;
 
178
 
 
179
    tmp = var->counter;
 
180
    do {
 
181
        old = tmp;
 
182
        tmp = ETHR_NATMC_FUNC__(cmpxchg)(var, tmp & mask, tmp);
 
183
    } while (__builtin_expect(tmp != old, 0));
 
184
    /* now tmp is the atomic's previous value */
 
185
    return tmp;
 
186
}
 
187
 
 
188
static ETHR_INLINE ETHR_AINT_T__
 
189
ETHR_NATMC_FUNC__(or_retold)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ mask)
 
190
{
 
191
    ETHR_AINT_T__ tmp, old;
 
192
 
 
193
    tmp = var->counter;
 
194
    do {
 
195
        old = tmp;
 
196
        tmp = ETHR_NATMC_FUNC__(cmpxchg)(var, tmp | mask, tmp);
 
197
    } while (__builtin_expect(tmp != old, 0));
 
198
    /* now tmp is the atomic's previous value */
 
199
    return tmp;
 
200
}
 
201
 
 
202
static ETHR_INLINE ETHR_AINT_T__
 
203
ETHR_NATMC_FUNC__(xchg)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ val)
141
204
{   
142
 
    long tmp = val;
 
205
    ETHR_AINT_T__ tmp = val;
143
206
    __asm__ __volatile__(
144
 
        "xchg" LONG_SUFFIX " %0, %1"
 
207
        "xchg" ETHR_AINT_SUFFIX__ " %0, %1"
145
208
        : "=r"(tmp)
146
209
        : "m"(var->counter), "0"(tmp));
147
210
    /* now tmp is the atomic's previous value */ 
148
211
    return tmp;
149
212
150
213
 
151
 
#undef LONG_SUFFIX
 
214
/*
 
215
 * Atomic ops with at least specified barriers.
 
216
 */
 
217
 
 
218
static ETHR_INLINE ETHR_AINT_T__
 
219
ETHR_NATMC_FUNC__(read_acqb)(ETHR_ATMC_T__ *var)
 
220
{
 
221
    ETHR_AINT_T__ val;
 
222
#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
 
223
    val = var->counter;
 
224
#else
 
225
    val = ETHR_NATMC_FUNC__(add_return)(var, 0);
 
226
#endif
 
227
    __asm__ __volatile__("" : : : "memory");
 
228
    return val;
 
229
}
 
230
 
 
231
static ETHR_INLINE void
 
232
ETHR_NATMC_FUNC__(set_relb)(ETHR_ATMC_T__ *var, ETHR_AINT_T__ i)
 
233
{
 
234
    __asm__ __volatile__("" : : : "memory");
 
235
#if defined(__x86_64__) || !defined(ETHR_PRE_PENTIUM4_COMPAT)
 
236
    var->counter = i;
 
237
#else
 
238
    (void) ETHR_NATMC_FUNC__(xchg)(var, i);
 
239
#endif
 
240
}
 
241
 
 
242
static ETHR_INLINE ETHR_AINT_T__
 
243
ETHR_NATMC_FUNC__(inc_return_acqb)(ETHR_ATMC_T__ *var)
 
244
{
 
245
    ETHR_AINT_T__ res = ETHR_NATMC_FUNC__(inc_return)(var);
 
246
    __asm__ __volatile__("" : : : "memory");
 
247
    return res;
 
248
}
 
249
 
 
250
static ETHR_INLINE void
 
251
ETHR_NATMC_FUNC__(dec_relb)(ETHR_ATMC_T__ *var)
 
252
{
 
253
    __asm__ __volatile__("" : : : "memory");
 
254
    ETHR_NATMC_FUNC__(dec)(var);
 
255
}
 
256
 
 
257
static ETHR_INLINE ETHR_AINT_T__
 
258
ETHR_NATMC_FUNC__(dec_return_relb)(ETHR_ATMC_T__ *var)
 
259
{
 
260
    __asm__ __volatile__("" : : : "memory");
 
261
    return ETHR_NATMC_FUNC__(dec_return)(var);
 
262
}
 
263
 
 
264
static ETHR_INLINE ETHR_AINT_T__
 
265
ETHR_NATMC_FUNC__(cmpxchg_acqb)(ETHR_ATMC_T__ *var,
 
266
                                ETHR_AINT_T__ new,
 
267
                                ETHR_AINT_T__ old)
 
268
{
 
269
    return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
 
270
}
 
271
 
 
272
static ETHR_INLINE ETHR_AINT_T__
 
273
ETHR_NATMC_FUNC__(cmpxchg_relb)(ETHR_ATMC_T__ *var,
 
274
                                ETHR_AINT_T__ new,
 
275
                                ETHR_AINT_T__ old)
 
276
{
 
277
    return ETHR_NATMC_FUNC__(cmpxchg)(var, new, old);
 
278
}
152
279
 
153
280
#endif /* ETHR_TRY_INLINE_FUNCS */
154
281
 
155
 
#endif /* ETHREAD_I386_ATOMIC_H */
 
282
#undef ETHR_NATMC_FUNC__
 
283
#undef ETHR_ATMC_T__
 
284
#undef ETHR_AINT_T__
 
285
#undef ETHR_AINT_SUFFIX__
 
286
 
 
287
#endif /* ETHR_INCLUDE_ATOMIC_IMPL__ */