diff options
Diffstat (limited to 'exynos4/hal/libump/os/linux/ump_osu_locks.c')
-rw-r--r-- | exynos4/hal/libump/os/linux/ump_osu_locks.c | 537 |
1 files changed, 0 insertions, 537 deletions
diff --git a/exynos4/hal/libump/os/linux/ump_osu_locks.c b/exynos4/hal/libump/os/linux/ump_osu_locks.c deleted file mode 100644 index 97ba858..0000000 --- a/exynos4/hal/libump/os/linux/ump_osu_locks.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if ((!defined _XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 600)) -#undef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 -#endif - - -#define _POSIX_C_SOURCE 200112L - -#include <ump/ump_osu.h> -#include <ump/ump_debug.h> - -#include <pthread.h> -#include <time.h> -#include <sys/time.h> -#include <errno.h> - -/** - * @file ump_osu_locks.c - * File implements the user side of the OS interface - */ - -/** @opt Most of the time, we use the plain mutex type of osu_lock, and so - * only require the flags and mutex members. This costs 2 extra DWORDS, but - * most of the time we don't use those DWORDS. - * Therefore, ANY_UNLOCK type osu_locks can be implemented as a second - * structure containing the member _ump_osu_lock_t lock_t, plus the extra - * state required. Then, we use &container->lock_t when passing out of the - * OSU api, and CONTAINER_OF() when passing back in to recover the original - * structure. */ - -/** Private declaration of the OSU lock type */ -struct _ump_osu_lock_t_struct -{ - /** At present, only two types of mutex, so we store this information as - * the flags supplied at init time */ - _ump_osu_lock_flags_t flags; - - pthread_mutex_t mutex; /**< Used in both plain and ANY_UNLOCK osu_locks */ - - /* Extra State for ANY_UNLOCK osu_locks. These are UNINITIALIZED when - * flags does not contain _UMP_OSU_LOCKFLAG_ANYUNLOCK: */ - pthread_cond_t condition; /**< The condition object to use while blocking */ - ump_bool state; /**< The boolean which indicates the event's state */ - - UMP_DEBUG_CODE( - /** debug checking of locks */ - _ump_osu_lock_mode_t locked_as; - ) /* UMP_DEBUG_CODE */ - -}; - -/* Provide two statically initialized locks */ -UMP_STATIC _ump_osu_lock_t _ump_osu_static_locks[] = -{ - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, - { - _UMP_OSU_LOCKFLAG_STATIC, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - UMP_FALSE, - UMP_DEBUG_CODE( _UMP_OSU_LOCKMODE_UNDEF ) - }, -}; - -/* Critical section for auto_init */ -UMP_STATIC pthread_mutex_t static_auto_init_mutex = PTHREAD_MUTEX_INITIALIZER; - - -_ump_osu_errcode_t _ump_osu_lock_auto_init( _ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order ) -{ - int call_result; - /* Validate parameters: */ - UMP_DEBUG_ASSERT_POINTER( pplock ); - - /** @opt We don't lock the Critical Section or do anything if this is already non-null */ - if ( NULL != *pplock) - { - return _UMP_OSU_ERR_OK; - } - - /* We MIGHT need to initialize it, lock the Critical Section and check again */ - call_result = pthread_mutex_lock(&static_auto_init_mutex); - /* It would be a programming error for this to fail: */ - UMP_DEBUG_ASSERT( 0 == call_result, - ("failed to lock critical section\n") ); - - if ( NULL != *pplock ) - { - /* - We caught a race condition to initialize this osu_lock. - The other thread won the race, so the osu_lock is now initialized. - */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - return _UMP_OSU_ERR_OK; - } - - /* We're the first thread in: initialize the osu_lock */ - *pplock = _ump_osu_lock_init( flags, initial, order ); - - if ( NULL == *pplock ) - { - /* osu_lock creation failed */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - return _UMP_OSU_ERR_FAULT; - } - - - /* osu_lock created OK */ - call_result = pthread_mutex_unlock(&static_auto_init_mutex); - - UMP_DEBUG_ASSERT(0 == call_result, - ("failed to unlock critical section\n")); - - UMP_IGNORE( call_result ); - - return _UMP_OSU_ERR_OK; -} - - -_ump_osu_lock_t *_ump_osu_lock_init( _ump_osu_lock_flags_t flags, u32 initial, u32 order ) -{ - _ump_osu_lock_t * lock; - pthread_mutexattr_t mutex_attributes; - - /* Validate parameters: */ - /* Flags acceptable */ - UMP_DEBUG_ASSERT( 0 == ( flags & ~( _UMP_OSU_LOCKFLAG_ANYUNLOCK)), - ("incorrect flags or trying to initialise a statically initialized lock, %.8X\n", flags) ); - - /* Parameter initial SBZ - for future expansion */ - UMP_DEBUG_ASSERT( 0 == initial, - ("initial must be zero\n") ); - - if (0 != pthread_mutexattr_init(&mutex_attributes)) - { - return NULL; - } - -#if UMP_DEBUG_EXTENDED_MUTEX_LOCK_CHECKING -#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK -#else -#define UMP_PTHREADS_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT -#endif - - if (0 != pthread_mutexattr_settype(&mutex_attributes, UMP_PTHREADS_MUTEX_TYPE)) - { - /** Return NULL on failure */ - pthread_mutexattr_destroy(&mutex_attributes); - return NULL; - - } - -#undef UMP_PTHREADS_MUTEX_TYPE - - /** @opt use containing structures for the ANY_UNLOCK type, to - * save 2 DWORDS when not in use */ - lock = _ump_osu_malloc( sizeof(_ump_osu_lock_t) ); - - if( NULL == lock ) - { - /** Return NULL on failure */ - pthread_mutexattr_destroy(&mutex_attributes); - return NULL; - } - - if (0 != pthread_mutex_init( &lock->mutex, &mutex_attributes )) - { - pthread_mutexattr_destroy(&mutex_attributes); - _ump_osu_free( lock ); - return NULL; - } - - /* done with the mutexattr object */ - pthread_mutexattr_destroy(&mutex_attributes); - - /* ANY_UNLOCK type */ - if ( flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK ) - { - if (0 != pthread_cond_init( &lock->condition, NULL )) - { - /* cleanup */ - pthread_mutex_destroy( &lock->mutex ); - _ump_osu_free( lock ); - return NULL; - } - lock->state = UMP_FALSE; /* mark as unlocked by default */ - } - - lock->flags = flags; - - /** Debug lock checking */ - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - return lock; -} - -_ump_osu_errcode_t _ump_osu_lock_timed_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout) -{ - /* absolute time specifier */ - struct timespec ts; - struct timeval tv; - - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKFLAG_ANYUNLOCK == lock->flags, ("Timed operations only implemented for ANYUNLOCK type locks")); - - /* calculate the realtime timeout value */ - - if (0 != gettimeofday(&tv, NULL)) - { - UMP_DEBUG_PRINT(1,("Could not get the current realtime value to calculate the absolute value for a timed mutex lock with a timeout")); - return _UMP_OSU_ERR_FAULT; - } - - tv.tv_usec += timeout; - -#define UMP_USECS_PER_SECOND 1000000ULL -#define UMP_NANOSECS_PER_USEC 1000ULL - - /* did we overflow a second in the usec part? */ - while (tv.tv_usec >= UMP_USECS_PER_SECOND) - { - tv.tv_usec -= UMP_USECS_PER_SECOND; - tv.tv_sec++; - } - - /* copy to the correct struct */ - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = (tv.tv_usec * UMP_NANOSECS_PER_USEC); - -#undef UMP_USECS_PER_SECOND -#undef UMP_NANOSECS_PER_USEC - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock( &lock->mutex ); - /* loop while locked (state is UMP_TRUE) */ - /* pthread_cond_timedwait unlocks the mutex, wait, and locks the mutex once unblocked (either due to the event or the timeout) */ - while ( UMP_TRUE == lock->state ) - { - int res; - res = pthread_cond_timedwait( &lock->condition, &lock->mutex, &ts ); - if (0 == res) continue; /* test the state variable again (loop condition) */ - else if (ETIMEDOUT == res) - { - /* timeout, need to clean up and return the correct error code */ - pthread_mutex_unlock(&lock->mutex); - return _UMP_OSU_ERR_TIMEOUT; - } - else - { - UMP_DEBUG_PRINT(1, ("Unexpected return from pthread_cond_timedwait 0x%08X\n", res)); - - pthread_mutex_unlock(&lock->mutex); - return _UMP_OSU_ERR_FAULT; - } - - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - - /* 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 */ - lock->state = UMP_TRUE; - /* final unlock of the mutex */ - pthread_mutex_unlock(&lock->mutex); - - return _UMP_OSU_ERR_OK; - -} - -_ump_osu_errcode_t _ump_osu_lock_wait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode) -{ - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - { - int call_result; - call_result = pthread_mutex_lock( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("pthread_mutex_lock call failed with error code %d\n", call_result)); - UMP_IGNORE( call_result ); - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock( &lock->mutex ); - /* loop while locked (state is UMP_TRUE) */ - /* pthread_cond_wait unlocks the mutex, wait, and locks the mutex once unblocked */ - while ( UMP_TRUE == lock->state ) pthread_cond_wait( &lock->condition, &lock->mutex ); - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("This lock was already locked\n") ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - - /* 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 */ - lock->state = UMP_TRUE; - /* final unlock of the mutex */ - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } - - return _UMP_OSU_ERR_OK; -} - -_ump_osu_errcode_t _ump_osu_lock_trywait( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode) -{ - _ump_osu_errcode_t err = _UMP_OSU_ERR_FAULT; - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - { - /* This is not subject to UMP_CHECK - overriding the result would cause a programming error */ - if ( 0 == pthread_mutex_trylock( &lock->mutex ) ) - { - err = _UMP_OSU_ERR_OK; - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as - || mode == lock->locked_as, - ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) ); - UMP_DEBUG_CODE( lock->locked_as = mode ); - } - } - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - /* lock the mutex protecting access to the state field */ - pthread_mutex_lock(&lock->mutex); - - if ( UMP_FALSE == lock->state) - { - /* unlocked, take the lock */ - lock->state = UMP_TRUE; - err = _UMP_OSU_ERR_OK; - } - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - /* Can do this regardless of whether we obtained ANYUNLOCK: */ - - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as - || mode == lock->locked_as, - ("tried as mode==%.8X, but was locked as %.8X\n", mode, lock->locked_as) ); - /* If we were already locked, this does no harm, because of the above assert: */ - UMP_DEBUG_CODE( lock->locked_as = mode ); - - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } - - return err; -} - - -void _ump_osu_lock_signal( _ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode ) -{ - /* Parameter validation */ - UMP_DEBUG_ASSERT_POINTER( lock ); - - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_RW == mode, - ("unrecognised mode, %.8X\n", mode) ); - - /** @note since only one flag can be set, we use a switch statement here. - * Otherwise, MUST add an enum into the _ump_osu_lock_t to store the - * implemented lock type */ - switch ( lock->flags ) - { - case _UMP_OSU_LOCKFLAG_STATIC: - case 0: - /* Usual Mutex type */ - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( mode == lock->locked_as, - ("This lock was locked as==%.8X, but tried to unlock as mode==%.8X\n", lock->locked_as, mode)); - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - { - int call_result; - call_result = pthread_mutex_unlock( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("pthread_mutex_lock call failed with error code %d\n", call_result)); - UMP_IGNORE( call_result ); - } - break; - - case _UMP_OSU_LOCKFLAG_ANYUNLOCK: - /** @note Use of bitflags in a case statement ONLY works because this - * is the ONLY flag that is supported */ - - pthread_mutex_lock(&lock->mutex); - UMP_DEBUG_ASSERT( UMP_TRUE == lock->state, ("Unlocking a _ump_osu_lock_t %p which is not locked\n", lock)); - - /* DEBUG tracking of previously locked state - occurs while lock is obtained */ - UMP_DEBUG_ASSERT( mode == lock->locked_as, - ("This lock was locked as==%.8X, but tried to unlock as %.8X\n", lock->locked_as, mode )); - UMP_DEBUG_CODE( lock->locked_as = _UMP_OSU_LOCKMODE_UNDEF ); - - /* mark as unlocked */ - lock->state = UMP_FALSE; - - /* signal the condition, only wake a single thread */ - pthread_cond_signal(&lock->condition); - - pthread_mutex_unlock(&lock->mutex); - break; - - default: - UMP_DEBUG_ERROR( ("lock has incorrect flags==%.8X\n", lock->flags) ); - break; - } -} - -void _ump_osu_lock_term( _ump_osu_lock_t *lock ) -{ - int call_result; - UMP_DEBUG_ASSERT_POINTER( lock ); - - /** Debug lock checking: */ - /* Lock is signalled on terminate - not a guarantee, since we could be locked immediately beforehand */ - UMP_DEBUG_ASSERT( _UMP_OSU_LOCKMODE_UNDEF == lock->locked_as, - ("cannot terminate held lock\n") ); - - call_result = pthread_mutex_destroy( &lock->mutex ); - UMP_DEBUG_ASSERT( 0 == call_result, - ("Incorrect mutex use detected: pthread_mutex_destroy call failed with error code %d\n", call_result) ); - - /* Destroy extra state for ANY_UNLOCK type osu_locks */ - if ( lock->flags & _UMP_OSU_LOCKFLAG_ANYUNLOCK ) - { - UMP_DEBUG_ASSERT( UMP_FALSE == lock->state, ("terminate called on locked object %p\n", lock)); - call_result = pthread_cond_destroy(&lock->condition); - UMP_DEBUG_ASSERT( 0 == call_result, - ("Incorrect condition-variable use detected: pthread_cond_destroy call failed with error code %d\n", call_result) ); - } - - UMP_IGNORE(call_result); - - _ump_osu_free( lock ); -} - -_ump_osu_lock_t *_ump_osu_lock_static( u32 nr ) -{ - UMP_DEBUG_ASSERT( nr < UMP_OSU_STATIC_LOCK_COUNT, - ("provided static lock index (%d) out of bounds (0 < nr < %d)\n", nr, UMP_OSU_STATIC_LOCK_COUNT) ); - return &_ump_osu_static_locks[nr]; -} |