OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgomp/] [config/] [linux/] [lock.c] - Blame information for rev 735

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 735 jeremybenn
/* Copyright (C) 2005, 2008, 2009, 2011 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 General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   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 General Public License for
14
   more details.
15
 
16
   Under Section 7 of GPL version 3, you are granted additional
17
   permissions described in the GCC Runtime Library Exception, version
18
   3.1, as published by the Free Software Foundation.
19
 
20
   You should have received a copy of the GNU General Public License and
21
   a copy of the GCC Runtime Library Exception along with this program;
22
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
   <http://www.gnu.org/licenses/>.  */
24
 
25
/* This is a Linux specific implementation of the public OpenMP locking
26
   primitives.  This implementation uses atomic instructions and the futex
27
   syscall.  */
28
 
29
#include <string.h>
30
#include <unistd.h>
31
#include <sys/syscall.h>
32
#include "wait.h"
33
 
34
 
35
/* The internal gomp_mutex_t and the external non-recursive omp_lock_t
36
   have the same form.  Re-use it.  */
37
 
38
void
39
gomp_init_lock_30 (omp_lock_t *lock)
40
{
41
  gomp_mutex_init (lock);
42
}
43
 
44
void
45
gomp_destroy_lock_30 (omp_lock_t *lock)
46
{
47
  gomp_mutex_destroy (lock);
48
}
49
 
50
void
51
gomp_set_lock_30 (omp_lock_t *lock)
52
{
53
  gomp_mutex_lock (lock);
54
}
55
 
56
void
57
gomp_unset_lock_30 (omp_lock_t *lock)
58
{
59
  gomp_mutex_unlock (lock);
60
}
61
 
62
int
63
gomp_test_lock_30 (omp_lock_t *lock)
64
{
65
  int oldval = 0;
66
 
67
  return __atomic_compare_exchange_n (lock, &oldval, 1, false,
68
                                      MEMMODEL_ACQUIRE, MEMMODEL_RELAXED);
69
}
70
 
71
void
72
gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
73
{
74
  memset (lock, '\0', sizeof (*lock));
75
}
76
 
77
void
78
gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
79
{
80
}
81
 
82
void
83
gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
84
{
85
  void *me = gomp_icv (true);
86
 
87
  if (lock->owner != me)
88
    {
89
      gomp_mutex_lock (&lock->lock);
90
      lock->owner = me;
91
    }
92
 
93
  lock->count++;
94
}
95
 
96
void
97
gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
98
{
99
  if (--lock->count == 0)
100
    {
101
      lock->owner = NULL;
102
      gomp_mutex_unlock (&lock->lock);
103
    }
104
}
105
 
106
int
107
gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
108
{
109
  void *me = gomp_icv (true);
110
  int oldval;
111
 
112
  if (lock->owner == me)
113
    return ++lock->count;
114
 
115
  oldval = 0;
116
  if (__atomic_compare_exchange_n (&lock->lock, &oldval, 1, false,
117
                                   MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
118
    {
119
      lock->owner = me;
120
      lock->count = 1;
121
      return 1;
122
    }
123
 
124
  return 0;
125
}
126
 
127
#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
128
/* gomp_mutex_* can be safely locked in one thread and
129
   unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
130
   non-nested locks can be the same.  */
131
strong_alias (gomp_init_lock_30, gomp_init_lock_25)
132
strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25)
133
strong_alias (gomp_set_lock_30, gomp_set_lock_25)
134
strong_alias (gomp_unset_lock_30, gomp_unset_lock_25)
135
strong_alias (gomp_test_lock_30, gomp_test_lock_25)
136
 
137
/* The external recursive omp_nest_lock_25_t form requires additional work.  */
138
 
139
/* We need an integer to uniquely identify this thread.  Most generally
140
   this is the thread's TID, which ideally we'd get this straight from
141
   the TLS block where glibc keeps it.  Unfortunately, we can't get at
142
   that directly.
143
 
144
   If we don't support (or have disabled) TLS, one function call is as
145
   good (or bad) as any other.  Use the syscall all the time.
146
 
147
   On an ILP32 system (defined here as not LP64), we can make do with
148
   any thread-local pointer.  Ideally we'd use the TLS base address,
149
   since that requires the least amount of arithmetic, but that's not
150
   always available directly.  Make do with the gomp_thread pointer
151
   since it's handy.  */
152
 
153
# if !defined (HAVE_TLS)
154
static inline int gomp_tid (void)
155
{
156
  return syscall (SYS_gettid);
157
}
158
# elif !defined(__LP64__)
159
static inline int gomp_tid (void)
160
{
161
  return (int) gomp_thread ();
162
}
163
# else
164
static __thread int tid_cache;
165
static inline int gomp_tid (void)
166
{
167
  int tid = tid_cache;
168
  if (__builtin_expect (tid == 0, 0))
169
    tid_cache = tid = syscall (SYS_gettid);
170
  return tid;
171
}
172
# endif
173
 
174
 
175
void
176
gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
177
{
178
  memset (lock, 0, sizeof (lock));
179
}
180
 
181
void
182
gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
183
{
184
}
185
 
186
void
187
gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
188
{
189
  int otid, tid = gomp_tid ();
190
 
191
  while (1)
192
    {
193
      otid = 0;
194
      if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
195
                                       MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
196
        {
197
          lock->count = 1;
198
          return;
199
        }
200
      if (otid == tid)
201
        {
202
          lock->count++;
203
          return;
204
        }
205
 
206
      do_wait (&lock->owner, otid);
207
    }
208
}
209
 
210
void
211
gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
212
{
213
  /* ??? Validate that we own the lock here.  */
214
 
215
  if (--lock->count == 0)
216
    {
217
      __atomic_store_n (&lock->owner, 0, MEMMODEL_RELEASE);
218
      futex_wake (&lock->owner, 1);
219
    }
220
}
221
 
222
int
223
gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
224
{
225
  int otid, tid = gomp_tid ();
226
 
227
  otid = 0;
228
  if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
229
                                   MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
230
    {
231
      lock->count = 1;
232
      return 1;
233
    }
234
  if (otid == tid)
235
    return ++lock->count;
236
 
237
  return 0;
238
}
239
 
240
omp_lock_symver (omp_init_lock)
241
omp_lock_symver (omp_destroy_lock)
242
omp_lock_symver (omp_set_lock)
243
omp_lock_symver (omp_unset_lock)
244
omp_lock_symver (omp_test_lock)
245
omp_lock_symver (omp_init_nest_lock)
246
omp_lock_symver (omp_destroy_nest_lock)
247
omp_lock_symver (omp_set_nest_lock)
248
omp_lock_symver (omp_unset_nest_lock)
249
omp_lock_symver (omp_test_nest_lock)
250
 
251
#else
252
 
253
ialias (omp_init_lock)
254
ialias (omp_init_nest_lock)
255
ialias (omp_destroy_lock)
256
ialias (omp_destroy_nest_lock)
257
ialias (omp_set_lock)
258
ialias (omp_set_nest_lock)
259
ialias (omp_unset_lock)
260
ialias (omp_unset_nest_lock)
261
ialias (omp_test_lock)
262
ialias (omp_test_nest_lock)
263
 
264
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.