~thopiekar/arm-mali/libump-sunxi

« back to all changes in this revision

Viewing changes to src/ump_osu_locks.c

  • Committer: Luc Verhaegen
  • Date: 2014-03-25 21:04:12 UTC
  • Revision ID: git-v1:fa5ad94ac2873793dcca65dafc3ea211de5e7226
import ump r2p4 source

Signed-off-by: Luc Verhaegen <libv@skynet.be>

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
 
3
 * 
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 * 
 
8
 *       http://www.apache.org/licenses/LICENSE-2.0
 
9
 * 
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#if ((!defined _XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 600))
 
18
#undef _XOPEN_SOURCE
 
19
#define _XOPEN_SOURCE 600
 
20
#endif
 
21
 
 
22
 
 
23
#define _POSIX_C_SOURCE 200112L
 
24
 
 
25
#include <ump/ump_osu.h>
 
26
#include <ump/ump_debug.h>
 
27
 
 
28
#include <pthread.h>
 
29
#include <time.h>
 
30
#include <sys/time.h>
 
31
#include <errno.h>
 
32
 
 
33
/**
 
34
 * @file ump_osu_locks.c
 
35
 * File implements the user side of the OS interface
 
36
 */
 
37
 
 
38
/** @opt Most of the time, we use the plain mutex type of osu_lock, and so
 
39
 * only require the flags and mutex members. This costs 2 extra DWORDS, but
 
40
 * most of the time we don't use those DWORDS.
 
41
 * Therefore, ANY_UNLOCK type osu_locks can be implemented as a second
 
42
 * structure containing the member _ump_osu_lock_t lock_t, plus the extra
 
43
 * state required. Then, we use &container->lock_t when passing out of the
 
44
 * OSU api, and CONTAINER_OF() when passing back in to recover the original
 
45
 * structure. */
 
46
 
 
47
/** Private declaration of the OSU lock type */
 
48
struct _ump_osu_lock_t_struct
 
49
{
 
50
        /** At present, only two types of mutex, so we store this information as
 
51
         * the flags supplied at init time */
 
52
        _ump_osu_lock_flags_t flags;
 
53
 
 
54
        pthread_mutex_t mutex; /**< Used in both plain and ANY_UNLOCK osu_locks */
 
55
 
 
56
        /* Extra State for ANY_UNLOCK osu_locks. These are UNINITIALIZED when
 
57
         * flags does not contain _UMP_OSU_LOCKFLAG_ANYUNLOCK: */
 
58
        pthread_cond_t condition;  /**< The condition object to use while blocking */
 
59
        ump_bool state;  /**< The boolean which indicates the event's state */
 
60
 
 
61
        UMP_DEBUG_CODE(
 
62
                                  /** debug checking of locks */
 
63
                                  _ump_osu_lock_mode_t locked_as;
 
64
        ) /* UMP_DEBUG_CODE */
 
65
 
 
66
};
 
67
 
 
68
/* Provide two statically initialized locks */
 
69
UMP_STATIC _ump_osu_lock_t _ump_osu_static_locks[] =
 
70
{
 
71
        {
 
72
            _UMP_OSU_LOCKFLAG_STATIC,
 
73
            PTHREAD_MUTEX_INITIALIZER,
 
74
            PTHREAD_COND_INITIALIZER,
 
75
            UMP_FALSE,
 
76
                UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
 
77
        },
 
78
        {
 
79
            _UMP_OSU_LOCKFLAG_STATIC,
 
80
            PTHREAD_MUTEX_INITIALIZER,
 
81
            PTHREAD_COND_INITIALIZER,
 
82
            UMP_FALSE,
 
83
                UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
 
84
        },
 
85
        {
 
86
            _UMP_OSU_LOCKFLAG_STATIC,
 
87
            PTHREAD_MUTEX_INITIALIZER,
 
88
            PTHREAD_COND_INITIALIZER,
 
89
            UMP_FALSE,
 
90
                UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
 
91
        },
 
92
        {
 
93
            _UMP_OSU_LOCKFLAG_STATIC,
 
94
            PTHREAD_MUTEX_INITIALIZER,
 
95
            PTHREAD_COND_INITIALIZER,
 
96
            UMP_FALSE,
 
97
                UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF )
 
98
        },
 
99
};
 
100
 
 
101
/* Critical section for auto_init */
 
102
UMP_STATIC pthread_mutex_t      static_auto_init_mutex = PTHREAD_MUTEX_INITIALIZER;
 
103
 
 
104
 
 
105
_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order )
 
106
{
 
107
        int call_result;
 
108
        /* Validate parameters: */
 
109
        UMP_DEBUG_ASSERT_POINTER( pplock );
 
110
 
 
111
        /** @opt We don't lock the Critical Section or do anything if this is already non-null */
 
112
        if ( NULL != *pplock)
 
113
        {
 
114
                return _UMP_OSU_ERR_OK;
 
115
        }
 
116
 
 
117
        /* We MIGHT need to initialize it, lock the Critical Section and check again */
 
118
        call_result = pthread_mutex_lock(&static_auto_init_mutex);
 
119
        /* It would be a programming error for this to fail: */
 
120
        UMP_DEBUG_ASSERT( 0 == call_result,
 
121
                                           ("failed to lock critical section\n") );
 
122
 
 
123
        if ( NULL != *pplock )
 
124
        {
 
125
                /*
 
126
                        We caught a race condition to initialize this osu_lock.
 
127
                        The other thread won the race, so the osu_lock is now initialized.
 
128
                */
 
129
                call_result = pthread_mutex_unlock(&static_auto_init_mutex);
 
130
 
 
131
                UMP_DEBUG_ASSERT(0 == call_result,
 
132
                                                  ("failed to unlock critical section\n"));
 
133
 
 
134
                return _UMP_OSU_ERR_OK;
 
135
        }
 
136
 
 
137
        /* We're the first thread in: initialize the osu_lock */
 
138
        *pplock = _ump_osu_lock_init( flags, initial, order );
 
139
 
 
140
        if ( NULL == *pplock )
 
141
        {
 
142
                /* osu_lock creation failed */
 
143
                call_result = pthread_mutex_unlock(&static_auto_init_mutex);
 
144
                UMP_DEBUG_ASSERT(0 == call_result,
 
145
                                                  ("failed to unlock critical section\n"));
 
146
 
 
147
                return _UMP_OSU_ERR_FAULT;
 
148
        }
 
149
 
 
150
 
 
151
        /* osu_lock created OK */
 
152
        call_result = pthread_mutex_unlock(&static_auto_init_mutex);
 
153
 
 
154
        UMP_DEBUG_ASSERT(0 == call_result,
 
155
                                          ("failed to unlock critical section\n"));
 
156
 
 
157
        UMP_IGNORE( call_result );
 
158
 
 
159
        return _UMP_OSU_ERR_OK;
 
160
}
 
161
 
 
162
 
 
163
_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order )
 
164
{
 
165
        _ump_osu_lock_t * lock;
 
166
        pthread_mutexattr_t mutex_attributes;
 
167
 
 
168
        UMP_IGNORE(order); /* order isn't implemented yet, for now callers should set it to zero. */
 
169
 
 
170
        /* Validate parameters: */
 
171
        /* Flags acceptable */
 
172
        UMP_DEBUG_ASSERT( 0 == ( flags & ~( _UMP_OSU_LOCKFLAG_ANYUNLOCK)),
 
173
                                           ("incorrect flags or trying to initialise a statically initialized lock, %.8X\n", flags) );
 
174
 
 
175
        /* Parameter initial SBZ - for future expansion */
 
176
        UMP_DEBUG_ASSERT( 0 == initial,
 
177
                                           ("initial must be zero\n") );
 
178
 
 
179
        if (0 != pthread_mutexattr_init(&mutex_attributes))
 
180
        {
 
181
                return NULL;
 
182
        }
 
183
 
 
184
#if UMP_DEBUG_EXTENDED_MUTEX_LOCK_CHECKING
 
185
#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK
 
186
#else
 
187
#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT
 
188
#endif
 
189
 
 
190
        if (0 != pthread_mutexattr_settype(&mutex_attributes, UMP_PTHREADS_MUTEX_TYPE))
 
191
        {
 
192
                /** Return NULL on failure */
 
193
                pthread_mutexattr_destroy(&mutex_attributes);
 
194
                return NULL;
 
195
 
 
196
        }
 
197
 
 
198
#undef UMP_PTHREADS_MUTEX_TYPE
 
199
 
 
200
        /** @opt use containing structures for the ANY_UNLOCK type, to
 
201
         * save 2 DWORDS when not in use */
 
202
        lock = _ump_osu_malloc( sizeof(_ump_osu_lock_t) );
 
203
 
 
204
        if( NULL == lock )
 
205
        {
 
206
                /** Return NULL on failure */
 
207
                pthread_mutexattr_destroy(&mutex_attributes);
 
208
                return NULL;
 
209
        }
 
210
 
 
211
        if (0 != pthread_mutex_init( &lock->mutex, &mutex_attributes ))
 
212
        {
 
213
                pthread_mutexattr_destroy(&mutex_attributes);
 
214
                _ump_osu_free( lock );
 
215
                return NULL;
 
216
        }
 
217
 
 
218
        /* done with the mutexattr object */
 
219
        pthread_mutexattr_destroy(&mutex_attributes);
 
220
 
 
221
        /* ANY_UNLOCK type */
 
222
        if ( flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK )
 
223
        {
 
224
                if (0 != pthread_cond_init( &lock->condition, NULL ))
 
225
                {
 
226
                        /* cleanup */
 
227
                        pthread_mutex_destroy( &lock->mutex );
 
228
                        _ump_osu_free( lock );
 
229
                        return NULL;
 
230
                }
 
231
                lock->state = UMP_FALSE; /* mark as unlocked by default */
 
232
        }
 
233
 
 
234
        lock->flags = flags;
 
235
 
 
236
        /** Debug lock checking */
 
237
        UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF       );
 
238
 
 
239
        return lock;
 
240
}
 
241
 
 
242
_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout)
 
243
{
 
244
        /* absolute time specifier */
 
245
        struct timespec ts;
 
246
        struct timeval tv;
 
247
 
 
248
        /* Parameter validation */
 
249
        UMP_DEBUG_ASSERT_POINTER( lock );
 
250
 
 
251
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
 
252
                                           ("unrecognised mode, %.8X\n", mode) );
 
253
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKFLAG_ANYUNLOCK == lock->flags, ("Timed operations only implemented for ANYUNLOCK type locks"));
 
254
 
 
255
        /* calculate the realtime timeout value */
 
256
 
 
257
        if (0 != gettimeofday(&tv, NULL))
 
258
        {
 
259
                UMP_DEBUG_PRINT(1,("Could not get the current realtime value to calculate the absolute value for a timed mutex lock with a timeout"));
 
260
                return _UMP_OSU_ERR_FAULT;
 
261
        }
 
262
 
 
263
        tv.tv_usec += timeout;
 
264
 
 
265
#define UMP_USECS_PER_SECOND 1000000LL
 
266
#define UMP_NANOSECS_PER_USEC 1000LL
 
267
 
 
268
        /* did we overflow a second in the usec part? */
 
269
        while (tv.tv_usec >= UMP_USECS_PER_SECOND)
 
270
        {
 
271
                tv.tv_usec -= UMP_USECS_PER_SECOND;
 
272
                tv.tv_sec++;
 
273
        }
 
274
 
 
275
        /* copy to the correct struct */
 
276
        ts.tv_sec = tv.tv_sec;
 
277
        ts.tv_nsec = (tv.tv_usec * UMP_NANOSECS_PER_USEC);
 
278
 
 
279
#undef UMP_USECS_PER_SECOND
 
280
#undef UMP_NANOSECS_PER_USEC
 
281
 
 
282
        /* lock the mutex protecting access to the state field */
 
283
        pthread_mutex_lock( &lock->mutex );
 
284
        /* loop while locked (state is UMP_TRUE) */
 
285
        /* pthread_cond_timedwait unlocks the mutex, wait, and locks the mutex once unblocked (either due to the event or the timeout) */
 
286
        while ( UMP_TRUE == lock->state )
 
287
        {
 
288
                int res;
 
289
                res = pthread_cond_timedwait( &lock->condition, &lock->mutex, &ts );
 
290
                if (0 == res) continue; /* test the state variable again (loop condition) */
 
291
                else if (ETIMEDOUT == res)
 
292
                {
 
293
                        /* timeout, need to clean up and return the correct error code */
 
294
                        pthread_mutex_unlock(&lock->mutex);
 
295
                        return _UMP_OSU_ERR_TIMEOUT;
 
296
                }
 
297
                else
 
298
                {
 
299
                        UMP_DEBUG_PRINT(1, ("Unexpected return from pthread_cond_timedwait 0x%08X\n", res));
 
300
 
 
301
                        pthread_mutex_unlock(&lock->mutex);
 
302
                        return _UMP_OSU_ERR_FAULT;
 
303
                }
 
304
        
 
305
        }
 
306
 
 
307
        /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
308
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
 
309
                        ("This lock was already locked\n") );
 
310
        UMP_DEBUG_CODE( lock->locked_as = mode );
 
311
 
 
312
        /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */
 
313
        lock->state = UMP_TRUE;
 
314
        /* final unlock of the mutex */
 
315
        pthread_mutex_unlock(&lock->mutex);
 
316
 
 
317
        return _UMP_OSU_ERR_OK;
 
318
 
 
319
}
 
320
 
 
321
_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode)
 
322
{
 
323
        /* Parameter validation */
 
324
        UMP_DEBUG_ASSERT_POINTER( lock );
 
325
 
 
326
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
 
327
                                           ("unrecognised mode, %.8X\n", mode) );
 
328
 
 
329
        /** @note since only one flag can be set, we use a switch statement here.
 
330
         * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
 
331
         * implemented lock type */
 
332
        switch ( lock->flags )
 
333
        {
 
334
        case _UMP_OSU_LOCKFLAG_STATIC:
 
335
        case 0:
 
336
                /* Usual Mutex type */
 
337
                {
 
338
                        int call_result;
 
339
                        call_result = pthread_mutex_lock( &lock->mutex );
 
340
                        UMP_DEBUG_ASSERT( 0 == call_result,
 
341
                                                           ("pthread_mutex_lock call failed with error code %d\n", call_result));
 
342
                        UMP_IGNORE( call_result );
 
343
                }
 
344
 
 
345
                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
346
                UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
 
347
                                                   ("This lock was already locked\n") );
 
348
                UMP_DEBUG_CODE( lock->locked_as = mode );
 
349
                break;
 
350
 
 
351
        case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
 
352
                /** @note Use of bitflags in a case statement ONLY works because this
 
353
                 * is the ONLY flag that is supported */
 
354
 
 
355
                /* lock the mutex protecting access to the state field */
 
356
                pthread_mutex_lock( &lock->mutex );
 
357
                /* loop while locked (state is UMP_TRUE) */
 
358
                /* pthread_cond_wait unlocks the mutex, wait, and locks the mutex once unblocked */
 
359
                while ( UMP_TRUE == lock->state ) pthread_cond_wait( &lock->condition, &lock->mutex );
 
360
 
 
361
                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
362
                UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
 
363
                                                   ("This lock was already locked\n") );
 
364
                UMP_DEBUG_CODE( lock->locked_as = mode );
 
365
 
 
366
                /* the state is UMP_FALSE (unlocked), so we set it to UMP_TRUE to indicate that it's locked and can return knowing that we own the lock */
 
367
                lock->state = UMP_TRUE;
 
368
                /* final unlock of the mutex */
 
369
                pthread_mutex_unlock(&lock->mutex);
 
370
                break;
 
371
 
 
372
        default:
 
373
                UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
 
374
                break;
 
375
        }
 
376
 
 
377
        return _UMP_OSU_ERR_OK;
 
378
}
 
379
 
 
380
_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode)
 
381
{
 
382
        _ump_osu_errcode_t err = _UMP_OSU_ERR_FAULT;
 
383
        /* Parameter validation */
 
384
        UMP_DEBUG_ASSERT_POINTER( lock );
 
385
 
 
386
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
 
387
                                           ("unrecognised mode, %.8X\n", mode) );
 
388
 
 
389
        /** @note since only one flag can be set, we use a switch statement here.
 
390
         * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
 
391
         * implemented lock type */
 
392
        switch ( lock->flags )
 
393
        {
 
394
        case _UMP_OSU_LOCKFLAG_STATIC:
 
395
        case 0:
 
396
                /* Usual Mutex type */
 
397
                {
 
398
                        /* This is not subject to UMP_CHECK - overriding the result would cause a programming error */
 
399
                        if ( 0 == pthread_mutex_trylock( &lock->mutex ) )
 
400
                        {
 
401
                                err = _UMP_OSU_ERR_OK;
 
402
 
 
403
                                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
404
                                UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as
 
405
                                                                   || mode == lock->locked_as,
 
406
                                                                   ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) );
 
407
                                UMP_DEBUG_CODE( lock->locked_as = mode );
 
408
                        }
 
409
                }
 
410
                break;
 
411
 
 
412
        case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
 
413
                /** @note Use of bitflags in a case statement ONLY works because this
 
414
                 * is the ONLY flag that is supported */
 
415
 
 
416
                /* lock the mutex protecting access to the state field */
 
417
                pthread_mutex_lock(&lock->mutex);
 
418
 
 
419
                if ( UMP_FALSE == lock->state)
 
420
                {
 
421
                        /* unlocked, take the lock */
 
422
                        lock->state = UMP_TRUE;
 
423
                        err = _UMP_OSU_ERR_OK;
 
424
                }
 
425
 
 
426
                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
427
                /* Can do this regardless of whether we obtained ANYUNLOCK: */
 
428
 
 
429
 
 
430
                UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as
 
431
                                                   || mode == lock->locked_as,
 
432
                                                   ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) );
 
433
                /* If we were already locked, this does no harm, because of the above assert: */
 
434
                UMP_DEBUG_CODE( lock->locked_as = mode );
 
435
 
 
436
                pthread_mutex_unlock(&lock->mutex);
 
437
                break;
 
438
 
 
439
        default:
 
440
                UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
 
441
                break;
 
442
        }
 
443
 
 
444
        return err;
 
445
}
 
446
 
 
447
 
 
448
void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode )
 
449
{
 
450
        /* Parameter validation */
 
451
        UMP_DEBUG_ASSERT_POINTER( lock );
 
452
 
 
453
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode,
 
454
                                           ("unrecognised mode, %.8X\n", mode) );
 
455
 
 
456
        /** @note since only one flag can be set, we use a switch statement here.
 
457
         * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the
 
458
         * implemented lock type */
 
459
        switch ( lock->flags )
 
460
        {
 
461
        case _UMP_OSU_LOCKFLAG_STATIC:
 
462
        case 0:
 
463
                /* Usual Mutex type */
 
464
 
 
465
                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
466
                UMP_DEBUG_ASSERT( mode == lock->locked_as,
 
467
                                                   ("This lock was locked as==%.8X, but tried to unlock as mode==%.8X\n", lock->locked_as, mode));
 
468
                UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF );
 
469
 
 
470
                {
 
471
                        int call_result;
 
472
                        call_result = pthread_mutex_unlock( &lock->mutex );
 
473
                        UMP_DEBUG_ASSERT( 0 == call_result,
 
474
                                                           ("pthread_mutex_lock call failed with error code %d\n", call_result));
 
475
                        UMP_IGNORE( call_result );
 
476
                }
 
477
                break;
 
478
 
 
479
        case _UMP_OSU_LOCKFLAG_ANYUNLOCK:
 
480
                /** @note Use of bitflags in a case statement ONLY works because this
 
481
                 * is the ONLY flag that is supported */
 
482
 
 
483
                pthread_mutex_lock(&lock->mutex);
 
484
                UMP_DEBUG_ASSERT( UMP_TRUE == lock->state, ("Unlocking a _ump_osu_lock_t %p which is not locked\n", lock));
 
485
 
 
486
                /* DEBUG tracking of previously locked state - occurs while lock is obtained */
 
487
                UMP_DEBUG_ASSERT( mode == lock->locked_as,
 
488
                                                   ("This lock was locked as==%.8X, but tried to unlock as %.8X\n", lock->locked_as, mode ));
 
489
                UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF );
 
490
 
 
491
                /* mark as unlocked */
 
492
                lock->state = UMP_FALSE;
 
493
 
 
494
                /* signal the condition, only wake a single thread */
 
495
                pthread_cond_signal(&lock->condition);
 
496
 
 
497
                pthread_mutex_unlock(&lock->mutex);
 
498
                break;
 
499
 
 
500
        default:
 
501
                UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) );
 
502
                break;
 
503
        }
 
504
}
 
505
 
 
506
void _ump_osu_lock_term( _ump_osu_lock_t *lock )
 
507
{
 
508
        int call_result;
 
509
        UMP_DEBUG_ASSERT_POINTER( lock );
 
510
 
 
511
        /** Debug lock checking: */
 
512
        /* Lock is signalled on terminate - not a guarantee, since we could be locked immediately beforehand */
 
513
        UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as,
 
514
                                           ("cannot terminate held lock\n") );
 
515
 
 
516
        call_result = pthread_mutex_destroy( &lock->mutex );
 
517
        UMP_DEBUG_ASSERT( 0 == call_result,
 
518
                                           ("Incorrect mutex use detected: pthread_mutex_destroy call failed with error code %d\n", call_result) );
 
519
 
 
520
        /* Destroy extra state for ANY_UNLOCK type osu_locks */
 
521
        if ( lock->flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK )
 
522
        {
 
523
                UMP_DEBUG_ASSERT( UMP_FALSE == lock->state, ("terminate called on locked object %p\n", lock));
 
524
                call_result = pthread_cond_destroy(&lock->condition);
 
525
                UMP_DEBUG_ASSERT( 0 == call_result,
 
526
                                                   ("Incorrect condition-variable use detected: pthread_cond_destroy call failed with error code %d\n", call_result) );
 
527
        }
 
528
 
 
529
        UMP_IGNORE(call_result);
 
530
 
 
531
        _ump_osu_free( lock );
 
532
}
 
533
 
 
534
_ump_osu_lock_t *_ump_osu_lock_static( u32 nr )
 
535
{
 
536
        UMP_DEBUG_ASSERT( nr < UMP_OSU_STATIC_LOCK_COUNT,
 
537
                           ("provided static lock index (%d) out of bounds (0 < nr < %d)\n", nr, UMP_OSU_STATIC_LOCK_COUNT) );
 
538
        return &_ump_osu_static_locks[nr];
 
539
}