~ubuntu-branches/ubuntu/precise/eglibc/precise

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2011-10-04 17:48:26 UTC
  • mfrom: (216.1.23 oneiric)
  • Revision ID: package-import@ubuntu.com-20111004174826-2cyb9ewn3ucymlsx
Tags: 2.13-20ubuntu5
libc6-dev: Don't break the current {gnat,gcj}-4.4-base versons. LP: #853688.

Show diffs side-by-side

added added

removed removed

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