~ubuntu-branches/ubuntu/trusty/gnupg/trusty-security

« back to all changes in this revision

Viewing changes to intl/lock.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2013-08-02 11:27:51 UTC
  • mfrom: (1.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20130802112751-np45f6mcog4qj3w8
Tags: 1.4.14-1ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Disable mlock() test since it fails with ulimit 0 (on buildds).
  - Set gpg (or gpg2) and gpgsm to use a passphrase agent by default.
  - Only suggest gnupg-curl and libldap; recommendations are pulled into
    minimal, and we don't need the keyserver utilities in a minimal Ubuntu
    system.
  - Remove the Win32 build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Locking in multithreaded situations.
2
 
   Copyright (C) 2005-2006 Free Software Foundation, Inc.
 
2
   Copyright (C) 2005-2008 Free Software Foundation, Inc.
3
3
 
4
4
   This program is free software; you can redistribute it and/or modify it
5
5
   under the terms of the GNU Library General Public License as published
28
28
 
29
29
#if USE_POSIX_THREADS
30
30
 
31
 
/* Use the POSIX threads library.  */
32
 
 
33
 
# if PTHREAD_IN_USE_DETECTION_HARD
34
 
 
35
 
/* The function to be executed by a dummy thread.  */
36
 
static void *
37
 
dummy_thread_func (void *arg)
38
 
{
39
 
  return arg;
40
 
}
41
 
 
42
 
int
43
 
glthread_in_use (void)
44
 
{
45
 
  static int tested;
46
 
  static int result; /* 1: linked with -lpthread, 0: only with libc */
47
 
 
48
 
  if (!tested)
49
 
    {
50
 
      pthread_t thread;
51
 
 
52
 
      if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)
53
 
        /* Thread creation failed.  */
54
 
        result = 0;
55
 
      else
56
 
        {
57
 
          /* Thread creation works.  */
58
 
          void *retval;
59
 
          if (pthread_join (thread, &retval) != 0)
60
 
            abort ();
61
 
          result = 1;
62
 
        }
63
 
      tested = 1;
64
 
    }
65
 
  return result;
66
 
}
67
 
 
68
 
# endif
69
 
 
70
31
/* -------------------------- gl_lock_t datatype -------------------------- */
71
32
 
72
33
/* ------------------------- gl_rwlock_t datatype ------------------------- */
75
36
 
76
37
#  if !defined PTHREAD_RWLOCK_INITIALIZER
77
38
 
78
 
void
79
 
glthread_rwlock_init (gl_rwlock_t *lock)
 
39
int
 
40
glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
80
41
{
81
 
  if (pthread_rwlock_init (&lock->rwlock, NULL) != 0)
82
 
    abort ();
 
42
  int err;
 
43
 
 
44
  err = pthread_rwlock_init (&lock->rwlock, NULL);
 
45
  if (err != 0)
 
46
    return err;
83
47
  lock->initialized = 1;
84
 
}
85
 
 
86
 
void
87
 
glthread_rwlock_rdlock (gl_rwlock_t *lock)
88
 
{
89
 
  if (!lock->initialized)
90
 
    {
91
 
      if (pthread_mutex_lock (&lock->guard) != 0)
92
 
        abort ();
93
 
      if (!lock->initialized)
94
 
        glthread_rwlock_init (lock);
95
 
      if (pthread_mutex_unlock (&lock->guard) != 0)
96
 
        abort ();
97
 
    }
98
 
  if (pthread_rwlock_rdlock (&lock->rwlock) != 0)
99
 
    abort ();
100
 
}
101
 
 
102
 
void
103
 
glthread_rwlock_wrlock (gl_rwlock_t *lock)
104
 
{
105
 
  if (!lock->initialized)
106
 
    {
107
 
      if (pthread_mutex_lock (&lock->guard) != 0)
108
 
        abort ();
109
 
      if (!lock->initialized)
110
 
        glthread_rwlock_init (lock);
111
 
      if (pthread_mutex_unlock (&lock->guard) != 0)
112
 
        abort ();
113
 
    }
114
 
  if (pthread_rwlock_wrlock (&lock->rwlock) != 0)
115
 
    abort ();
116
 
}
117
 
 
118
 
void
119
 
glthread_rwlock_unlock (gl_rwlock_t *lock)
120
 
{
121
 
  if (!lock->initialized)
122
 
    abort ();
123
 
  if (pthread_rwlock_unlock (&lock->rwlock) != 0)
124
 
    abort ();
125
 
}
126
 
 
127
 
void
128
 
glthread_rwlock_destroy (gl_rwlock_t *lock)
129
 
{
130
 
  if (!lock->initialized)
131
 
    abort ();
132
 
  if (pthread_rwlock_destroy (&lock->rwlock) != 0)
133
 
    abort ();
 
48
  return 0;
 
49
}
 
50
 
 
51
int
 
52
glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
 
53
{
 
54
  if (!lock->initialized)
 
55
    {
 
56
      int err;
 
57
 
 
58
      err = pthread_mutex_lock (&lock->guard);
 
59
      if (err != 0)
 
60
        return err;
 
61
      if (!lock->initialized)
 
62
        {
 
63
          err = glthread_rwlock_init_multithreaded (lock);
 
64
          if (err != 0)
 
65
            {
 
66
              pthread_mutex_unlock (&lock->guard);
 
67
              return err;
 
68
            }
 
69
        }
 
70
      err = pthread_mutex_unlock (&lock->guard);
 
71
      if (err != 0)
 
72
        return err;
 
73
    }
 
74
  return pthread_rwlock_rdlock (&lock->rwlock);
 
75
}
 
76
 
 
77
int
 
78
glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
 
79
{
 
80
  if (!lock->initialized)
 
81
    {
 
82
      int err;
 
83
 
 
84
      err = pthread_mutex_lock (&lock->guard);
 
85
      if (err != 0)
 
86
        return err;
 
87
      if (!lock->initialized)
 
88
        {
 
89
          err = glthread_rwlock_init_multithreaded (lock);
 
90
          if (err != 0)
 
91
            {
 
92
              pthread_mutex_unlock (&lock->guard);
 
93
              return err;
 
94
            }
 
95
        }
 
96
      err = pthread_mutex_unlock (&lock->guard);
 
97
      if (err != 0)
 
98
        return err;
 
99
    }
 
100
  return pthread_rwlock_wrlock (&lock->rwlock);
 
101
}
 
102
 
 
103
int
 
104
glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
 
105
{
 
106
  if (!lock->initialized)
 
107
    return EINVAL;
 
108
  return pthread_rwlock_unlock (&lock->rwlock);
 
109
}
 
110
 
 
111
int
 
112
glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
 
113
{
 
114
  int err;
 
115
 
 
116
  if (!lock->initialized)
 
117
    return EINVAL;
 
118
  err = pthread_rwlock_destroy (&lock->rwlock);
 
119
  if (err != 0)
 
120
    return err;
134
121
  lock->initialized = 0;
 
122
  return 0;
135
123
}
136
124
 
137
125
#  endif
138
126
 
139
127
# else
140
128
 
141
 
void
142
 
glthread_rwlock_init (gl_rwlock_t *lock)
 
129
int
 
130
glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
143
131
{
144
 
  if (pthread_mutex_init (&lock->lock, NULL) != 0)
145
 
    abort ();
146
 
  if (pthread_cond_init (&lock->waiting_readers, NULL) != 0)
147
 
    abort ();
148
 
  if (pthread_cond_init (&lock->waiting_writers, NULL) != 0)
149
 
    abort ();
 
132
  int err;
 
133
 
 
134
  err = pthread_mutex_init (&lock->lock, NULL);
 
135
  if (err != 0)
 
136
    return err;
 
137
  err = pthread_cond_init (&lock->waiting_readers, NULL);
 
138
  if (err != 0)
 
139
    return err;
 
140
  err = pthread_cond_init (&lock->waiting_writers, NULL);
 
141
  if (err != 0)
 
142
    return err;
150
143
  lock->waiting_writers_count = 0;
151
144
  lock->runcount = 0;
 
145
  return 0;
152
146
}
153
147
 
154
 
void
155
 
glthread_rwlock_rdlock (gl_rwlock_t *lock)
 
148
int
 
149
glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
156
150
{
157
 
  if (pthread_mutex_lock (&lock->lock) != 0)
158
 
    abort ();
 
151
  int err;
 
152
 
 
153
  err = pthread_mutex_lock (&lock->lock);
 
154
  if (err != 0)
 
155
    return err;
159
156
  /* Test whether only readers are currently running, and whether the runcount
160
157
     field will not overflow.  */
161
158
  /* POSIX says: "It is implementation-defined whether the calling thread
165
162
  while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
166
163
    {
167
164
      /* This thread has to wait for a while.  Enqueue it among the
168
 
         waiting_readers.  */
169
 
      if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0)
170
 
        abort ();
 
165
         waiting_readers.  */
 
166
      err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
 
167
      if (err != 0)
 
168
        {
 
169
          pthread_mutex_unlock (&lock->lock);
 
170
          return err;
 
171
        }
171
172
    }
172
173
  lock->runcount++;
173
 
  if (pthread_mutex_unlock (&lock->lock) != 0)
174
 
    abort ();
 
174
  return pthread_mutex_unlock (&lock->lock);
175
175
}
176
176
 
177
 
void
178
 
glthread_rwlock_wrlock (gl_rwlock_t *lock)
 
177
int
 
178
glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
179
179
{
180
 
  if (pthread_mutex_lock (&lock->lock) != 0)
181
 
    abort ();
 
180
  int err;
 
181
 
 
182
  err = pthread_mutex_lock (&lock->lock);
 
183
  if (err != 0)
 
184
    return err;
182
185
  /* Test whether no readers or writers are currently running.  */
183
186
  while (!(lock->runcount == 0))
184
187
    {
185
188
      /* This thread has to wait for a while.  Enqueue it among the
186
 
         waiting_writers.  */
 
189
         waiting_writers.  */
187
190
      lock->waiting_writers_count++;
188
 
      if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0)
189
 
        abort ();
 
191
      err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
 
192
      if (err != 0)
 
193
        {
 
194
          lock->waiting_writers_count--;
 
195
          pthread_mutex_unlock (&lock->lock);
 
196
          return err;
 
197
        }
190
198
      lock->waiting_writers_count--;
191
199
    }
192
200
  lock->runcount--; /* runcount becomes -1 */
193
 
  if (pthread_mutex_unlock (&lock->lock) != 0)
194
 
    abort ();
 
201
  return pthread_mutex_unlock (&lock->lock);
195
202
}
196
203
 
197
 
void
198
 
glthread_rwlock_unlock (gl_rwlock_t *lock)
 
204
int
 
205
glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
199
206
{
200
 
  if (pthread_mutex_lock (&lock->lock) != 0)
201
 
    abort ();
 
207
  int err;
 
208
 
 
209
  err = pthread_mutex_lock (&lock->lock);
 
210
  if (err != 0)
 
211
    return err;
202
212
  if (lock->runcount < 0)
203
213
    {
204
214
      /* Drop a writer lock.  */
205
215
      if (!(lock->runcount == -1))
206
 
        abort ();
 
216
        {
 
217
          pthread_mutex_unlock (&lock->lock);
 
218
          return EINVAL;
 
219
        }
207
220
      lock->runcount = 0;
208
221
    }
209
222
  else
210
223
    {
211
224
      /* Drop a reader lock.  */
212
225
      if (!(lock->runcount > 0))
213
 
        abort ();
 
226
        {
 
227
          pthread_mutex_unlock (&lock->lock);
 
228
          return EINVAL;
 
229
        }
214
230
      lock->runcount--;
215
231
    }
216
232
  if (lock->runcount == 0)
217
233
    {
218
234
      /* POSIX recommends that "write locks shall take precedence over read
219
 
         locks", to avoid "writer starvation".  */
 
235
         locks", to avoid "writer starvation".  */
220
236
      if (lock->waiting_writers_count > 0)
221
 
        {
222
 
          /* Wake up one of the waiting writers.  */
223
 
          if (pthread_cond_signal (&lock->waiting_writers) != 0)
224
 
            abort ();
225
 
        }
 
237
        {
 
238
          /* Wake up one of the waiting writers.  */
 
239
          err = pthread_cond_signal (&lock->waiting_writers);
 
240
          if (err != 0)
 
241
            {
 
242
              pthread_mutex_unlock (&lock->lock);
 
243
              return err;
 
244
            }
 
245
        }
226
246
      else
227
 
        {
228
 
          /* Wake up all waiting readers.  */
229
 
          if (pthread_cond_broadcast (&lock->waiting_readers) != 0)
230
 
            abort ();
231
 
        }
 
247
        {
 
248
          /* Wake up all waiting readers.  */
 
249
          err = pthread_cond_broadcast (&lock->waiting_readers);
 
250
          if (err != 0)
 
251
            {
 
252
              pthread_mutex_unlock (&lock->lock);
 
253
              return err;
 
254
            }
 
255
        }
232
256
    }
233
 
  if (pthread_mutex_unlock (&lock->lock) != 0)
234
 
    abort ();
 
257
  return pthread_mutex_unlock (&lock->lock);
235
258
}
236
259
 
237
 
void
238
 
glthread_rwlock_destroy (gl_rwlock_t *lock)
 
260
int
 
261
glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
239
262
{
240
 
  if (pthread_mutex_destroy (&lock->lock) != 0)
241
 
    abort ();
242
 
  if (pthread_cond_destroy (&lock->waiting_readers) != 0)
243
 
    abort ();
244
 
  if (pthread_cond_destroy (&lock->waiting_writers) != 0)
245
 
    abort ();
 
263
  int err;
 
264
 
 
265
  err = pthread_mutex_destroy (&lock->lock);
 
266
  if (err != 0)
 
267
    return err;
 
268
  err = pthread_cond_destroy (&lock->waiting_readers);
 
269
  if (err != 0)
 
270
    return err;
 
271
  err = pthread_cond_destroy (&lock->waiting_writers);
 
272
  if (err != 0)
 
273
    return err;
 
274
  return 0;
246
275
}
247
276
 
248
277
# endif
251
280
 
252
281
# if HAVE_PTHREAD_MUTEX_RECURSIVE
253
282
 
254
 
#  if !(defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
255
 
 
256
 
void
257
 
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
258
 
{
259
 
  pthread_mutexattr_t attributes;
260
 
 
261
 
  if (pthread_mutexattr_init (&attributes) != 0)
262
 
    abort ();
263
 
  if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0)
264
 
    abort ();
265
 
  if (pthread_mutex_init (&lock->recmutex, &attributes) != 0)
266
 
    abort ();
267
 
  if (pthread_mutexattr_destroy (&attributes) != 0)
268
 
    abort ();
 
283
#  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
 
284
 
 
285
int
 
286
glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
 
287
{
 
288
  pthread_mutexattr_t attributes;
 
289
  int err;
 
290
 
 
291
  err = pthread_mutexattr_init (&attributes);
 
292
  if (err != 0)
 
293
    return err;
 
294
  err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
 
295
  if (err != 0)
 
296
    {
 
297
      pthread_mutexattr_destroy (&attributes);
 
298
      return err;
 
299
    }
 
300
  err = pthread_mutex_init (lock, &attributes);
 
301
  if (err != 0)
 
302
    {
 
303
      pthread_mutexattr_destroy (&attributes);
 
304
      return err;
 
305
    }
 
306
  err = pthread_mutexattr_destroy (&attributes);
 
307
  if (err != 0)
 
308
    return err;
 
309
  return 0;
 
310
}
 
311
 
 
312
#  else
 
313
 
 
314
int
 
315
glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
 
316
{
 
317
  pthread_mutexattr_t attributes;
 
318
  int err;
 
319
 
 
320
  err = pthread_mutexattr_init (&attributes);
 
321
  if (err != 0)
 
322
    return err;
 
323
  err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
 
324
  if (err != 0)
 
325
    {
 
326
      pthread_mutexattr_destroy (&attributes);
 
327
      return err;
 
328
    }
 
329
  err = pthread_mutex_init (&lock->recmutex, &attributes);
 
330
  if (err != 0)
 
331
    {
 
332
      pthread_mutexattr_destroy (&attributes);
 
333
      return err;
 
334
    }
 
335
  err = pthread_mutexattr_destroy (&attributes);
 
336
  if (err != 0)
 
337
    return err;
269
338
  lock->initialized = 1;
 
339
  return 0;
270
340
}
271
341
 
272
 
void
273
 
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
 
342
int
 
343
glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
274
344
{
275
345
  if (!lock->initialized)
276
346
    {
277
 
      if (pthread_mutex_lock (&lock->guard) != 0)
278
 
        abort ();
 
347
      int err;
 
348
 
 
349
      err = pthread_mutex_lock (&lock->guard);
 
350
      if (err != 0)
 
351
        return err;
279
352
      if (!lock->initialized)
280
 
        glthread_recursive_lock_init (lock);
281
 
      if (pthread_mutex_unlock (&lock->guard) != 0)
282
 
        abort ();
 
353
        {
 
354
          err = glthread_recursive_lock_init_multithreaded (lock);
 
355
          if (err != 0)
 
356
            {
 
357
              pthread_mutex_unlock (&lock->guard);
 
358
              return err;
 
359
            }
 
360
        }
 
361
      err = pthread_mutex_unlock (&lock->guard);
 
362
      if (err != 0)
 
363
        return err;
283
364
    }
284
 
  if (pthread_mutex_lock (&lock->recmutex) != 0)
285
 
    abort ();
286
 
}
287
 
 
288
 
void
289
 
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
290
 
{
291
 
  if (!lock->initialized)
292
 
    abort ();
293
 
  if (pthread_mutex_unlock (&lock->recmutex) != 0)
294
 
    abort ();
295
 
}
296
 
 
297
 
void
298
 
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
299
 
{
300
 
  if (!lock->initialized)
301
 
    abort ();
302
 
  if (pthread_mutex_destroy (&lock->recmutex) != 0)
303
 
    abort ();
 
365
  return pthread_mutex_lock (&lock->recmutex);
 
366
}
 
367
 
 
368
int
 
369
glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
 
370
{
 
371
  if (!lock->initialized)
 
372
    return EINVAL;
 
373
  return pthread_mutex_unlock (&lock->recmutex);
 
374
}
 
375
 
 
376
int
 
377
glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
 
378
{
 
379
  int err;
 
380
 
 
381
  if (!lock->initialized)
 
382
    return EINVAL;
 
383
  err = pthread_mutex_destroy (&lock->recmutex);
 
384
  if (err != 0)
 
385
    return err;
304
386
  lock->initialized = 0;
 
387
  return 0;
305
388
}
306
389
 
307
390
#  endif
308
391
 
309
392
# else
310
393
 
311
 
void
312
 
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
 
394
int
 
395
glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
313
396
{
314
 
  if (pthread_mutex_init (&lock->mutex, NULL) != 0)
315
 
    abort ();
 
397
  int err;
 
398
 
 
399
  err = pthread_mutex_init (&lock->mutex, NULL);
 
400
  if (err != 0)
 
401
    return err;
316
402
  lock->owner = (pthread_t) 0;
317
403
  lock->depth = 0;
 
404
  return 0;
318
405
}
319
406
 
320
 
void
321
 
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
 
407
int
 
408
glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
322
409
{
323
410
  pthread_t self = pthread_self ();
324
411
  if (lock->owner != self)
325
412
    {
326
 
      if (pthread_mutex_lock (&lock->mutex) != 0)
327
 
        abort ();
 
413
      int err;
 
414
 
 
415
      err = pthread_mutex_lock (&lock->mutex);
 
416
      if (err != 0)
 
417
        return err;
328
418
      lock->owner = self;
329
419
    }
330
420
  if (++(lock->depth) == 0) /* wraparound? */
331
 
    abort ();
 
421
    {
 
422
      lock->depth--;
 
423
      return EAGAIN;
 
424
    }
 
425
  return 0;
332
426
}
333
427
 
334
 
void
335
 
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
 
428
int
 
429
glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
336
430
{
337
431
  if (lock->owner != pthread_self ())
338
 
    abort ();
 
432
    return EPERM;
339
433
  if (lock->depth == 0)
340
 
    abort ();
 
434
    return EINVAL;
341
435
  if (--(lock->depth) == 0)
342
436
    {
343
437
      lock->owner = (pthread_t) 0;
344
 
      if (pthread_mutex_unlock (&lock->mutex) != 0)
345
 
        abort ();
 
438
      return pthread_mutex_unlock (&lock->mutex);
346
439
    }
 
440
  else
 
441
    return 0;
347
442
}
348
443
 
349
 
void
350
 
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
 
444
int
 
445
glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
351
446
{
352
447
  if (lock->owner != (pthread_t) 0)
353
 
    abort ();
354
 
  if (pthread_mutex_destroy (&lock->mutex) != 0)
355
 
    abort ();
 
448
    return EBUSY;
 
449
  return pthread_mutex_destroy (&lock->mutex);
356
450
}
357
451
 
358
452
# endif
393
487
 
394
488
/* -------------------------- gl_once_t datatype -------------------------- */
395
489
 
396
 
void
 
490
static void
397
491
glthread_once_call (void *arg)
398
492
{
399
493
  void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
402
496
}
403
497
 
404
498
int
 
499
glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void))
 
500
{
 
501
  void (*temp) (void) = initfunction;
 
502
  return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0);
 
503
}
 
504
 
 
505
int
405
506
glthread_once_singlethreaded (pth_once_t *once_control)
406
507
{
407
508
  /* We know that pth_once_t is an integer type.  */
429
530
 
430
531
/* --------------------- gl_recursive_lock_t datatype --------------------- */
431
532
 
432
 
void
433
 
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
 
533
int
 
534
glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
434
535
{
435
 
  if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0)
436
 
    abort ();
 
536
  int err;
 
537
 
 
538
  err = mutex_init (&lock->mutex, USYNC_THREAD, NULL);
 
539
  if (err != 0)
 
540
    return err;
437
541
  lock->owner = (thread_t) 0;
438
542
  lock->depth = 0;
 
543
  return 0;
439
544
}
440
545
 
441
 
void
442
 
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
 
546
int
 
547
glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
443
548
{
444
549
  thread_t self = thr_self ();
445
550
  if (lock->owner != self)
446
551
    {
447
 
      if (mutex_lock (&lock->mutex) != 0)
448
 
        abort ();
 
552
      int err;
 
553
 
 
554
      err = mutex_lock (&lock->mutex);
 
555
      if (err != 0)
 
556
        return err;
449
557
      lock->owner = self;
450
558
    }
451
559
  if (++(lock->depth) == 0) /* wraparound? */
452
 
    abort ();
 
560
    {
 
561
      lock->depth--;
 
562
      return EAGAIN;
 
563
    }
 
564
  return 0;
453
565
}
454
566
 
455
 
void
456
 
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
 
567
int
 
568
glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
457
569
{
458
570
  if (lock->owner != thr_self ())
459
 
    abort ();
 
571
    return EPERM;
460
572
  if (lock->depth == 0)
461
 
    abort ();
 
573
    return EINVAL;
462
574
  if (--(lock->depth) == 0)
463
575
    {
464
576
      lock->owner = (thread_t) 0;
465
 
      if (mutex_unlock (&lock->mutex) != 0)
466
 
        abort ();
 
577
      return mutex_unlock (&lock->mutex);
467
578
    }
 
579
  else
 
580
    return 0;
468
581
}
469
582
 
470
 
void
471
 
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
 
583
int
 
584
glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
472
585
{
473
586
  if (lock->owner != (thread_t) 0)
474
 
    abort ();
475
 
  if (mutex_destroy (&lock->mutex) != 0)
476
 
    abort ();
 
587
    return EBUSY;
 
588
  return mutex_destroy (&lock->mutex);
477
589
}
478
590
 
479
591
/* -------------------------- gl_once_t datatype -------------------------- */
480
592
 
481
 
void
482
 
glthread_once (gl_once_t *once_control, void (*initfunction) (void))
 
593
int
 
594
glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void))
483
595
{
484
596
  if (!once_control->inited)
485
597
    {
 
598
      int err;
 
599
 
486
600
      /* Use the mutex to guarantee that if another thread is already calling
487
 
         the initfunction, this thread waits until it's finished.  */
488
 
      if (mutex_lock (&once_control->mutex) != 0)
489
 
        abort ();
 
601
         the initfunction, this thread waits until it's finished.  */
 
602
      err = mutex_lock (&once_control->mutex);
 
603
      if (err != 0)
 
604
        return err;
490
605
      if (!once_control->inited)
491
 
        {
492
 
          once_control->inited = 1;
493
 
          initfunction ();
494
 
        }
495
 
      if (mutex_unlock (&once_control->mutex) != 0)
496
 
        abort ();
 
606
        {
 
607
          once_control->inited = 1;
 
608
          initfunction ();
 
609
        }
 
610
      return mutex_unlock (&once_control->mutex);
497
611
    }
 
612
  else
 
613
    return 0;
498
614
}
499
615
 
500
616
int
520
636
/* -------------------------- gl_lock_t datatype -------------------------- */
521
637
 
522
638
void
523
 
glthread_lock_init (gl_lock_t *lock)
 
639
glthread_lock_init_func (gl_lock_t *lock)
524
640
{
525
641
  InitializeCriticalSection (&lock->lock);
526
642
  lock->guard.done = 1;
527
643
}
528
644
 
529
 
void
530
 
glthread_lock_lock (gl_lock_t *lock)
 
645
int
 
646
glthread_lock_lock_func (gl_lock_t *lock)
531
647
{
532
648
  if (!lock->guard.done)
533
649
    {
534
650
      if (InterlockedIncrement (&lock->guard.started) == 0)
535
 
        /* This thread is the first one to need this lock.  Initialize it.  */
536
 
        glthread_lock_init (lock);
 
651
        /* This thread is the first one to need this lock.  Initialize it.  */
 
652
        glthread_lock_init (lock);
537
653
      else
538
 
        /* Yield the CPU while waiting for another thread to finish
539
 
           initializing this lock.  */
540
 
        while (!lock->guard.done)
541
 
          Sleep (0);
 
654
        /* Yield the CPU while waiting for another thread to finish
 
655
           initializing this lock.  */
 
656
        while (!lock->guard.done)
 
657
          Sleep (0);
542
658
    }
543
659
  EnterCriticalSection (&lock->lock);
 
660
  return 0;
544
661
}
545
662
 
546
 
void
547
 
glthread_lock_unlock (gl_lock_t *lock)
 
663
int
 
664
glthread_lock_unlock_func (gl_lock_t *lock)
548
665
{
549
666
  if (!lock->guard.done)
550
 
    abort ();
 
667
    return EINVAL;
551
668
  LeaveCriticalSection (&lock->lock);
 
669
  return 0;
552
670
}
553
671
 
554
 
void
555
 
glthread_lock_destroy (gl_lock_t *lock)
 
672
int
 
673
glthread_lock_destroy_func (gl_lock_t *lock)
556
674
{
557
675
  if (!lock->guard.done)
558
 
    abort ();
 
676
    return EINVAL;
559
677
  DeleteCriticalSection (&lock->lock);
560
678
  lock->guard.done = 0;
 
679
  return 0;
561
680
}
562
681
 
563
682
/* ------------------------- gl_rwlock_t datatype ------------------------- */
564
683
 
 
684
/* In this file, the waitqueues are implemented as circular arrays.  */
 
685
#define gl_waitqueue_t gl_carray_waitqueue_t
 
686
 
565
687
static inline void
566
688
gl_waitqueue_init (gl_waitqueue_t *wq)
567
689
{
583
705
    {
584
706
      unsigned int new_alloc = 2 * wq->alloc + 1;
585
707
      HANDLE *new_array =
586
 
        (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
 
708
        (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
587
709
      if (new_array == NULL)
588
 
        /* No more memory.  */
589
 
        return INVALID_HANDLE_VALUE;
 
710
        /* No more memory.  */
 
711
        return INVALID_HANDLE_VALUE;
590
712
      /* Now is a good opportunity to rotate the array so that its contents
591
 
         starts at offset 0.  */
 
713
         starts at offset 0.  */
592
714
      if (wq->offset > 0)
593
 
        {
594
 
          unsigned int old_count = wq->count;
595
 
          unsigned int old_alloc = wq->alloc;
596
 
          unsigned int old_offset = wq->offset;
597
 
          unsigned int i;
598
 
          if (old_offset + old_count > old_alloc)
599
 
            {
600
 
              unsigned int limit = old_offset + old_count - old_alloc;
601
 
              for (i = 0; i < limit; i++)
602
 
                new_array[old_alloc + i] = new_array[i];
603
 
            }
604
 
          for (i = 0; i < old_count; i++)
605
 
            new_array[i] = new_array[old_offset + i];
606
 
          wq->offset = 0;
607
 
        }
 
715
        {
 
716
          unsigned int old_count = wq->count;
 
717
          unsigned int old_alloc = wq->alloc;
 
718
          unsigned int old_offset = wq->offset;
 
719
          unsigned int i;
 
720
          if (old_offset + old_count > old_alloc)
 
721
            {
 
722
              unsigned int limit = old_offset + old_count - old_alloc;
 
723
              for (i = 0; i < limit; i++)
 
724
                new_array[old_alloc + i] = new_array[i];
 
725
            }
 
726
          for (i = 0; i < old_count; i++)
 
727
            new_array[i] = new_array[old_offset + i];
 
728
          wq->offset = 0;
 
729
        }
608
730
      wq->array = new_array;
609
731
      wq->alloc = new_alloc;
610
732
    }
 
733
  /* Whether the created event is a manual-reset one or an auto-reset one,
 
734
     does not matter, since we will wait on it only once.  */
611
735
  event = CreateEvent (NULL, TRUE, FALSE, NULL);
612
736
  if (event == INVALID_HANDLE_VALUE)
613
737
    /* No way to allocate an event.  */
641
765
    {
642
766
      unsigned int index = wq->offset + i;
643
767
      if (index >= wq->alloc)
644
 
        index -= wq->alloc;
 
768
        index -= wq->alloc;
645
769
      SetEvent (wq->array[index]);
646
770
    }
647
771
  wq->count = 0;
649
773
}
650
774
 
651
775
void
652
 
glthread_rwlock_init (gl_rwlock_t *lock)
 
776
glthread_rwlock_init_func (gl_rwlock_t *lock)
653
777
{
654
778
  InitializeCriticalSection (&lock->lock);
655
779
  gl_waitqueue_init (&lock->waiting_readers);
658
782
  lock->guard.done = 1;
659
783
}
660
784
 
661
 
void
662
 
glthread_rwlock_rdlock (gl_rwlock_t *lock)
 
785
int
 
786
glthread_rwlock_rdlock_func (gl_rwlock_t *lock)
663
787
{
664
788
  if (!lock->guard.done)
665
789
    {
666
790
      if (InterlockedIncrement (&lock->guard.started) == 0)
667
 
        /* This thread is the first one to need this lock.  Initialize it.  */
668
 
        glthread_rwlock_init (lock);
 
791
        /* This thread is the first one to need this lock.  Initialize it.  */
 
792
        glthread_rwlock_init (lock);
669
793
      else
670
 
        /* Yield the CPU while waiting for another thread to finish
671
 
           initializing this lock.  */
672
 
        while (!lock->guard.done)
673
 
          Sleep (0);
 
794
        /* Yield the CPU while waiting for another thread to finish
 
795
           initializing this lock.  */
 
796
        while (!lock->guard.done)
 
797
          Sleep (0);
674
798
    }
675
799
  EnterCriticalSection (&lock->lock);
676
800
  /* Test whether only readers are currently running, and whether the runcount
678
802
  if (!(lock->runcount + 1 > 0))
679
803
    {
680
804
      /* This thread has to wait for a while.  Enqueue it among the
681
 
         waiting_readers.  */
 
805
         waiting_readers.  */
682
806
      HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
683
807
      if (event != INVALID_HANDLE_VALUE)
684
 
        {
685
 
          DWORD result;
686
 
          LeaveCriticalSection (&lock->lock);
687
 
          /* Wait until another thread signals this event.  */
688
 
          result = WaitForSingleObject (event, INFINITE);
689
 
          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
690
 
            abort ();
691
 
          CloseHandle (event);
692
 
          /* The thread which signalled the event already did the bookkeeping:
693
 
             removed us from the waiting_readers, incremented lock->runcount.  */
694
 
          if (!(lock->runcount > 0))
695
 
            abort ();
696
 
          return;
697
 
        }
 
808
        {
 
809
          DWORD result;
 
810
          LeaveCriticalSection (&lock->lock);
 
811
          /* Wait until another thread signals this event.  */
 
812
          result = WaitForSingleObject (event, INFINITE);
 
813
          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
 
814
            abort ();
 
815
          CloseHandle (event);
 
816
          /* The thread which signalled the event already did the bookkeeping:
 
817
             removed us from the waiting_readers, incremented lock->runcount.  */
 
818
          if (!(lock->runcount > 0))
 
819
            abort ();
 
820
          return 0;
 
821
        }
698
822
      else
699
 
        {
700
 
          /* Allocation failure.  Weird.  */
701
 
          do
702
 
            {
703
 
              LeaveCriticalSection (&lock->lock);
704
 
              Sleep (1);
705
 
              EnterCriticalSection (&lock->lock);
706
 
            }
707
 
          while (!(lock->runcount + 1 > 0));
708
 
        }
 
823
        {
 
824
          /* Allocation failure.  Weird.  */
 
825
          do
 
826
            {
 
827
              LeaveCriticalSection (&lock->lock);
 
828
              Sleep (1);
 
829
              EnterCriticalSection (&lock->lock);
 
830
            }
 
831
          while (!(lock->runcount + 1 > 0));
 
832
        }
709
833
    }
710
834
  lock->runcount++;
711
835
  LeaveCriticalSection (&lock->lock);
 
836
  return 0;
712
837
}
713
838
 
714
 
void
715
 
glthread_rwlock_wrlock (gl_rwlock_t *lock)
 
839
int
 
840
glthread_rwlock_wrlock_func (gl_rwlock_t *lock)
716
841
{
717
842
  if (!lock->guard.done)
718
843
    {
719
844
      if (InterlockedIncrement (&lock->guard.started) == 0)
720
 
        /* This thread is the first one to need this lock.  Initialize it.  */
721
 
        glthread_rwlock_init (lock);
 
845
        /* This thread is the first one to need this lock.  Initialize it.  */
 
846
        glthread_rwlock_init (lock);
722
847
      else
723
 
        /* Yield the CPU while waiting for another thread to finish
724
 
           initializing this lock.  */
725
 
        while (!lock->guard.done)
726
 
          Sleep (0);
 
848
        /* Yield the CPU while waiting for another thread to finish
 
849
           initializing this lock.  */
 
850
        while (!lock->guard.done)
 
851
          Sleep (0);
727
852
    }
728
853
  EnterCriticalSection (&lock->lock);
729
854
  /* Test whether no readers or writers are currently running.  */
730
855
  if (!(lock->runcount == 0))
731
856
    {
732
857
      /* This thread has to wait for a while.  Enqueue it among the
733
 
         waiting_writers.  */
 
858
         waiting_writers.  */
734
859
      HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
735
860
      if (event != INVALID_HANDLE_VALUE)
736
 
        {
737
 
          DWORD result;
738
 
          LeaveCriticalSection (&lock->lock);
739
 
          /* Wait until another thread signals this event.  */
740
 
          result = WaitForSingleObject (event, INFINITE);
741
 
          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
742
 
            abort ();
743
 
          CloseHandle (event);
744
 
          /* The thread which signalled the event already did the bookkeeping:
745
 
             removed us from the waiting_writers, set lock->runcount = -1.  */
746
 
          if (!(lock->runcount == -1))
747
 
            abort ();
748
 
          return;
749
 
        }
 
861
        {
 
862
          DWORD result;
 
863
          LeaveCriticalSection (&lock->lock);
 
864
          /* Wait until another thread signals this event.  */
 
865
          result = WaitForSingleObject (event, INFINITE);
 
866
          if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
 
867
            abort ();
 
868
          CloseHandle (event);
 
869
          /* The thread which signalled the event already did the bookkeeping:
 
870
             removed us from the waiting_writers, set lock->runcount = -1.  */
 
871
          if (!(lock->runcount == -1))
 
872
            abort ();
 
873
          return 0;
 
874
        }
750
875
      else
751
 
        {
752
 
          /* Allocation failure.  Weird.  */
753
 
          do
754
 
            {
755
 
              LeaveCriticalSection (&lock->lock);
756
 
              Sleep (1);
757
 
              EnterCriticalSection (&lock->lock);
758
 
            }
759
 
          while (!(lock->runcount == 0));
760
 
        }
 
876
        {
 
877
          /* Allocation failure.  Weird.  */
 
878
          do
 
879
            {
 
880
              LeaveCriticalSection (&lock->lock);
 
881
              Sleep (1);
 
882
              EnterCriticalSection (&lock->lock);
 
883
            }
 
884
          while (!(lock->runcount == 0));
 
885
        }
761
886
    }
762
887
  lock->runcount--; /* runcount becomes -1 */
763
888
  LeaveCriticalSection (&lock->lock);
 
889
  return 0;
764
890
}
765
891
 
766
 
void
767
 
glthread_rwlock_unlock (gl_rwlock_t *lock)
 
892
int
 
893
glthread_rwlock_unlock_func (gl_rwlock_t *lock)
768
894
{
769
895
  if (!lock->guard.done)
770
 
    abort ();
 
896
    return EINVAL;
771
897
  EnterCriticalSection (&lock->lock);
772
898
  if (lock->runcount < 0)
773
899
    {
774
900
      /* Drop a writer lock.  */
775
901
      if (!(lock->runcount == -1))
776
 
        abort ();
 
902
        abort ();
777
903
      lock->runcount = 0;
778
904
    }
779
905
  else
780
906
    {
781
907
      /* Drop a reader lock.  */
782
908
      if (!(lock->runcount > 0))
783
 
        abort ();
 
909
        {
 
910
          LeaveCriticalSection (&lock->lock);
 
911
          return EPERM;
 
912
        }
784
913
      lock->runcount--;
785
914
    }
786
915
  if (lock->runcount == 0)
787
916
    {
788
917
      /* POSIX recommends that "write locks shall take precedence over read
789
 
         locks", to avoid "writer starvation".  */
 
918
         locks", to avoid "writer starvation".  */
790
919
      if (lock->waiting_writers.count > 0)
791
 
        {
792
 
          /* Wake up one of the waiting writers.  */
793
 
          lock->runcount--;
794
 
          gl_waitqueue_notify_first (&lock->waiting_writers);
795
 
        }
 
920
        {
 
921
          /* Wake up one of the waiting writers.  */
 
922
          lock->runcount--;
 
923
          gl_waitqueue_notify_first (&lock->waiting_writers);
 
924
        }
796
925
      else
797
 
        {
798
 
          /* Wake up all waiting readers.  */
799
 
          lock->runcount += lock->waiting_readers.count;
800
 
          gl_waitqueue_notify_all (&lock->waiting_readers);
801
 
        }
 
926
        {
 
927
          /* Wake up all waiting readers.  */
 
928
          lock->runcount += lock->waiting_readers.count;
 
929
          gl_waitqueue_notify_all (&lock->waiting_readers);
 
930
        }
802
931
    }
803
932
  LeaveCriticalSection (&lock->lock);
 
933
  return 0;
804
934
}
805
935
 
806
 
void
807
 
glthread_rwlock_destroy (gl_rwlock_t *lock)
 
936
int
 
937
glthread_rwlock_destroy_func (gl_rwlock_t *lock)
808
938
{
809
939
  if (!lock->guard.done)
810
 
    abort ();
 
940
    return EINVAL;
811
941
  if (lock->runcount != 0)
812
 
    abort ();
 
942
    return EBUSY;
813
943
  DeleteCriticalSection (&lock->lock);
814
944
  if (lock->waiting_readers.array != NULL)
815
945
    free (lock->waiting_readers.array);
816
946
  if (lock->waiting_writers.array != NULL)
817
947
    free (lock->waiting_writers.array);
818
948
  lock->guard.done = 0;
 
949
  return 0;
819
950
}
820
951
 
821
952
/* --------------------- gl_recursive_lock_t datatype --------------------- */
822
953
 
823
954
void
824
 
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
 
955
glthread_recursive_lock_init_func (gl_recursive_lock_t *lock)
825
956
{
826
957
  lock->owner = 0;
827
958
  lock->depth = 0;
829
960
  lock->guard.done = 1;
830
961
}
831
962
 
832
 
void
833
 
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
 
963
int
 
964
glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock)
834
965
{
835
966
  if (!lock->guard.done)
836
967
    {
837
968
      if (InterlockedIncrement (&lock->guard.started) == 0)
838
 
        /* This thread is the first one to need this lock.  Initialize it.  */
839
 
        glthread_recursive_lock_init (lock);
 
969
        /* This thread is the first one to need this lock.  Initialize it.  */
 
970
        glthread_recursive_lock_init (lock);
840
971
      else
841
 
        /* Yield the CPU while waiting for another thread to finish
842
 
           initializing this lock.  */
843
 
        while (!lock->guard.done)
844
 
          Sleep (0);
 
972
        /* Yield the CPU while waiting for another thread to finish
 
973
           initializing this lock.  */
 
974
        while (!lock->guard.done)
 
975
          Sleep (0);
845
976
    }
846
977
  {
847
978
    DWORD self = GetCurrentThreadId ();
848
979
    if (lock->owner != self)
849
980
      {
850
 
        EnterCriticalSection (&lock->lock);
851
 
        lock->owner = self;
 
981
        EnterCriticalSection (&lock->lock);
 
982
        lock->owner = self;
852
983
      }
853
984
    if (++(lock->depth) == 0) /* wraparound? */
854
 
      abort ();
 
985
      {
 
986
        lock->depth--;
 
987
        return EAGAIN;
 
988
      }
855
989
  }
 
990
  return 0;
856
991
}
857
992
 
858
 
void
859
 
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
 
993
int
 
994
glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock)
860
995
{
861
996
  if (lock->owner != GetCurrentThreadId ())
862
 
    abort ();
 
997
    return EPERM;
863
998
  if (lock->depth == 0)
864
 
    abort ();
 
999
    return EINVAL;
865
1000
  if (--(lock->depth) == 0)
866
1001
    {
867
1002
      lock->owner = 0;
868
1003
      LeaveCriticalSection (&lock->lock);
869
1004
    }
 
1005
  return 0;
870
1006
}
871
1007
 
872
 
void
873
 
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
 
1008
int
 
1009
glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock)
874
1010
{
875
1011
  if (lock->owner != 0)
876
 
    abort ();
 
1012
    return EBUSY;
877
1013
  DeleteCriticalSection (&lock->lock);
878
1014
  lock->guard.done = 0;
 
1015
  return 0;
879
1016
}
880
1017
 
881
1018
/* -------------------------- gl_once_t datatype -------------------------- */
882
1019
 
883
1020
void
884
 
glthread_once (gl_once_t *once_control, void (*initfunction) (void))
 
1021
glthread_once_func (gl_once_t *once_control, void (*initfunction) (void))
885
1022
{
886
1023
  if (once_control->inited <= 0)
887
1024
    {
888
1025
      if (InterlockedIncrement (&once_control->started) == 0)
889
 
        {
890
 
          /* This thread is the first one to come to this once_control.  */
891
 
          InitializeCriticalSection (&once_control->lock);
892
 
          EnterCriticalSection (&once_control->lock);
893
 
          once_control->inited = 0;
894
 
          initfunction ();
895
 
          once_control->inited = 1;
896
 
          LeaveCriticalSection (&once_control->lock);
897
 
        }
 
1026
        {
 
1027
          /* This thread is the first one to come to this once_control.  */
 
1028
          InitializeCriticalSection (&once_control->lock);
 
1029
          EnterCriticalSection (&once_control->lock);
 
1030
          once_control->inited = 0;
 
1031
          initfunction ();
 
1032
          once_control->inited = 1;
 
1033
          LeaveCriticalSection (&once_control->lock);
 
1034
        }
898
1035
      else
899
 
        {
900
 
          /* Undo last operation.  */
901
 
          InterlockedDecrement (&once_control->started);
902
 
          /* Some other thread has already started the initialization.
903
 
             Yield the CPU while waiting for the other thread to finish
904
 
             initializing and taking the lock.  */
905
 
          while (once_control->inited < 0)
906
 
            Sleep (0);
907
 
          if (once_control->inited <= 0)
908
 
            {
909
 
              /* Take the lock.  This blocks until the other thread has
910
 
                 finished calling the initfunction.  */
911
 
              EnterCriticalSection (&once_control->lock);
912
 
              LeaveCriticalSection (&once_control->lock);
913
 
              if (!(once_control->inited > 0))
914
 
                abort ();
915
 
            }
916
 
        }
 
1036
        {
 
1037
          /* Undo last operation.  */
 
1038
          InterlockedDecrement (&once_control->started);
 
1039
          /* Some other thread has already started the initialization.
 
1040
             Yield the CPU while waiting for the other thread to finish
 
1041
             initializing and taking the lock.  */
 
1042
          while (once_control->inited < 0)
 
1043
            Sleep (0);
 
1044
          if (once_control->inited <= 0)
 
1045
            {
 
1046
              /* Take the lock.  This blocks until the other thread has
 
1047
                 finished calling the initfunction.  */
 
1048
              EnterCriticalSection (&once_control->lock);
 
1049
              LeaveCriticalSection (&once_control->lock);
 
1050
              if (!(once_control->inited > 0))
 
1051
                abort ();
 
1052
            }
 
1053
        }
917
1054
    }
918
1055
}
919
1056