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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [linuxthreads/] [spinlock.h] - Blame information for rev 148

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Linuxthreads - a simple clone()-based implementation of Posix        */
2
/* threads for Linux.                                                   */
3
/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4
/*                                                                      */
5
/* This program is free software; you can redistribute it and/or        */
6
/* modify it under the terms of the GNU Library General Public License  */
7
/* as published by the Free Software Foundation; either version 2       */
8
/* of the License, or (at your option) any later version.               */
9
/*                                                                      */
10
/* This program 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        */
13
/* GNU Library General Public License for more details.                 */
14
 
15
#include <bits/initspin.h>
16
 
17
 
18
/* There are 2 compare and swap synchronization primitives with
19
   different semantics:
20
 
21
        1. compare_and_swap, which has acquire semantics (i.e. it
22
        completes befor subsequent writes.)
23
        2. compare_and_swap_with_release_semantics, which has release
24
        semantics (it completes after previous writes.)
25
 
26
   For those platforms on which they are the same. HAS_COMPARE_AND_SWAP
27
   should be defined. For those platforms on which they are different,
28
   HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined.  */
29
 
30
#ifndef HAS_COMPARE_AND_SWAP
31
#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
32
#define HAS_COMPARE_AND_SWAP
33
#endif
34
#endif
35
 
36
#if defined(TEST_FOR_COMPARE_AND_SWAP)
37
 
38
extern int __pthread_has_cas;
39
extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
40
                                      int * spinlock);
41
 
42
static inline int compare_and_swap(long * ptr, long oldval, long newval,
43
                                   int * spinlock)
44
{
45
  if (__builtin_expect (__pthread_has_cas, 1))
46
    return __compare_and_swap(ptr, oldval, newval);
47
  else
48
    return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
49
}
50
 
51
#elif defined(HAS_COMPARE_AND_SWAP)
52
 
53
#ifdef IMPLEMENT_TAS_WITH_CAS
54
#define testandset(p) !__compare_and_swap((long int *) p, 0, 1)
55
#endif
56
 
57
#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
58
 
59
static inline int
60
compare_and_swap_with_release_semantics (long * ptr, long oldval,
61
                                         long newval, int * spinlock)
62
{
63
  return __compare_and_swap_with_release_semantics (ptr, oldval,
64
                                                    newval);
65
}
66
 
67
#endif
68
 
69
static inline int compare_and_swap(long * ptr, long oldval, long newval,
70
                                   int * spinlock)
71
{
72
  return __compare_and_swap(ptr, oldval, newval);
73
}
74
 
75
#else
76
 
77
extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
78
                                      int * spinlock);
79
 
80
static inline int compare_and_swap(long * ptr, long oldval, long newval,
81
                                   int * spinlock)
82
{
83
  return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
84
}
85
 
86
#endif
87
 
88
#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
89
#define compare_and_swap_with_release_semantics compare_and_swap
90
#define __compare_and_swap_with_release_semantics __compare_and_swap
91
#endif
92
 
93
/* Internal locks */
94
 
95
extern void internal_function __pthread_lock(struct _pthread_fastlock * lock,
96
                                             pthread_descr self);
97
extern int __pthread_unlock(struct _pthread_fastlock *lock);
98
 
99
static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
100
{
101
  lock->__status = 0;
102
  lock->__spinlock = __LT_SPINLOCK_INIT;
103
}
104
 
105
static inline int __pthread_trylock (struct _pthread_fastlock * lock)
106
{
107
#if defined TEST_FOR_COMPARE_AND_SWAP
108
  if (!__pthread_has_cas)
109
#endif
110
#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
111
  {
112
    return (testandset(&lock->__spinlock) ? EBUSY : 0);
113
  }
114
#endif
115
 
116
#if defined HAS_COMPARE_AND_SWAP
117
  do {
118
    if (lock->__status != 0) return EBUSY;
119
  } while(! __compare_and_swap(&lock->__status, 0, 1));
120
  return 0;
121
#endif
122
}
123
 
124
/* Variation of internal lock used for pthread_mutex_t, supporting
125
   timed-out waits.  Warning: do not mix these operations with the above ones
126
   over the same lock object! */
127
 
128
extern void __pthread_alt_lock(struct _pthread_fastlock * lock,
129
                               pthread_descr self);
130
 
131
extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
132
                               pthread_descr self, const struct timespec *abstime);
133
 
134
extern void __pthread_alt_unlock(struct _pthread_fastlock *lock);
135
 
136
static inline void __pthread_alt_init_lock(struct _pthread_fastlock * lock)
137
{
138
  lock->__status = 0;
139
  lock->__spinlock = __LT_SPINLOCK_INIT;
140
}
141
 
142
static inline int __pthread_alt_trylock (struct _pthread_fastlock * lock)
143
{
144
#if defined TEST_FOR_COMPARE_AND_SWAP
145
  if (!__pthread_has_cas)
146
#endif
147
#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
148
  {
149
    int res = EBUSY;
150
 
151
    if (testandset(&lock->__spinlock) == 0)
152
      {
153
        if (lock->__status == 0)
154
          {
155
            lock->__status = 1;
156
            WRITE_MEMORY_BARRIER();
157
            res = 0;
158
          }
159
        lock->__spinlock = __LT_SPINLOCK_INIT;
160
      }
161
    return res;
162
  }
163
#endif
164
 
165
#if defined HAS_COMPARE_AND_SWAP
166
  do {
167
    if (lock->__status != 0) return EBUSY;
168
  } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
169
  return 0;
170
#endif
171
}
172
 
173
/* Operations on pthread_atomic, which is defined in internals.h */
174
 
175
static inline long atomic_increment(struct pthread_atomic *pa)
176
{
177
    long oldval;
178
 
179
    do {
180
        oldval = pa->p_count;
181
    } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock));
182
 
183
    return oldval;
184
}
185
 
186
 
187
static inline long atomic_decrement(struct pthread_atomic *pa)
188
{
189
    long oldval;
190
 
191
    do {
192
        oldval = pa->p_count;
193
    } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock));
194
 
195
    return oldval;
196
}
197
 
198
 
199
static inline void
200
__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif)
201
{
202
  /* Only store a non-null peif if the thread has cancellation enabled.
203
     Otherwise pthread_cancel will unconditionally call the extricate handler,
204
     and restart the thread giving rise to forbidden spurious wakeups. */
205
  if (peif == NULL
206
      || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
207
    {
208
      /* If we are removing the extricate interface, we need to synchronize
209
         against pthread_cancel so that it does not continue with a pointer
210
         to a deallocated pthread_extricate_if struct! The thread lock
211
         is (ab)used for this synchronization purpose. */
212
      if (peif == NULL)
213
        __pthread_lock (THREAD_GETMEM(self, p_lock), self);
214
      THREAD_SETMEM(self, p_extricate, peif);
215
      if (peif == NULL)
216
        __pthread_unlock (THREAD_GETMEM(self, p_lock));
217
    }
218
}

powered by: WebSVN 2.1.0

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