~ubuntu-branches/ubuntu/trusty/eglibc/trusty

« back to all changes in this revision

Viewing changes to sysdeps/unix/sysv/linux/aarch64/nptl/lowlevellock.h

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-01-10 18:39:35 UTC
  • mfrom: (1.5.2) (4.4.24 experimental)
  • Revision ID: package-import@ubuntu.com-20130110183935-afsgfxkmg7wk5eaj
Tags: 2.17-0ubuntu1
* Merge with Debian, bringing in a new upstream and many small fixes:
  - patches/any/cvs-malloc-deadlock.diff: Dropped, merged upstream.
  - patches/ubuntu/lddebug-scopes.diff: Rebase for upstream changes.
  - patches/ubuntu/local-CVE-2012-3406.diff: Rebased against upstream.
  - patches/ubuntu/no-asm-mtune-i686.diff: Fixed in recent binutils.
* This upstream merge fixes a nasty hang in pulseaudio (LP: #1085342)
* Bump MIN_KERNEL_SUPPORTED to 2.6.32 on ARM, now that we no longer
  have to support shonky 2.6.31 kernels on imx51 babbage builders.
* Drop patches/ubuntu/local-disable-nscd-host-caching.diff, as these
  issues were apparently resolved upstream a while ago (LP: #613662)
* Fix the compiled-in bug URL to point to launchpad.net, not Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2005, 2006, 2007, 2008, 2009-2012
2
 
   Free Software Foundation, Inc.
3
 
 
4
 
   This file is part of the GNU C Library.
5
 
 
6
 
   The GNU C Library is free software; you can redistribute it and/or
7
 
   modify it under the terms of the GNU Lesser General Public
8
 
   License as published by the Free Software Foundation; either
9
 
   version 2.1 of the License, or (at your option) any later version.
10
 
 
11
 
   The GNU C Library is distributed in the hope that it will be useful,
12
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
   Lesser General Public License for more details.
15
 
 
16
 
   You should have received a copy of the GNU Lesser General Public
17
 
   License along with the GNU C Library; if not, see
18
 
   <http://www.gnu.org/licenses/>.  */
19
 
 
20
 
#ifndef _LOWLEVELLOCK_H
21
 
#define _LOWLEVELLOCK_H 1
22
 
 
23
 
#include <time.h>
24
 
#include <sys/param.h>
25
 
#include <bits/pthreadtypes.h>
26
 
#include <atomic.h>
27
 
#include <sysdep.h>
28
 
#include <kernel-features.h>
29
 
 
30
 
#define FUTEX_WAIT              0
31
 
#define FUTEX_WAKE              1
32
 
#define FUTEX_REQUEUE           3
33
 
#define FUTEX_CMP_REQUEUE       4
34
 
#define FUTEX_WAKE_OP           5
35
 
#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE   ((4 << 24) | 1)
36
 
#define FUTEX_LOCK_PI           6
37
 
#define FUTEX_UNLOCK_PI         7
38
 
#define FUTEX_TRYLOCK_PI        8
39
 
#define FUTEX_WAIT_BITSET       9
40
 
#define FUTEX_WAKE_BITSET       10
41
 
#define FUTEX_PRIVATE_FLAG      128
42
 
#define FUTEX_CLOCK_REALTIME    256
43
 
 
44
 
#define FUTEX_BITSET_MATCH_ANY  0xffffffff
45
 
 
46
 
/* Values for 'private' parameter of locking macros.  Yes, the
47
 
   definition seems to be backwards.  But it is not.  The bit will be
48
 
   reversed before passing to the system call.  */
49
 
#define LLL_PRIVATE     0
50
 
#define LLL_SHARED      FUTEX_PRIVATE_FLAG
51
 
 
52
 
 
53
 
#if !defined NOT_IN_libc || defined IS_IN_rtld
54
 
/* In libc.so or ld.so all futexes are private.  */
55
 
# ifdef __ASSUME_PRIVATE_FUTEX
56
 
#  define __lll_private_flag(fl, private) \
57
 
  ((fl) | FUTEX_PRIVATE_FLAG)
58
 
# else
59
 
#  define __lll_private_flag(fl, private) \
60
 
  ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
61
 
# endif
62
 
#else
63
 
# ifdef __ASSUME_PRIVATE_FUTEX
64
 
#  define __lll_private_flag(fl, private) \
65
 
  (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
66
 
# else
67
 
#  define __lll_private_flag(fl, private) \
68
 
  (__builtin_constant_p (private)                                             \
69
 
   ? ((private) == 0                                                          \
70
 
      ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))            \
71
 
      : (fl))                                                                 \
72
 
   : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG)                                \
73
 
              & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
74
 
# endif
75
 
#endif
76
 
 
77
 
 
78
 
#define lll_futex_wait(futexp, val, private) \
79
 
  lll_futex_timed_wait(futexp, val, NULL, private)
80
 
 
81
 
#define lll_futex_timed_wait(futexp, val, timespec, private) \
82
 
  ({                                                                          \
83
 
    INTERNAL_SYSCALL_DECL (__err);                                            \
84
 
    long int __ret;                                                           \
85
 
    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
86
 
                              __lll_private_flag (FUTEX_WAIT, private),       \
87
 
                              (val), (timespec));                             \
88
 
    __ret;                                                                    \
89
 
  })
90
 
 
91
 
#define lll_futex_wake(futexp, nr, private) \
92
 
  ({                                                                          \
93
 
    INTERNAL_SYSCALL_DECL (__err);                                            \
94
 
    long int __ret;                                                           \
95
 
    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
96
 
                              __lll_private_flag (FUTEX_WAKE, private),       \
97
 
                              (nr), 0);                                       \
98
 
    __ret;                                                                    \
99
 
  })
100
 
 
101
 
#define lll_robust_dead(futexv, private) \
102
 
  do                                                                          \
103
 
    {                                                                         \
104
 
      int *__futexp = &(futexv);                                              \
105
 
      atomic_or (__futexp, FUTEX_OWNER_DIED);                                 \
106
 
      lll_futex_wake (__futexp, 1, private);                                  \
107
 
    }                                                                         \
108
 
  while (0)
109
 
 
110
 
/* Returns non-zero if error happened, zero if success.  */
111
 
#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
112
 
  ({                                                                          \
113
 
    INTERNAL_SYSCALL_DECL (__err);                                            \
114
 
    long int __ret;                                                           \
115
 
    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
116
 
                              __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
117
 
                              (nr_wake), (nr_move), (mutex), (val));          \
118
 
    INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
119
 
  })
120
 
 
121
 
 
122
 
/* Returns non-zero if error happened, zero if success.  */
123
 
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
124
 
  ({                                                                          \
125
 
    INTERNAL_SYSCALL_DECL (__err);                                            \
126
 
    long int __ret;                                                           \
127
 
    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
128
 
                              __lll_private_flag (FUTEX_WAKE_OP, private),    \
129
 
                              (nr_wake), (nr_wake2), (futexp2),               \
130
 
                              FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
131
 
    INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
132
 
  })
133
 
 
134
 
 
135
 
#define lll_trylock(lock)       \
136
 
  atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
137
 
 
138
 
#define lll_cond_trylock(lock)  \
139
 
  atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
140
 
 
141
 
#define __lll_robust_trylock(futex, id) \
142
 
  (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
143
 
#define lll_robust_trylock(lock, id) \
144
 
  __lll_robust_trylock (&(lock), id)
145
 
 
146
 
extern void __lll_lock_wait_private (int *futex) attribute_hidden;
147
 
extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
148
 
extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
149
 
 
150
 
#define __lll_lock(futex, private)                                            \
151
 
  ((void) ({                                                                  \
152
 
    int *__futex = (futex);                                                   \
153
 
    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
154
 
                                                                1, 0), 0))    \
155
 
      {                                                                       \
156
 
        if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)       \
157
 
          __lll_lock_wait_private (__futex);                                  \
158
 
        else                                                                  \
159
 
          __lll_lock_wait (__futex, private);                                 \
160
 
      }                                                                       \
161
 
  }))
162
 
#define lll_lock(futex, private) __lll_lock (&(futex), private)
163
 
 
164
 
 
165
 
#define __lll_robust_lock(futex, id, private)                                 \
166
 
  ({                                                                          \
167
 
    int *__futex = (futex);                                                   \
168
 
    int __val = 0;                                                            \
169
 
                                                                              \
170
 
    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
171
 
                                                                0), 0))       \
172
 
      __val = __lll_robust_lock_wait (__futex, private);                      \
173
 
    __val;                                                                    \
174
 
  })
175
 
#define lll_robust_lock(futex, id, private) \
176
 
  __lll_robust_lock (&(futex), id, private)
177
 
 
178
 
 
179
 
#define __lll_cond_lock(futex, private)                                       \
180
 
  ((void) ({                                                                  \
181
 
    int *__futex = (futex);                                                   \
182
 
    if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))               \
183
 
      __lll_lock_wait (__futex, private);                                     \
184
 
  }))
185
 
#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
186
 
 
187
 
 
188
 
#define lll_robust_cond_lock(futex, id, private) \
189
 
  __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
190
 
 
191
 
 
192
 
extern int __lll_timedlock_wait (int *futex, const struct timespec *,
193
 
                                 int private) attribute_hidden;
194
 
extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
195
 
                                        int private) attribute_hidden;
196
 
 
197
 
#define __lll_timedlock(futex, abstime, private)                              \
198
 
  ({                                                                          \
199
 
     int *__futex = (futex);                                                  \
200
 
     int __val = 0;                                                           \
201
 
                                                                              \
202
 
     if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))              \
203
 
       __val = __lll_timedlock_wait (__futex, abstime, private);              \
204
 
     __val;                                                                   \
205
 
  })
206
 
#define lll_timedlock(futex, abstime, private) \
207
 
  __lll_timedlock (&(futex), abstime, private)
208
 
 
209
 
 
210
 
#define __lll_robust_timedlock(futex, abstime, id, private)                   \
211
 
  ({                                                                          \
212
 
    int *__futex = (futex);                                                   \
213
 
    int __val = 0;                                                            \
214
 
                                                                              \
215
 
    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
216
 
                                                                0), 0))       \
217
 
      __val = __lll_robust_timedlock_wait (__futex, abstime, private);        \
218
 
    __val;                                                                    \
219
 
  })
220
 
#define lll_robust_timedlock(futex, abstime, id, private) \
221
 
  __lll_robust_timedlock (&(futex), abstime, id, private)
222
 
 
223
 
 
224
 
#define __lll_unlock(futex, private) \
225
 
  (void)                                                        \
226
 
    ({ int *__futex = (futex);                                  \
227
 
       int __oldval = atomic_exchange_rel (__futex, 0);         \
228
 
       if (__builtin_expect (__oldval > 1, 0))                  \
229
 
         lll_futex_wake (__futex, 1, private);                  \
230
 
    })
231
 
 
232
 
#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
233
 
 
234
 
 
235
 
#define __lll_robust_unlock(futex, private) \
236
 
  (void)                                                        \
237
 
    ({ int *__futex = (futex);                                  \
238
 
       int __oldval = atomic_exchange_rel (__futex, 0);         \
239
 
       if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))      \
240
 
         lll_futex_wake (__futex, 1, private);                  \
241
 
    })
242
 
#define lll_robust_unlock(futex, private) \
243
 
  __lll_robust_unlock(&(futex), private)
244
 
 
245
 
 
246
 
#define lll_islocked(futex) \
247
 
  (futex != 0)
248
 
 
249
 
 
250
 
/* Our internal lock implementation is identical to the binary-compatible
251
 
   mutex implementation. */
252
 
 
253
 
/* Initializers for lock.  */
254
 
#define LLL_LOCK_INITIALIZER            (0)
255
 
#define LLL_LOCK_INITIALIZER_LOCKED     (1)
256
 
 
257
 
/* The states of a lock are:
258
 
    0  -  untaken
259
 
    1  -  taken by one user
260
 
   >1  -  taken by more users */
261
 
 
262
 
/* The kernel notifies a process which uses CLONE_CLEARTID via futex
263
 
   wakeup when the clone terminates.  The memory location contains the
264
 
   thread ID while the clone is running and is reset to zero
265
 
   afterwards.  */
266
 
#define lll_wait_tid(tid) \
267
 
  do {                                  \
268
 
    __typeof (tid) __tid;               \
269
 
    while ((__tid = (tid)) != 0)        \
270
 
      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
271
 
  } while (0)
272
 
 
273
 
extern int __lll_timedwait_tid (int *, const struct timespec *)
274
 
     attribute_hidden;
275
 
 
276
 
#define lll_timedwait_tid(tid, abstime) \
277
 
  ({                                                    \
278
 
    int __res = 0;                                      \
279
 
    if ((tid) != 0)                                     \
280
 
      __res = __lll_timedwait_tid (&(tid), (abstime));  \
281
 
    __res;                                              \
282
 
  })
283
 
 
284
 
#endif  /* lowlevellock.h */