~ubuntu-branches/ubuntu/karmic/centerim/karmic

« back to all changes in this revision

Viewing changes to intl/lock.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-03-26 19:51:53 UTC
  • mfrom: (1.1.5 upstream) (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090326195153-dxo63t1lwbp2m592
Tags: 4.22.7-1ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - Packages that Depend/Recommend/Suggest firefox (metapackage) must
    must alternatively Depend/Recommend/Suggest abrowser.
* Bugfix-only release, fixed bugs: LP: #146308 and LP: #186381.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Locking in multithreaded situations.
2
 
   Copyright (C) 2005-2006 Free Software Foundation, Inc.
3
 
 
4
 
   This program is free software; you can redistribute it and/or modify it
5
 
   under the terms of the GNU Library General Public License as published
6
 
   by the Free Software Foundation; either version 2, or (at your option)
7
 
   any later version.
8
 
 
9
 
   This program is distributed in the hope that it will be useful,
10
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
   Library General Public License for more details.
13
 
 
14
 
   You should have received a copy of the GNU Library General Public
15
 
   License along with this program; if not, write to the Free Software
16
 
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17
 
   USA.  */
18
 
 
19
 
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
20
 
   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
21
 
   gthr-win32.h.  */
22
 
 
23
 
/* This file contains locking primitives for use with a given thread library.
24
 
   It does not contain primitives for creating threads or for other
25
 
   synchronization primitives.
26
 
 
27
 
   Normal (non-recursive) locks:
28
 
     Type:                gl_lock_t
29
 
     Declaration:         gl_lock_define(extern, name)
30
 
     Initializer:         gl_lock_define_initialized(, name)
31
 
     Initialization:      gl_lock_init (name);
32
 
     Taking the lock:     gl_lock_lock (name);
33
 
     Releasing the lock:  gl_lock_unlock (name);
34
 
     De-initialization:   gl_lock_destroy (name);
35
 
 
36
 
   Read-Write (non-recursive) locks:
37
 
     Type:                gl_rwlock_t
38
 
     Declaration:         gl_rwlock_define(extern, name)
39
 
     Initializer:         gl_rwlock_define_initialized(, name)
40
 
     Initialization:      gl_rwlock_init (name);
41
 
     Taking the lock:     gl_rwlock_rdlock (name);
42
 
                          gl_rwlock_wrlock (name);
43
 
     Releasing the lock:  gl_rwlock_unlock (name);
44
 
     De-initialization:   gl_rwlock_destroy (name);
45
 
 
46
 
   Recursive locks:
47
 
     Type:                gl_recursive_lock_t
48
 
     Declaration:         gl_recursive_lock_define(extern, name)
49
 
     Initializer:         gl_recursive_lock_define_initialized(, name)
50
 
     Initialization:      gl_recursive_lock_init (name);
51
 
     Taking the lock:     gl_recursive_lock_lock (name);
52
 
     Releasing the lock:  gl_recursive_lock_unlock (name);
53
 
     De-initialization:   gl_recursive_lock_destroy (name);
54
 
 
55
 
  Once-only execution:
56
 
     Type:                gl_once_t
57
 
     Initializer:         gl_once_define(extern, name)
58
 
     Execution:           gl_once (name, initfunction);
59
 
*/
60
 
 
61
 
 
62
 
#ifndef _LOCK_H
63
 
#define _LOCK_H
64
 
 
65
 
/* ========================================================================= */
66
 
 
67
 
#if USE_POSIX_THREADS
68
 
 
69
 
/* Use the POSIX threads library.  */
70
 
 
71
 
# include <pthread.h>
72
 
# include <stdlib.h>
73
 
 
74
 
# ifdef __cplusplus
75
 
extern "C" {
76
 
# endif
77
 
 
78
 
# if PTHREAD_IN_USE_DETECTION_HARD
79
 
 
80
 
/* The pthread_in_use() detection needs to be done at runtime.  */
81
 
#  define pthread_in_use() \
82
 
     glthread_in_use ()
83
 
extern int glthread_in_use (void);
84
 
 
85
 
# endif
86
 
 
87
 
# if USE_POSIX_THREADS_WEAK
88
 
 
89
 
/* Use weak references to the POSIX threads library.  */
90
 
 
91
 
/* Weak references avoid dragging in external libraries if the other parts
92
 
   of the program don't use them.  Here we use them, because we don't want
93
 
   every program that uses libintl to depend on libpthread.  This assumes
94
 
   that libpthread would not be loaded after libintl; i.e. if libintl is
95
 
   loaded first, by an executable that does not depend on libpthread, and
96
 
   then a module is dynamically loaded that depends on libpthread, libintl
97
 
   will not be multithread-safe.  */
98
 
 
99
 
/* The way to test at runtime whether libpthread is present is to test
100
 
   whether a function pointer's value, such as &pthread_mutex_init, is
101
 
   non-NULL.  However, some versions of GCC have a bug through which, in
102
 
   PIC mode, &foo != NULL always evaluates to true if there is a direct
103
 
   call to foo(...) in the same function.  To avoid this, we test the
104
 
   address of a function in libpthread that we don't use.  */
105
 
 
106
 
#  pragma weak pthread_mutex_init
107
 
#  pragma weak pthread_mutex_lock
108
 
#  pragma weak pthread_mutex_unlock
109
 
#  pragma weak pthread_mutex_destroy
110
 
#  pragma weak pthread_rwlock_init
111
 
#  pragma weak pthread_rwlock_rdlock
112
 
#  pragma weak pthread_rwlock_wrlock
113
 
#  pragma weak pthread_rwlock_unlock
114
 
#  pragma weak pthread_rwlock_destroy
115
 
#  pragma weak pthread_once
116
 
#  pragma weak pthread_cond_init
117
 
#  pragma weak pthread_cond_wait
118
 
#  pragma weak pthread_cond_signal
119
 
#  pragma weak pthread_cond_broadcast
120
 
#  pragma weak pthread_cond_destroy
121
 
#  pragma weak pthread_mutexattr_init
122
 
#  pragma weak pthread_mutexattr_settype
123
 
#  pragma weak pthread_mutexattr_destroy
124
 
#  ifndef pthread_self
125
 
#   pragma weak pthread_self
126
 
#  endif
127
 
 
128
 
#  if !PTHREAD_IN_USE_DETECTION_HARD
129
 
#   pragma weak pthread_cancel
130
 
#   define pthread_in_use() (pthread_cancel != NULL)
131
 
#  endif
132
 
 
133
 
# else
134
 
 
135
 
#  if !PTHREAD_IN_USE_DETECTION_HARD
136
 
#   define pthread_in_use() 1
137
 
#  endif
138
 
 
139
 
# endif
140
 
 
141
 
/* -------------------------- gl_lock_t datatype -------------------------- */
142
 
 
143
 
typedef pthread_mutex_t gl_lock_t;
144
 
# define gl_lock_define(STORAGECLASS, NAME) \
145
 
    STORAGECLASS pthread_mutex_t NAME;
146
 
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
147
 
    STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
148
 
# define gl_lock_initializer \
149
 
    PTHREAD_MUTEX_INITIALIZER
150
 
# define gl_lock_init(NAME) \
151
 
    if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
152
 
# define gl_lock_lock(NAME) \
153
 
    if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
154
 
# define gl_lock_unlock(NAME) \
155
 
    if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
156
 
# define gl_lock_destroy(NAME) \
157
 
    if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
158
 
 
159
 
/* ------------------------- gl_rwlock_t datatype ------------------------- */
160
 
 
161
 
# if HAVE_PTHREAD_RWLOCK
162
 
 
163
 
#  ifdef PTHREAD_RWLOCK_INITIALIZER
164
 
 
165
 
typedef pthread_rwlock_t gl_rwlock_t;
166
 
#   define gl_rwlock_define(STORAGECLASS, NAME) \
167
 
      STORAGECLASS pthread_rwlock_t NAME;
168
 
#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
169
 
      STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
170
 
#   define gl_rwlock_initializer \
171
 
      PTHREAD_RWLOCK_INITIALIZER
172
 
#   define gl_rwlock_init(NAME) \
173
 
      if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
174
 
#   define gl_rwlock_rdlock(NAME) \
175
 
      if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
176
 
#   define gl_rwlock_wrlock(NAME) \
177
 
      if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
178
 
#   define gl_rwlock_unlock(NAME) \
179
 
      if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
180
 
#   define gl_rwlock_destroy(NAME) \
181
 
      if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
182
 
 
183
 
#  else
184
 
 
185
 
typedef struct
186
 
        {
187
 
          int initialized;
188
 
          pthread_mutex_t guard;   /* protects the initialization */
189
 
          pthread_rwlock_t rwlock; /* read-write lock */
190
 
        }
191
 
        gl_rwlock_t;
192
 
#   define gl_rwlock_define(STORAGECLASS, NAME) \
193
 
      STORAGECLASS gl_rwlock_t NAME;
194
 
#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
195
 
      STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
196
 
#   define gl_rwlock_initializer \
197
 
      { 0, PTHREAD_MUTEX_INITIALIZER }
198
 
#   define gl_rwlock_init(NAME) \
199
 
      if (pthread_in_use ()) glthread_rwlock_init (&NAME)
200
 
#   define gl_rwlock_rdlock(NAME) \
201
 
      if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
202
 
#   define gl_rwlock_wrlock(NAME) \
203
 
      if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
204
 
#   define gl_rwlock_unlock(NAME) \
205
 
      if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
206
 
#   define gl_rwlock_destroy(NAME) \
207
 
      if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
208
 
extern void glthread_rwlock_init (gl_rwlock_t *lock);
209
 
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
210
 
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
211
 
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
212
 
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
213
 
 
214
 
#  endif
215
 
 
216
 
# else
217
 
 
218
 
typedef struct
219
 
        {
220
 
          pthread_mutex_t lock; /* protects the remaining fields */
221
 
          pthread_cond_t waiting_readers; /* waiting readers */
222
 
          pthread_cond_t waiting_writers; /* waiting writers */
223
 
          unsigned int waiting_writers_count; /* number of waiting writers */
224
 
          int runcount; /* number of readers running, or -1 when a writer runs */
225
 
        }
226
 
        gl_rwlock_t;
227
 
# define gl_rwlock_define(STORAGECLASS, NAME) \
228
 
    STORAGECLASS gl_rwlock_t NAME;
229
 
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
230
 
    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
231
 
# define gl_rwlock_initializer \
232
 
    { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
233
 
# define gl_rwlock_init(NAME) \
234
 
    if (pthread_in_use ()) glthread_rwlock_init (&NAME)
235
 
# define gl_rwlock_rdlock(NAME) \
236
 
    if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
237
 
# define gl_rwlock_wrlock(NAME) \
238
 
    if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
239
 
# define gl_rwlock_unlock(NAME) \
240
 
    if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
241
 
# define gl_rwlock_destroy(NAME) \
242
 
    if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
243
 
extern void glthread_rwlock_init (gl_rwlock_t *lock);
244
 
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
245
 
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
246
 
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
247
 
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
248
 
 
249
 
# endif
250
 
 
251
 
/* --------------------- gl_recursive_lock_t datatype --------------------- */
252
 
 
253
 
# if HAVE_PTHREAD_MUTEX_RECURSIVE
254
 
 
255
 
#  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
256
 
 
257
 
typedef pthread_mutex_t gl_recursive_lock_t;
258
 
#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
259
 
      STORAGECLASS pthread_mutex_t NAME;
260
 
#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
261
 
      STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
262
 
#   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
263
 
#    define gl_recursive_lock_initializer \
264
 
       PTHREAD_RECURSIVE_MUTEX_INITIALIZER
265
 
#   else
266
 
#    define gl_recursive_lock_initializer \
267
 
       PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
268
 
#   endif
269
 
#   define gl_recursive_lock_init(NAME) \
270
 
      if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
271
 
#   define gl_recursive_lock_lock(NAME) \
272
 
      if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
273
 
#   define gl_recursive_lock_unlock(NAME) \
274
 
      if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
275
 
#   define gl_recursive_lock_destroy(NAME) \
276
 
      if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
277
 
 
278
 
#  else
279
 
 
280
 
typedef struct
281
 
        {
282
 
          pthread_mutex_t recmutex; /* recursive mutex */
283
 
          pthread_mutex_t guard;    /* protects the initialization */
284
 
          int initialized;
285
 
        }
286
 
        gl_recursive_lock_t;
287
 
#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
288
 
      STORAGECLASS gl_recursive_lock_t NAME;
289
 
#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
290
 
      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
291
 
#   define gl_recursive_lock_initializer \
292
 
      { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
293
 
#   define gl_recursive_lock_init(NAME) \
294
 
      if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
295
 
#   define gl_recursive_lock_lock(NAME) \
296
 
      if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
297
 
#   define gl_recursive_lock_unlock(NAME) \
298
 
      if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
299
 
#   define gl_recursive_lock_destroy(NAME) \
300
 
      if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
301
 
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
302
 
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
303
 
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
304
 
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
305
 
 
306
 
#  endif
307
 
 
308
 
# else
309
 
 
310
 
/* Old versions of POSIX threads on Solaris did not have recursive locks.
311
 
   We have to implement them ourselves.  */
312
 
 
313
 
typedef struct
314
 
        {
315
 
          pthread_mutex_t mutex;
316
 
          pthread_t owner;
317
 
          unsigned long depth;
318
 
        }
319
 
        gl_recursive_lock_t;
320
 
#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
321
 
     STORAGECLASS gl_recursive_lock_t NAME;
322
 
#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
323
 
     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
324
 
#  define gl_recursive_lock_initializer \
325
 
     { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
326
 
#  define gl_recursive_lock_init(NAME) \
327
 
     if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
328
 
#  define gl_recursive_lock_lock(NAME) \
329
 
     if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
330
 
#  define gl_recursive_lock_unlock(NAME) \
331
 
     if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
332
 
#  define gl_recursive_lock_destroy(NAME) \
333
 
     if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
334
 
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
335
 
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
336
 
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
337
 
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
338
 
 
339
 
# endif
340
 
 
341
 
/* -------------------------- gl_once_t datatype -------------------------- */
342
 
 
343
 
typedef pthread_once_t gl_once_t;
344
 
# define gl_once_define(STORAGECLASS, NAME) \
345
 
    STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
346
 
# define gl_once(NAME, INITFUNCTION) \
347
 
    do                                                   \
348
 
      {                                                  \
349
 
        if (pthread_in_use ())                           \
350
 
          {                                              \
351
 
            if (pthread_once (&NAME, INITFUNCTION) != 0) \
352
 
              abort ();                                  \
353
 
          }                                              \
354
 
        else                                             \
355
 
          {                                              \
356
 
            if (glthread_once_singlethreaded (&NAME))    \
357
 
              INITFUNCTION ();                           \
358
 
          }                                              \
359
 
      }                                                  \
360
 
    while (0)
361
 
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
362
 
 
363
 
# ifdef __cplusplus
364
 
}
365
 
# endif
366
 
 
367
 
#endif
368
 
 
369
 
/* ========================================================================= */
370
 
 
371
 
#if USE_PTH_THREADS
372
 
 
373
 
/* Use the GNU Pth threads library.  */
374
 
 
375
 
# include <pth.h>
376
 
# include <stdlib.h>
377
 
 
378
 
# ifdef __cplusplus
379
 
extern "C" {
380
 
# endif
381
 
 
382
 
# if USE_PTH_THREADS_WEAK
383
 
 
384
 
/* Use weak references to the GNU Pth threads library.  */
385
 
 
386
 
#  pragma weak pth_mutex_init
387
 
#  pragma weak pth_mutex_acquire
388
 
#  pragma weak pth_mutex_release
389
 
#  pragma weak pth_rwlock_init
390
 
#  pragma weak pth_rwlock_acquire
391
 
#  pragma weak pth_rwlock_release
392
 
#  pragma weak pth_once
393
 
 
394
 
#  pragma weak pth_cancel
395
 
#  define pth_in_use() (pth_cancel != NULL)
396
 
 
397
 
# else
398
 
 
399
 
#  define pth_in_use() 1
400
 
 
401
 
# endif
402
 
 
403
 
/* -------------------------- gl_lock_t datatype -------------------------- */
404
 
 
405
 
typedef pth_mutex_t gl_lock_t;
406
 
# define gl_lock_define(STORAGECLASS, NAME) \
407
 
    STORAGECLASS pth_mutex_t NAME;
408
 
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
409
 
    STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
410
 
# define gl_lock_initializer \
411
 
    PTH_MUTEX_INIT
412
 
# define gl_lock_init(NAME) \
413
 
    if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
414
 
# define gl_lock_lock(NAME) \
415
 
    if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
416
 
# define gl_lock_unlock(NAME) \
417
 
    if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
418
 
# define gl_lock_destroy(NAME) \
419
 
    (void)(&NAME)
420
 
 
421
 
/* ------------------------- gl_rwlock_t datatype ------------------------- */
422
 
 
423
 
typedef pth_rwlock_t gl_rwlock_t;
424
 
#  define gl_rwlock_define(STORAGECLASS, NAME) \
425
 
     STORAGECLASS pth_rwlock_t NAME;
426
 
#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
427
 
     STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
428
 
#  define gl_rwlock_initializer \
429
 
     PTH_RWLOCK_INIT
430
 
#  define gl_rwlock_init(NAME) \
431
 
     if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
432
 
#  define gl_rwlock_rdlock(NAME) \
433
 
     if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
434
 
#  define gl_rwlock_wrlock(NAME) \
435
 
     if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
436
 
#  define gl_rwlock_unlock(NAME) \
437
 
     if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
438
 
#  define gl_rwlock_destroy(NAME) \
439
 
     (void)(&NAME)
440
 
 
441
 
/* --------------------- gl_recursive_lock_t datatype --------------------- */
442
 
 
443
 
/* In Pth, mutexes are recursive by default.  */
444
 
typedef pth_mutex_t gl_recursive_lock_t;
445
 
#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
446
 
     STORAGECLASS pth_mutex_t NAME;
447
 
#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
448
 
     STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
449
 
#  define gl_recursive_lock_initializer \
450
 
     PTH_MUTEX_INIT
451
 
#  define gl_recursive_lock_init(NAME) \
452
 
     if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
453
 
#  define gl_recursive_lock_lock(NAME) \
454
 
     if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
455
 
#  define gl_recursive_lock_unlock(NAME) \
456
 
     if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
457
 
#  define gl_recursive_lock_destroy(NAME) \
458
 
     (void)(&NAME)
459
 
 
460
 
/* -------------------------- gl_once_t datatype -------------------------- */
461
 
 
462
 
typedef pth_once_t gl_once_t;
463
 
# define gl_once_define(STORAGECLASS, NAME) \
464
 
    STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
465
 
# define gl_once(NAME, INITFUNCTION) \
466
 
    do                                                                \
467
 
      {                                                               \
468
 
        if (pth_in_use ())                                            \
469
 
          {                                                           \
470
 
            void (*gl_once_temp) (void) = INITFUNCTION;               \
471
 
            if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
472
 
              abort ();                                               \
473
 
          }                                                           \
474
 
        else                                                          \
475
 
          {                                                           \
476
 
            if (glthread_once_singlethreaded (&NAME))                 \
477
 
              INITFUNCTION ();                                        \
478
 
          }                                                           \
479
 
      }                                                               \
480
 
    while (0)
481
 
extern void glthread_once_call (void *arg);
482
 
extern int glthread_once_singlethreaded (pth_once_t *once_control);
483
 
 
484
 
# ifdef __cplusplus
485
 
}
486
 
# endif
487
 
 
488
 
#endif
489
 
 
490
 
/* ========================================================================= */
491
 
 
492
 
#if USE_SOLARIS_THREADS
493
 
 
494
 
/* Use the old Solaris threads library.  */
495
 
 
496
 
# include <thread.h>
497
 
# include <synch.h>
498
 
# include <stdlib.h>
499
 
 
500
 
# ifdef __cplusplus
501
 
extern "C" {
502
 
# endif
503
 
 
504
 
# if USE_SOLARIS_THREADS_WEAK
505
 
 
506
 
/* Use weak references to the old Solaris threads library.  */
507
 
 
508
 
#  pragma weak mutex_init
509
 
#  pragma weak mutex_lock
510
 
#  pragma weak mutex_unlock
511
 
#  pragma weak mutex_destroy
512
 
#  pragma weak rwlock_init
513
 
#  pragma weak rw_rdlock
514
 
#  pragma weak rw_wrlock
515
 
#  pragma weak rw_unlock
516
 
#  pragma weak rwlock_destroy
517
 
#  pragma weak thr_self
518
 
 
519
 
#  pragma weak thr_suspend
520
 
#  define thread_in_use() (thr_suspend != NULL)
521
 
 
522
 
# else
523
 
 
524
 
#  define thread_in_use() 1
525
 
 
526
 
# endif
527
 
 
528
 
/* -------------------------- gl_lock_t datatype -------------------------- */
529
 
 
530
 
typedef mutex_t gl_lock_t;
531
 
# define gl_lock_define(STORAGECLASS, NAME) \
532
 
    STORAGECLASS mutex_t NAME;
533
 
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
534
 
    STORAGECLASS mutex_t NAME = gl_lock_initializer;
535
 
# define gl_lock_initializer \
536
 
    DEFAULTMUTEX
537
 
# define gl_lock_init(NAME) \
538
 
    if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
539
 
# define gl_lock_lock(NAME) \
540
 
    if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
541
 
# define gl_lock_unlock(NAME) \
542
 
    if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
543
 
# define gl_lock_destroy(NAME) \
544
 
    if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
545
 
 
546
 
/* ------------------------- gl_rwlock_t datatype ------------------------- */
547
 
 
548
 
typedef rwlock_t gl_rwlock_t;
549
 
# define gl_rwlock_define(STORAGECLASS, NAME) \
550
 
    STORAGECLASS rwlock_t NAME;
551
 
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
552
 
    STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
553
 
# define gl_rwlock_initializer \
554
 
    DEFAULTRWLOCK
555
 
# define gl_rwlock_init(NAME) \
556
 
    if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
557
 
# define gl_rwlock_rdlock(NAME) \
558
 
    if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
559
 
# define gl_rwlock_wrlock(NAME) \
560
 
    if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
561
 
# define gl_rwlock_unlock(NAME) \
562
 
    if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
563
 
# define gl_rwlock_destroy(NAME) \
564
 
    if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
565
 
 
566
 
/* --------------------- gl_recursive_lock_t datatype --------------------- */
567
 
 
568
 
/* Old Solaris threads did not have recursive locks.
569
 
   We have to implement them ourselves.  */
570
 
 
571
 
typedef struct
572
 
        {
573
 
          mutex_t mutex;
574
 
          thread_t owner;
575
 
          unsigned long depth;
576
 
        }
577
 
        gl_recursive_lock_t;
578
 
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
579
 
    STORAGECLASS gl_recursive_lock_t NAME;
580
 
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
581
 
    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
582
 
# define gl_recursive_lock_initializer \
583
 
    { DEFAULTMUTEX, (thread_t) 0, 0 }
584
 
# define gl_recursive_lock_init(NAME) \
585
 
    if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
586
 
# define gl_recursive_lock_lock(NAME) \
587
 
    if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
588
 
# define gl_recursive_lock_unlock(NAME) \
589
 
    if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
590
 
# define gl_recursive_lock_destroy(NAME) \
591
 
    if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
592
 
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
593
 
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
594
 
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
595
 
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
596
 
 
597
 
/* -------------------------- gl_once_t datatype -------------------------- */
598
 
 
599
 
typedef struct
600
 
        {
601
 
          volatile int inited;
602
 
          mutex_t mutex;
603
 
        }
604
 
        gl_once_t;
605
 
# define gl_once_define(STORAGECLASS, NAME) \
606
 
    STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
607
 
# define gl_once(NAME, INITFUNCTION) \
608
 
    do                                                \
609
 
      {                                               \
610
 
        if (thread_in_use ())                         \
611
 
          {                                           \
612
 
            glthread_once (&NAME, INITFUNCTION);      \
613
 
          }                                           \
614
 
        else                                          \
615
 
          {                                           \
616
 
            if (glthread_once_singlethreaded (&NAME)) \
617
 
              INITFUNCTION ();                        \
618
 
          }                                           \
619
 
      }                                               \
620
 
    while (0)
621
 
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
622
 
extern int glthread_once_singlethreaded (gl_once_t *once_control);
623
 
 
624
 
# ifdef __cplusplus
625
 
}
626
 
# endif
627
 
 
628
 
#endif
629
 
 
630
 
/* ========================================================================= */
631
 
 
632
 
#if USE_WIN32_THREADS
633
 
 
634
 
# include <windows.h>
635
 
 
636
 
# ifdef __cplusplus
637
 
extern "C" {
638
 
# endif
639
 
 
640
 
/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
641
 
   Semaphore types, because
642
 
     - we need only to synchronize inside a single process (address space),
643
 
       not inter-process locking,
644
 
     - we don't need to support trylock operations.  (TryEnterCriticalSection
645
 
       does not work on Windows 95/98/ME.  Packages that need trylock usually
646
 
       define their own mutex type.)  */
647
 
 
648
 
/* There is no way to statically initialize a CRITICAL_SECTION.  It needs
649
 
   to be done lazily, once only.  For this we need spinlocks.  */
650
 
 
651
 
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
652
 
 
653
 
/* -------------------------- gl_lock_t datatype -------------------------- */
654
 
 
655
 
typedef struct
656
 
        {
657
 
          gl_spinlock_t guard; /* protects the initialization */
658
 
          CRITICAL_SECTION lock;
659
 
        }
660
 
        gl_lock_t;
661
 
# define gl_lock_define(STORAGECLASS, NAME) \
662
 
    STORAGECLASS gl_lock_t NAME;
663
 
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
664
 
    STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
665
 
# define gl_lock_initializer \
666
 
    { { 0, -1 } }
667
 
# define gl_lock_init(NAME) \
668
 
    glthread_lock_init (&NAME)
669
 
# define gl_lock_lock(NAME) \
670
 
    glthread_lock_lock (&NAME)
671
 
# define gl_lock_unlock(NAME) \
672
 
    glthread_lock_unlock (&NAME)
673
 
# define gl_lock_destroy(NAME) \
674
 
    glthread_lock_destroy (&NAME)
675
 
extern void glthread_lock_init (gl_lock_t *lock);
676
 
extern void glthread_lock_lock (gl_lock_t *lock);
677
 
extern void glthread_lock_unlock (gl_lock_t *lock);
678
 
extern void glthread_lock_destroy (gl_lock_t *lock);
679
 
 
680
 
/* ------------------------- gl_rwlock_t datatype ------------------------- */
681
 
 
682
 
/* It is impossible to implement read-write locks using plain locks, without
683
 
   introducing an extra thread dedicated to managing read-write locks.
684
 
   Therefore here we need to use the low-level Event type.  */
685
 
 
686
 
typedef struct
687
 
        {
688
 
          HANDLE *array; /* array of waiting threads, each represented by an event */
689
 
          unsigned int count; /* number of waiting threads */
690
 
          unsigned int alloc; /* length of allocated array */
691
 
          unsigned int offset; /* index of first waiting thread in array */
692
 
        }
693
 
        gl_waitqueue_t;
694
 
typedef struct
695
 
        {
696
 
          gl_spinlock_t guard; /* protects the initialization */
697
 
          CRITICAL_SECTION lock; /* protects the remaining fields */
698
 
          gl_waitqueue_t waiting_readers; /* waiting readers */
699
 
          gl_waitqueue_t waiting_writers; /* waiting writers */
700
 
          int runcount; /* number of readers running, or -1 when a writer runs */
701
 
        }
702
 
        gl_rwlock_t;
703
 
# define gl_rwlock_define(STORAGECLASS, NAME) \
704
 
    STORAGECLASS gl_rwlock_t NAME;
705
 
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
706
 
    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
707
 
# define gl_rwlock_initializer \
708
 
    { { 0, -1 } }
709
 
# define gl_rwlock_init(NAME) \
710
 
    glthread_rwlock_init (&NAME)
711
 
# define gl_rwlock_rdlock(NAME) \
712
 
    glthread_rwlock_rdlock (&NAME)
713
 
# define gl_rwlock_wrlock(NAME) \
714
 
    glthread_rwlock_wrlock (&NAME)
715
 
# define gl_rwlock_unlock(NAME) \
716
 
    glthread_rwlock_unlock (&NAME)
717
 
# define gl_rwlock_destroy(NAME) \
718
 
    glthread_rwlock_destroy (&NAME)
719
 
extern void glthread_rwlock_init (gl_rwlock_t *lock);
720
 
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
721
 
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
722
 
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
723
 
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
724
 
 
725
 
/* --------------------- gl_recursive_lock_t datatype --------------------- */
726
 
 
727
 
/* The Win32 documentation says that CRITICAL_SECTION already implements a
728
 
   recursive lock.  But we need not rely on it: It's easy to implement a
729
 
   recursive lock without this assumption.  */
730
 
 
731
 
typedef struct
732
 
        {
733
 
          gl_spinlock_t guard; /* protects the initialization */
734
 
          DWORD owner;
735
 
          unsigned long depth;
736
 
          CRITICAL_SECTION lock;
737
 
        }
738
 
        gl_recursive_lock_t;
739
 
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
740
 
    STORAGECLASS gl_recursive_lock_t NAME;
741
 
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
742
 
    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
743
 
# define gl_recursive_lock_initializer \
744
 
    { { 0, -1 }, 0, 0 }
745
 
# define gl_recursive_lock_init(NAME) \
746
 
    glthread_recursive_lock_init (&NAME)
747
 
# define gl_recursive_lock_lock(NAME) \
748
 
    glthread_recursive_lock_lock (&NAME)
749
 
# define gl_recursive_lock_unlock(NAME) \
750
 
    glthread_recursive_lock_unlock (&NAME)
751
 
# define gl_recursive_lock_destroy(NAME) \
752
 
    glthread_recursive_lock_destroy (&NAME)
753
 
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
754
 
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
755
 
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
756
 
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
757
 
 
758
 
/* -------------------------- gl_once_t datatype -------------------------- */
759
 
 
760
 
typedef struct
761
 
        {
762
 
          volatile int inited;
763
 
          volatile long started;
764
 
          CRITICAL_SECTION lock;
765
 
        }
766
 
        gl_once_t;
767
 
# define gl_once_define(STORAGECLASS, NAME) \
768
 
    STORAGECLASS gl_once_t NAME = { -1, -1 };
769
 
# define gl_once(NAME, INITFUNCTION) \
770
 
    glthread_once (&NAME, INITFUNCTION)
771
 
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
772
 
 
773
 
# ifdef __cplusplus
774
 
}
775
 
# endif
776
 
 
777
 
#endif
778
 
 
779
 
/* ========================================================================= */
780
 
 
781
 
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
782
 
 
783
 
/* Provide dummy implementation if threads are not supported.  */
784
 
 
785
 
/* -------------------------- gl_lock_t datatype -------------------------- */
786
 
 
787
 
typedef int gl_lock_t;
788
 
# define gl_lock_define(STORAGECLASS, NAME)
789
 
# define gl_lock_define_initialized(STORAGECLASS, NAME)
790
 
# define gl_lock_init(NAME)
791
 
# define gl_lock_lock(NAME)
792
 
# define gl_lock_unlock(NAME)
793
 
 
794
 
/* ------------------------- gl_rwlock_t datatype ------------------------- */
795
 
 
796
 
typedef int gl_rwlock_t;
797
 
# define gl_rwlock_define(STORAGECLASS, NAME)
798
 
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
799
 
# define gl_rwlock_init(NAME)
800
 
# define gl_rwlock_rdlock(NAME)
801
 
# define gl_rwlock_wrlock(NAME)
802
 
# define gl_rwlock_unlock(NAME)
803
 
 
804
 
/* --------------------- gl_recursive_lock_t datatype --------------------- */
805
 
 
806
 
typedef int gl_recursive_lock_t;
807
 
# define gl_recursive_lock_define(STORAGECLASS, NAME)
808
 
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
809
 
# define gl_recursive_lock_init(NAME)
810
 
# define gl_recursive_lock_lock(NAME)
811
 
# define gl_recursive_lock_unlock(NAME)
812
 
 
813
 
/* -------------------------- gl_once_t datatype -------------------------- */
814
 
 
815
 
typedef int gl_once_t;
816
 
# define gl_once_define(STORAGECLASS, NAME) \
817
 
    STORAGECLASS gl_once_t NAME = 0;
818
 
# define gl_once(NAME, INITFUNCTION) \
819
 
    do                       \
820
 
      {                      \
821
 
        if (NAME == 0)       \
822
 
          {                  \
823
 
            NAME = ~ 0;      \
824
 
            INITFUNCTION (); \
825
 
          }                  \
826
 
      }                      \
827
 
    while (0)
828
 
 
829
 
#endif
830
 
 
831
 
/* ========================================================================= */
832
 
 
833
 
#endif /* _LOCK_H */