diff options
Diffstat (limited to 'domx/mm_osal/src/timm_osal_events.c')
-rwxr-xr-x | domx/mm_osal/src/timm_osal_events.c | 420 |
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; + +} |