summaryrefslogtreecommitdiffstats
path: root/exynos4/hal/libump/os
diff options
context:
space:
mode:
Diffstat (limited to 'exynos4/hal/libump/os')
-rw-r--r--exynos4/hal/libump/os/linux/ump_ioctl.h55
-rw-r--r--exynos4/hal/libump/os/linux/ump_osu_locks.c537
-rw-r--r--exynos4/hal/libump/os/linux/ump_osu_memory.c60
-rw-r--r--exynos4/hal/libump/os/linux/ump_uku.c193
-rw-r--r--exynos4/hal/libump/os/ump_uku.h56
5 files changed, 901 insertions, 0 deletions
diff --git a/exynos4/hal/libump/os/linux/ump_ioctl.h b/exynos4/hal/libump/os/linux/ump_ioctl.h
new file mode 100644
index 0000000..e978858
--- /dev/null
+++ b/exynos4/hal/libump/os/linux/ump_ioctl.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef __UMP_IOCTL_H__
+#define __UMP_IOCTL_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <ump_uk_types.h>
+
+#ifndef __user
+#define __user
+#endif
+
+
+/**
+ * @file UMP_ioctl.h
+ * This file describes the interface needed to use the Linux device driver.
+ * The interface is used by the userpace UMP driver.
+ */
+
+#define UMP_IOCTL_NR 0x90
+
+
+#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s)
+#define UMP_IOC_ALLOCATE _IOWR(UMP_IOCTL_NR, _UMP_IOC_ALLOCATE, _ump_uk_allocate_s)
+#define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s)
+#define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s)
+#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_size_get_s)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_IOCTL_H__ */
diff --git a/exynos4/hal/libump/os/linux/ump_osu_locks.c b/exynos4/hal/libump/os/linux/ump_osu_locks.c
new file mode 100644
index 0000000..97ba858
--- /dev/null
+++ b/exynos4/hal/libump/os/linux/ump_osu_locks.c
@@ -0,0 +1,537 @@
+/*
+ * 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];
+}
diff --git a/exynos4/hal/libump/os/linux/ump_osu_memory.c b/exynos4/hal/libump/os/linux/ump_osu_memory.c
new file mode 100644
index 0000000..5807594
--- /dev/null
+++ b/exynos4/hal/libump/os/linux/ump_osu_memory.c
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#include <ump/ump_osu.h>
+
+#include <stdlib.h>
+#include <string.h> /* memcmp, memchr, memset */
+
+/**
+ * @file ump_osu_memory.c
+ * File implements the user side of the OS interface
+ */
+
+void *_ump_osu_calloc( u32 n, u32 size )
+{
+ return calloc( n, size );
+}
+
+void *_ump_osu_malloc( u32 size )
+{
+ return malloc( size );
+}
+
+void *_ump_osu_realloc( void *ptr, u32 size )
+{
+ return realloc( ptr, size );
+}
+
+void _ump_osu_free( void *ptr )
+{
+ free( ptr );
+}
+
+void *_ump_osu_memcpy( void *dst, const void *src, u32 len )
+{
+ return memcpy( dst, src, len );
+}
+
+void *_ump_osu_memset( void *ptr, u32 chr, u32 size )
+{
+ return memset( ptr, chr, size );
+}
+
+int _ump_osu_memcmp( const void *ptr1, const void *ptr2, u32 size )
+{
+ return memcmp( ptr1, ptr2, size );
+}
diff --git a/exynos4/hal/libump/os/linux/ump_uku.c b/exynos4/hal/libump/os/linux/ump_uku.c
new file mode 100644
index 0000000..f46a2c7
--- /dev/null
+++ b/exynos4/hal/libump/os/linux/ump_uku.c
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ump_uku.c
+ * File implements the user side of the user-kernel interface
+ */
+
+#include "../ump_uku.h"
+#include <stdio.h>
+#include "ump_ioctl.h"
+
+#include <sys/mman.h>
+
+/* Needed for file operations on the device file*/
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args);
+
+static int ump_ioctl_api_version_used = UMP_IOCTL_API_VERSION;
+
+/**
+ * The device file to access the UMP device driver
+ * This is a character special file giving access to the device driver.
+ * Usually created using the mknod command line utility.
+ */
+static const char ump_device_file_name[] = "/dev/ump";
+
+_ump_osu_errcode_t _ump_uku_open( void **context )
+{
+ int ump_device_file;
+ if(NULL == context)
+ {
+ return _UMP_OSU_ERR_FAULT;
+ }
+
+ ump_device_file = open(ump_device_file_name, O_RDWR);
+
+ if (-1 == ump_device_file)
+ {
+ return _UMP_OSU_ERR_FAULT;
+ }
+
+ {
+ struct _ump_uk_api_version_s args;
+ args.ctx = (void*)ump_device_file;
+ args.version = UMP_IOCTL_API_VERSION;
+ args.compatible = 3;
+ ump_driver_ioctl(args.ctx, UMP_IOC_QUERY_API_VERSION, &args);
+ if ( 1 != args.compatible )
+ {
+ if (IS_API_MATCH(MAKE_VERSION_ID(1), args.version))
+ {
+ ump_ioctl_api_version_used = MAKE_VERSION_ID(1);
+ UMP_PRINTF("The UMP devicedriver does not support cached UMP. Update it if this is needed.\n");
+ }
+ else
+ {
+ UMP_PRINTF("The UMP devicedriver is version: %d, UMP libraries is version: %d.\n", GET_VERSION(args.version), GET_VERSION(UMP_IOCTL_API_VERSION) );
+ close(ump_device_file);
+ return _UMP_OSU_ERR_FAULT;
+ }
+ }
+ }
+
+ *context = (void *) ump_device_file;
+ return _UMP_OSU_ERR_OK;
+}
+
+_ump_osu_errcode_t _ump_uku_close( void **context )
+{
+ if(NULL == context)
+ {
+ return _UMP_OSU_ERR_FAULT;
+ }
+
+ if(-1 == (int)*context)
+ {
+ return _UMP_OSU_ERR_FAULT;
+ }
+
+ close((int)*context);
+ *context = (void *)-1;
+
+ return _UMP_OSU_ERR_OK;
+}
+
+int _ump_uku_allocate(_ump_uk_allocate_s *args)
+{
+ return ump_driver_ioctl(args->ctx, UMP_IOC_ALLOCATE, args);
+}
+
+_ump_osu_errcode_t _ump_uku_release(_ump_uk_release_s *args)
+{
+ return ump_driver_ioctl(args->ctx, UMP_IOC_RELEASE, args);
+}
+
+_ump_osu_errcode_t _ump_uku_size_get(_ump_uk_size_get_s *args)
+{
+ return ump_driver_ioctl(args->ctx, UMP_IOC_SIZE_GET, args);
+}
+
+
+void _ump_uku_msynch(_ump_uk_msync_s *args)
+{
+ /* This is for backwards compatibillity */
+ if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used)
+ {
+ args->is_cached = 0;
+ if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED != args->op )
+ {
+ UMP_DEBUG_PRINT(3, ("Warning: Doing UMP cache flush operations on a Device Driver that does not support cached UMP mem.\n"));
+ }
+ return;
+ }
+ ump_driver_ioctl(args->ctx, UMP_IOC_MSYNC, args);
+}
+
+int _ump_uku_map_mem(_ump_uk_map_mem_s *args)
+{
+ int flags;
+ if( -1 == (int)args->ctx )
+ {
+ return -1;
+ }
+
+ flags = MAP_SHARED;
+
+ /* This is for backwards compatibillity */
+ if ( MAKE_VERSION_ID(1) == ump_ioctl_api_version_used)
+ {
+ args->is_cached = 0;
+ }
+
+ /* If we want the Caching to be enabled we set the flags to be PRIVATE. The UMP DD reads this and do proper handling
+ Note: this enforces the user to use proper invalidation*/
+ if ( args->is_cached ) flags = MAP_PRIVATE;
+
+ args->mapping = mmap(NULL, args->size, PROT_READ | PROT_WRITE ,flags , (int)args->ctx, (off_t)args->secure_id * sysconf(_SC_PAGE_SIZE));
+ if (MAP_FAILED == args->mapping)
+ {
+ return -1;
+ }
+
+ args->cookie = 0; /* Cookie is not used in linux _ump_uku_unmap_mem */
+
+ return 0;
+}
+
+void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args )
+{
+ /*
+ * If a smaller size is used Linux will just remove the requested range but don't tell
+ * the ump driver before all of it is unmapped, either via another unmap request or upon process shutdown.
+ * Unmapping too much will just ignore the overhead or hit undefined behavior,
+ * only affecting the calling process which could mess itself up in other ways anyway.
+ * So we don't need any security checks here.
+ */
+ munmap(args->mapping, args->size);
+}
+
+static _ump_osu_errcode_t ump_driver_ioctl(void *context, u32 command, void *args)
+{
+ /*UMP_CHECK_NON_NULL(args, _UMP_OSK_ERR_INVALID_ARGS);*/
+
+ /* check for a valid file descriptor */
+ /** @note manual type safety check-point */
+ if( -1 == (int)context )
+ {
+ return _UMP_OSU_ERR_FAULT;
+ }
+
+ /* call ioctl handler of driver */
+ if (0 != ioctl((int)context, command, args)) return -1;
+ return _UMP_OSU_ERR_OK;
+}
diff --git a/exynos4/hal/libump/os/ump_uku.h b/exynos4/hal/libump/os/ump_uku.h
new file mode 100644
index 0000000..7da7185
--- /dev/null
+++ b/exynos4/hal/libump/os/ump_uku.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ump_uku.h
+ * Defines the user-side interface of the user-kernel interface
+ */
+
+#ifndef __UMP_UKU_H__
+#define __UMP_UKU_H__
+
+#include <ump/ump_osu.h>
+#include <ump/ump_debug.h>
+#include <ump/ump_uk_types.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+_ump_osu_errcode_t _ump_uku_open( void **context );
+
+_ump_osu_errcode_t _ump_uku_close( void **context );
+
+_ump_osu_errcode_t _ump_uku_allocate( _ump_uk_allocate_s *args );
+
+_ump_osu_errcode_t _ump_uku_release( _ump_uk_release_s *args );
+
+_ump_osu_errcode_t _ump_uku_size_get( _ump_uk_size_get_s *args );
+
+_ump_osu_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args );
+
+int _ump_uku_map_mem( _ump_uk_map_mem_s *args );
+
+void _ump_uku_unmap_mem( _ump_uk_unmap_mem_s *args );
+
+void _ump_uku_msynch(_ump_uk_msync_s *args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UKU_H__ */