OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [newlib/] [libc/] [sys/] [linux/] [linuxthreads/] [condvar.c] - Blame information for rev 207

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/* Linuxthreads - a simple clone()-based implementation of Posix        */
2
/* threads for Linux.                                                   */
3
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4
/* and Pavel Krauz (krauz@fsid.cvut.cz).                                */
5
/*                                                                      */
6
/* This program is free software; you can redistribute it and/or        */
7
/* modify it under the terms of the GNU Library General Public License  */
8
/* as published by the Free Software Foundation; either version 2       */
9
/* of the License, or (at your option) any later version.               */
10
/*                                                                      */
11
/* This program 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        */
14
/* GNU Library General Public License for more details.                 */
15
 
16
/* Condition variables */
17
 
18
#include <errno.h>
19
#include <sched.h>
20
#include <stddef.h>
21
#include <sys/time.h>
22
#include "pthread.h"
23
#include "internals.h"
24
#include "spinlock.h"
25
#include "queue.h"
26
#include "restart.h"
27
 
28
int pthread_cond_init(pthread_cond_t *cond,
29
                      const pthread_condattr_t *cond_attr)
30
{
31
  __pthread_init_lock(&cond->__c_lock);
32
  cond->__c_waiting = NULL;
33
  return 0;
34
}
35
 
36
int pthread_cond_destroy(pthread_cond_t *cond)
37
{
38
  if (cond->__c_waiting != NULL) return EBUSY;
39
  return 0;
40
}
41
 
42
/* Function called by pthread_cancel to remove the thread from
43
   waiting on a condition variable queue. */
44
 
45
static int cond_extricate_func(void *obj, pthread_descr th)
46
{
47
  volatile pthread_descr self = thread_self();
48
  pthread_cond_t *cond = obj;
49
  int did_remove = 0;
50
 
51
  __pthread_lock(&cond->__c_lock, self);
52
  did_remove = remove_from_queue(&cond->__c_waiting, th);
53
  __pthread_unlock(&cond->__c_lock);
54
 
55
  return did_remove;
56
}
57
 
58
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
59
{
60
  volatile pthread_descr self = thread_self();
61
  pthread_extricate_if extr;
62
  int already_canceled = 0;
63
  int spurious_wakeup_count;
64
 
65
  /* Check whether the mutex is locked and owned by this thread.  */
66
  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
67
      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
68
      && mutex->__m_owner != self)
69
    return EINVAL;
70
 
71
  /* Set up extrication interface */
72
  extr.pu_object = cond;
73
  extr.pu_extricate_func = cond_extricate_func;
74
 
75
  /* Register extrication interface */
76
  THREAD_SETMEM(self, p_condvar_avail, 0);
77
  __pthread_set_own_extricate_if(self, &extr);
78
 
79
  /* Atomically enqueue thread for waiting, but only if it is not
80
     canceled. If the thread is canceled, then it will fall through the
81
     suspend call below, and then call pthread_exit without
82
     having to worry about whether it is still on the condition variable queue.
83
     This depends on pthread_cancel setting p_canceled before calling the
84
     extricate function. */
85
 
86
  __pthread_lock(&cond->__c_lock, self);
87
  if (!(THREAD_GETMEM(self, p_canceled)
88
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
89
    enqueue(&cond->__c_waiting, self);
90
  else
91
    already_canceled = 1;
92
  __pthread_unlock(&cond->__c_lock);
93
 
94
  if (already_canceled) {
95
    __pthread_set_own_extricate_if(self, 0);
96
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
97
  }
98
 
99
  pthread_mutex_unlock(mutex);
100
 
101
  spurious_wakeup_count = 0;
102
  while (1)
103
    {
104
      suspend(self);
105
      if (THREAD_GETMEM(self, p_condvar_avail) == 0
106
          && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
107
              || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
108
        {
109
          /* Count resumes that don't belong to us. */
110
          spurious_wakeup_count++;
111
          continue;
112
        }
113
      break;
114
    }
115
 
116
  __pthread_set_own_extricate_if(self, 0);
117
 
118
  /* Check for cancellation again, to provide correct cancellation
119
     point behavior */
120
 
121
  if (THREAD_GETMEM(self, p_woken_by_cancel)
122
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
123
    THREAD_SETMEM(self, p_woken_by_cancel, 0);
124
    pthread_mutex_lock(mutex);
125
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
126
  }
127
 
128
  /* Put back any resumes we caught that don't belong to us. */
129
  while (spurious_wakeup_count--)
130
    restart(self);
131
 
132
  pthread_mutex_lock(mutex);
133
  return 0;
134
}
135
 
136
static int
137
pthread_cond_timedwait_relative(pthread_cond_t *cond,
138
                                pthread_mutex_t *mutex,
139
                                const struct timespec * abstime)
140
{
141
  volatile pthread_descr self = thread_self();
142
  int already_canceled = 0;
143
  pthread_extricate_if extr;
144
  int spurious_wakeup_count;
145
 
146
  /* Check whether the mutex is locked and owned by this thread.  */
147
  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
148
      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
149
      && mutex->__m_owner != self)
150
    return EINVAL;
151
 
152
  /* Set up extrication interface */
153
  extr.pu_object = cond;
154
  extr.pu_extricate_func = cond_extricate_func;
155
 
156
  /* Register extrication interface */
157
  THREAD_SETMEM(self, p_condvar_avail, 0);
158
  __pthread_set_own_extricate_if(self, &extr);
159
 
160
  /* Enqueue to wait on the condition and check for cancellation. */
161
  __pthread_lock(&cond->__c_lock, self);
162
  if (!(THREAD_GETMEM(self, p_canceled)
163
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
164
    enqueue(&cond->__c_waiting, self);
165
  else
166
    already_canceled = 1;
167
  __pthread_unlock(&cond->__c_lock);
168
 
169
  if (already_canceled) {
170
    __pthread_set_own_extricate_if(self, 0);
171
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
172
  }
173
 
174
  pthread_mutex_unlock(mutex);
175
 
176
  spurious_wakeup_count = 0;
177
  while (1)
178
    {
179
      if (!timedsuspend(self, abstime)) {
180
        int was_on_queue;
181
 
182
        /* __pthread_lock will queue back any spurious restarts that
183
           may happen to it. */
184
 
185
        __pthread_lock(&cond->__c_lock, self);
186
        was_on_queue = remove_from_queue(&cond->__c_waiting, self);
187
        __pthread_unlock(&cond->__c_lock);
188
 
189
        if (was_on_queue) {
190
          __pthread_set_own_extricate_if(self, 0);
191
          pthread_mutex_lock(mutex);
192
          return ETIMEDOUT;
193
        }
194
 
195
        /* Eat the outstanding restart() from the signaller */
196
        suspend(self);
197
      }
198
 
199
      if (THREAD_GETMEM(self, p_condvar_avail) == 0
200
          && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
201
              || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
202
        {
203
          /* Count resumes that don't belong to us. */
204
          spurious_wakeup_count++;
205
          continue;
206
        }
207
      break;
208
    }
209
 
210
  __pthread_set_own_extricate_if(self, 0);
211
 
212
  /* The remaining logic is the same as in other cancellable waits,
213
     such as pthread_join sem_wait or pthread_cond wait. */
214
 
215
  if (THREAD_GETMEM(self, p_woken_by_cancel)
216
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
217
    THREAD_SETMEM(self, p_woken_by_cancel, 0);
218
    pthread_mutex_lock(mutex);
219
    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
220
  }
221
 
222
  /* Put back any resumes we caught that don't belong to us. */
223
  while (spurious_wakeup_count--)
224
    restart(self);
225
 
226
  pthread_mutex_lock(mutex);
227
  return 0;
228
}
229
 
230
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
231
                           const struct timespec * abstime)
232
{
233
  /* Indirect call through pointer! */
234
  return pthread_cond_timedwait_relative(cond, mutex, abstime);
235
}
236
 
237
int pthread_cond_signal(pthread_cond_t *cond)
238
{
239
  pthread_descr th;
240
 
241
  __pthread_lock(&cond->__c_lock, NULL);
242
  th = dequeue(&cond->__c_waiting);
243
  __pthread_unlock(&cond->__c_lock);
244
  if (th != NULL) {
245
    th->p_condvar_avail = 1;
246
    WRITE_MEMORY_BARRIER();
247
    restart(th);
248
  }
249
  return 0;
250
}
251
 
252
int pthread_cond_broadcast(pthread_cond_t *cond)
253
{
254
  pthread_descr tosignal, th;
255
 
256
  __pthread_lock(&cond->__c_lock, NULL);
257
  /* Copy the current state of the waiting queue and empty it */
258
  tosignal = cond->__c_waiting;
259
  cond->__c_waiting = NULL;
260
  __pthread_unlock(&cond->__c_lock);
261
  /* Now signal each process in the queue */
262
  while ((th = dequeue(&tosignal)) != NULL) {
263
    th->p_condvar_avail = 1;
264
    WRITE_MEMORY_BARRIER();
265
    restart(th);
266
  }
267
  return 0;
268
}
269
 
270
int pthread_condattr_init(pthread_condattr_t *attr)
271
{
272
  return 0;
273
}
274
 
275
int pthread_condattr_destroy(pthread_condattr_t *attr)
276
{
277
  return 0;
278
}
279
 
280
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 3
281
 
282
int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
283
{
284
  *pshared = PTHREAD_PROCESS_PRIVATE;
285
  return 0;
286
}
287
 
288
int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
289
{
290
  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
291
    return EINVAL;
292
 
293
  /* For now it is not possible to shared a conditional variable.  */
294
  if (pshared != PTHREAD_PROCESS_PRIVATE)
295
    return ENOSYS;
296
 
297
  return 0;
298
}
299
 
300
#endif /* !_ELIX_LEVEL || _ELIX_LEVEL >= 3 */
301
 

powered by: WebSVN 2.1.0

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