summaryrefslogtreecommitdiffstats
path: root/domx/mm_osal/src/timm_osal_events.c
diff options
context:
space:
mode:
Diffstat (limited to 'domx/mm_osal/src/timm_osal_events.c')
-rwxr-xr-xdomx/mm_osal/src/timm_osal_events.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/domx/mm_osal/src/timm_osal_events.c b/domx/mm_osal/src/timm_osal_events.c
new file mode 100755
index 0000000..96f8e59
--- /dev/null
+++ b/domx/mm_osal/src/timm_osal_events.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2010, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+* @file timm_osal_events.c
+* This file contains methods that provides the functionality
+* for creating/using events.
+*
+* @path \
+*
+*/
+/* -------------------------------------------------------------------------- */
+/* =========================================================================
+ *!
+ *! Revision History
+ *! ===================================
+ *! 06-Nov-2008 Maiya ShreeHarsha: Linux specific changes
+ *! 0.1: Created the first draft version, ksrini@ti.com
+ * ========================================================================= */
+
+/******************************************************************************
+* Includes
+******************************************************************************/
+#include <stdio.h>
+#include <pthread.h> /*for POSIX calls */
+#include <sys/time.h>
+#include <errno.h>
+
+#include "timm_osal_types.h"
+#include "timm_osal_trace.h"
+#include "timm_osal_error.h"
+#include "timm_osal_memory.h"
+#include "timm_osal_events.h"
+
+
+typedef struct
+{
+ TIMM_OSAL_BOOL bSignaled;
+ TIMM_OSAL_U32 eFlags;
+ pthread_mutex_t mutex;
+ pthread_cond_t condition;
+} TIMM_OSAL_THREAD_EVENT;
+
+
+/* ========================================================================== */
+/**
+* @fn TIMM_OSAL_EventCreate function
+*
+*
+*/
+/* ========================================================================== */
+TIMM_OSAL_ERRORTYPE TIMM_OSAL_EventCreate(TIMM_OSAL_PTR * pEvents)
+{
+ TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ TIMM_OSAL_THREAD_EVENT *plEvent = NULL;
+
+ plEvent =
+ (TIMM_OSAL_THREAD_EVENT *)
+ TIMM_OSAL_Malloc(sizeof(TIMM_OSAL_THREAD_EVENT), 0, 0, 0);
+
+ if (TIMM_OSAL_NULL == plEvent)
+ {
+ bReturnStatus = TIMM_OSAL_ERR_ALLOC;
+ goto EXIT;
+ }
+ plEvent->bSignaled = TIMM_OSAL_FALSE;
+ plEvent->eFlags = 0;
+
+ if (SUCCESS != pthread_mutex_init(&(plEvent->mutex), NULL))
+ {
+ TIMM_OSAL_Error("Event Create:Mutex Init failed !");
+ goto EXIT; /*bReturnStatus = TIMM_OSAL_ERR_UNKNOWN */
+ }
+
+ if (SUCCESS != pthread_cond_init(&(plEvent->condition), NULL))
+ {
+ TIMM_OSAL_Error
+ ("Event Create:Conditional Variable Init failed !");
+ pthread_mutex_destroy(&(plEvent->mutex));
+ /*TIMM_OSAL_Free(plEvent); */
+ } else
+ {
+ *pEvents = (TIMM_OSAL_PTR) plEvent;
+ bReturnStatus = TIMM_OSAL_ERR_NONE;
+ }
+ EXIT:
+ if ((TIMM_OSAL_ERR_NONE != bReturnStatus) &&
+ (TIMM_OSAL_NULL != plEvent))
+ {
+ TIMM_OSAL_Free(plEvent);
+ }
+ return bReturnStatus;
+}
+
+/* ========================================================================== */
+/**
+* @fn TIMM_OSAL_EventDelete function
+*
+*
+*/
+/* ========================================================================== */
+TIMM_OSAL_ERRORTYPE TIMM_OSAL_EventDelete(TIMM_OSAL_PTR pEvents)
+{
+ TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_NONE;
+ TIMM_OSAL_THREAD_EVENT *plEvent = (TIMM_OSAL_THREAD_EVENT *) pEvents;
+
+ if (TIMM_OSAL_NULL == plEvent)
+ {
+ bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
+ goto EXIT;
+ }
+
+ if (SUCCESS != pthread_mutex_lock(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Delete: Mutex Lock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ }
+ if (SUCCESS != pthread_cond_destroy(&(plEvent->condition)))
+ {
+ TIMM_OSAL_Error
+ ("Event Delete: Conditional Variable Destroy failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ }
+
+ if (SUCCESS != pthread_mutex_unlock(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Delete: Mutex Unlock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ }
+
+ if (SUCCESS != pthread_mutex_destroy(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Delete: Mutex Destory failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ }
+
+ TIMM_OSAL_Free(plEvent);
+ EXIT:
+ return bReturnStatus;
+}
+
+
+/* ========================================================================== */
+/**
+* @fn TIMM_OSAL_EventSet function
+*
+*
+*/
+/* ========================================================================== */
+TIMM_OSAL_ERRORTYPE TIMM_OSAL_EventSet(TIMM_OSAL_PTR pEvents,
+ TIMM_OSAL_U32 uEventFlags, TIMM_OSAL_EVENT_OPERATION eOperation)
+{
+
+ TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ TIMM_OSAL_THREAD_EVENT *plEvent = (TIMM_OSAL_THREAD_EVENT *) pEvents;
+
+ if (TIMM_OSAL_NULL == plEvent)
+ {
+ bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
+ goto EXIT;
+ }
+
+ if (SUCCESS != pthread_mutex_lock(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Set: Mutex Lock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ goto EXIT;
+ }
+
+ switch (eOperation)
+ {
+ case TIMM_OSAL_EVENT_AND:
+ plEvent->eFlags = plEvent->eFlags & uEventFlags;
+ break;
+ case TIMM_OSAL_EVENT_OR:
+ plEvent->eFlags = plEvent->eFlags | uEventFlags;
+ break;
+ default:
+ TIMM_OSAL_Error("Event Set: Bad eOperation !");
+ bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
+ pthread_mutex_unlock(&plEvent->mutex);
+ goto EXIT;
+ }
+
+ plEvent->bSignaled = TIMM_OSAL_TRUE;
+
+ if (SUCCESS != pthread_cond_signal(&plEvent->condition))
+ {
+ TIMM_OSAL_Error
+ ("Event Set: Condition Variable Signal failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ pthread_mutex_unlock(&plEvent->mutex);
+ goto EXIT;
+ }
+
+ if (SUCCESS != pthread_mutex_unlock(&plEvent->mutex))
+ {
+ TIMM_OSAL_Error("Event Set: Mutex Unlock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ } else
+ bReturnStatus = TIMM_OSAL_ERR_NONE;
+
+ EXIT:
+ return bReturnStatus;
+
+
+}
+
+/* ========================================================================== */
+/**
+* @fn TIMM_OSAL_EventRetrieve function
+*
+*Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur.
+*
+*A representative sequence for using condition variables is shown below
+*
+*Thread A (Retrieve Events) |Thread B (Set Events)
+*------------------------------------------------------------------------------------------------------------
+*1) Do work up to the point where a certain condition |1)Do work
+* must occur (such as "count" must reach a specified |2)Lock associated mutex
+* value) |3)Change the value of the global variable
+*2) Lock associated mutex and check value of a global | that Thread-A is waiting upon.
+* variable |4)Check value of the global Thread-A wait
+*3) Call pthread_cond_wait() to perform a blocking wait | variable. If it fulfills the desired
+* for signal from Thread-B. Note that a call to | condition, signal Thread-A.
+* pthread_cond_wait() automatically and atomically |5)Unlock mutex.
+* unlocks the associated mutex variable so that it can |6)Continue
+* be used by Thread-B. |
+*4) When signalled, wake up. Mutex is automatically and |
+* atomically locked. |
+*5) Explicitly unlock mutex |
+*6) Continue |
+*
+*/
+/* ========================================================================== */
+TIMM_OSAL_ERRORTYPE TIMM_OSAL_EventRetrieve(TIMM_OSAL_PTR pEvents,
+ TIMM_OSAL_U32 uRequestedEvents,
+ TIMM_OSAL_EVENT_OPERATION eOperation,
+ TIMM_OSAL_U32 * pRetrievedEvents, TIMM_OSAL_U32 uTimeOutMsec)
+{
+ TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ struct timespec timeout;
+ struct timeval now;
+ TIMM_OSAL_U32 timeout_us;
+ TIMM_OSAL_U32 isolatedFlags;
+ int status = -1;
+ int and_operation;
+ TIMM_OSAL_THREAD_EVENT *plEvent = (TIMM_OSAL_THREAD_EVENT *) pEvents;
+
+ if (TIMM_OSAL_NULL == plEvent)
+ {
+ bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
+ goto EXIT;
+ }
+
+ /* Lock the mutex for access to the eFlags global variable */
+ if (SUCCESS != pthread_mutex_lock(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Retrieve: Mutex Lock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ goto EXIT;
+ }
+
+ /*Check the eOperation and put it in a variable */
+ and_operation = ((TIMM_OSAL_EVENT_AND == eOperation) ||
+ (TIMM_OSAL_EVENT_AND_CONSUME == eOperation));
+
+ /* Isolate the flags. The & operation is suffice for an TIMM_OSAL_EVENT_OR eOperation */
+ isolatedFlags = plEvent->eFlags & uRequestedEvents;
+
+ /*Check if it is the AND operation. If yes then, all the flags must match */
+ if (and_operation)
+ {
+ isolatedFlags = (isolatedFlags == uRequestedEvents);
+ }
+
+
+ if (isolatedFlags)
+ {
+
+ /*We have got required combination of the eFlags bits and will return it back */
+ *pRetrievedEvents = plEvent->eFlags;
+ bReturnStatus = TIMM_OSAL_ERR_NONE;
+ } else
+ {
+
+ /*Required combination of bits is not yet available */
+ if (TIMM_OSAL_NO_SUSPEND == uTimeOutMsec)
+ {
+ *pRetrievedEvents = 0;
+ bReturnStatus = TIMM_OSAL_ERR_NONE;
+ }
+
+ else if (TIMM_OSAL_SUSPEND == uTimeOutMsec)
+ {
+
+ /*Wait till we get the required combination of bits. We we get the required
+ *bits then we go out of the while loop
+ */
+ while (!isolatedFlags)
+ {
+
+ /*Wait on the conditional variable for another thread to set the eFlags and signal */
+ pthread_cond_wait(&(plEvent->condition),
+ &(plEvent->mutex));
+
+ /* eFlags set by some thread. Now, isolate the flags.
+ * The & operation is suffice for an TIMM_OSAL_EVENT_OR eOperation
+ */
+ isolatedFlags =
+ plEvent->eFlags & uRequestedEvents;
+
+ /*Check if it is the AND operation. If yes then, all the flags must match */
+ if (and_operation)
+ {
+ isolatedFlags =
+ (isolatedFlags ==
+ uRequestedEvents);
+ }
+ }
+
+ /* Obtained the requested combination of bits on eFlags */
+ *pRetrievedEvents = plEvent->eFlags;
+ bReturnStatus = TIMM_OSAL_ERR_NONE;
+
+ } else
+ {
+
+ /* Calculate uTimeOutMsec in terms of the absolute time. uTimeOutMsec is in milliseconds */
+ gettimeofday(&now, NULL);
+ timeout_us = now.tv_usec + 1000 * uTimeOutMsec;
+ timeout.tv_sec = now.tv_sec + timeout_us / 1000000;
+ timeout.tv_nsec = (timeout_us % 1000000) * 1000;
+
+ while (!isolatedFlags)
+ {
+
+ /* Wait till uTimeOutMsec for a thread to signal on the conditional variable */
+ status =
+ pthread_cond_timedwait(&(plEvent->
+ condition), &(plEvent->mutex),
+ &timeout);
+
+ /*Timedout or error and returned without being signalled */
+ if (SUCCESS != status)
+ {
+ if (ETIMEDOUT == status)
+ bReturnStatus =
+ TIMM_OSAL_ERR_NONE;
+ *pRetrievedEvents = 0;
+ break;
+ }
+
+ /* eFlags set by some thread. Now, isolate the flags.
+ * The & operation is suffice for an TIMM_OSAL_EVENT_OR eOperation
+ */
+ isolatedFlags =
+ plEvent->eFlags & uRequestedEvents;
+
+ /*Check if it is the AND operation. If yes then, all the flags must match */
+ if (and_operation)
+ {
+ isolatedFlags =
+ (isolatedFlags ==
+ uRequestedEvents);
+ }
+
+ }
+ }
+ }
+
+ /*If we have got the required combination of bits, we will have to reset the eFlags if CONSUME is mentioned
+ *in the eOperations
+ */
+ if (isolatedFlags && ((eOperation == TIMM_OSAL_EVENT_AND_CONSUME) ||
+ (eOperation == TIMM_OSAL_EVENT_OR_CONSUME)))
+ {
+ plEvent->eFlags = 0;
+ }
+
+ /*Manually unlock the mutex */
+ if (SUCCESS != pthread_mutex_unlock(&(plEvent->mutex)))
+ {
+ TIMM_OSAL_Error("Event Retrieve: Mutex Unlock failed !");
+ bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
+ }
+
+ EXIT:
+ return bReturnStatus;
+
+}