Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      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  ************************************************************************
     18  * @file         M4OSA_Semaphore.c
     19  * @brief        Semaphore for Windows
     20  * @note         This file implements functions to manipulate semaphore
     21  ************************************************************************
     22 */
     23 
     24 
     25 
     26 #include "M4OSA_Debug.h"
     27 #include "M4OSA_Types.h"
     28 #include "M4OSA_Error.h"
     29 #include "M4OSA_Memory.h"
     30 #include "M4OSA_Semaphore.h"
     31 
     32 #include <semaphore.h>
     33 #include <string.h>
     34 #include <stdlib.h>
     35 #include <stdio.h>
     36 #include <errno.h>
     37 #include <time.h>
     38 
     39 
     40 /* Context for the semaphore */
     41 typedef struct {
     42    M4OSA_UInt32   coreID;     /* semaphore context identifiant */
     43    sem_t          semaphore;  /* semaphore */
     44 } M4OSA_SemaphoreContext;
     45 
     46 
     47 
     48 
     49 /**
     50  ************************************************************************
     51  * @brief      This method creates a new semaphore with the "initialCounter"
     52  *             value.
     53  * @note       This function creates and allocates a unique context. It's the
     54  *             OSAL real time responsibility for managing its context. It must
     55  *             be freed by the M4OSA_semaphoreClose function. The context
     56  *             parameter will be sent back to any OSAL core semaphore functions
     57  *             to allow retrieving data associated to the opened semaphore.
     58  * @param      context:(OUT) Context of the created semaphore
     59  * @param      initial_count:(IN) Initial counter of the semaphore
     60  * @return     M4NO_ERROR: there is no error
     61  * @return     M4ERR_PARAMETER: provided context is NULL
     62  * @return     M4ERR_ALLOC: there is no more available memory
     63  * @return     M4ERR_CONTEXT_FAILED: the context creation failed
     64  ************************************************************************
     65 */
     66 M4OSA_ERR M4OSA_semaphoreOpen(M4OSA_Context* context,
     67                               M4OSA_UInt32 initial_count)
     68 {
     69    M4OSA_SemaphoreContext* semaphoreContext = M4OSA_NULL;
     70 
     71    M4OSA_TRACE1_2("M4OSA_semaphoreOpen\t\tM4OSA_Context* 0x%x\tM4OSA_UInt32 "
     72                   "%d", context, initial_count);
     73 
     74    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
     75                    M4ERR_PARAMETER, "M4OSA_semaphoreOpen");
     76 
     77    *context = M4OSA_NULL;
     78 
     79    semaphoreContext = (M4OSA_SemaphoreContext*) M4OSA_32bitAlignedMalloc(
     80                       sizeof(M4OSA_SemaphoreContext), M4OSA_SEMAPHORE,
     81                       (M4OSA_Char*)"M4OSA_semaphoreOpen: semaphore context");
     82 
     83    if(semaphoreContext == M4OSA_NULL)
     84    {
     85       M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_semaphoreOpen");
     86 
     87       return M4ERR_ALLOC;
     88    }
     89 
     90    if (0 != sem_init(&semaphoreContext->semaphore, 0, initial_count))
     91    {
     92       free(semaphoreContext);
     93 
     94       M4OSA_DEBUG(M4ERR_CONTEXT_FAILED,
     95          "M4OSA_semaphoreOpen: OS semaphore creation failed");
     96 
     97       return M4ERR_CONTEXT_FAILED;
     98    }
     99 
    100    semaphoreContext->coreID = M4OSA_SEMAPHORE ;
    101    *context = (M4OSA_Context)semaphoreContext;
    102 
    103    return M4NO_ERROR;
    104 }
    105 
    106 
    107 
    108 
    109 /**
    110  ************************************************************************
    111  * @brief      This method decrements (one by one) the semaphore counter. The
    112  *             semaphore is identified by its context This call is not blocking
    113  *             if the semaphore counter is positive or zero (after
    114  *             decrementation). This call is blocking if the semaphore counter
    115  *             is less than zero (after decrementation), until the semaphore is
    116  *             upper than zero (see M4OSA_semaphorePost) or time_out is
    117  *             reached.
    118  * @note       If "timeout" value is M4OSA_WAIT_FOREVER, the calling thread
    119  *             will block indefinitely until the semaphore  is unlocked.
    120  * @param      context:(IN/OUT) Context of the semaphore
    121  * @param      timeout:(IN) Time out in milliseconds
    122  * @return     M4NO_ERROR: there is no error
    123  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    124  * @return     M4WAR_TIME_OUT: time out is elapsed before semaphore has been
    125  *             available.
    126  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    127  ************************************************************************
    128 */
    129 M4OSA_ERR M4OSA_semaphoreWait(M4OSA_Context context, M4OSA_Int32 timeout)
    130 {
    131    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
    132    struct timespec         ts;
    133    struct timespec         left;
    134    int                     result;
    135 
    136    M4OSA_TRACE1_2("M4OSA_semaphoreWait\t\tM4OSA_Context 0x%x\tM4OSA_UInt32 %d",
    137                   context, timeout);
    138 
    139    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    140                    M4ERR_PARAMETER, "M4OSA_semaphoreWait");
    141 
    142    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
    143                    M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait");
    144 
    145    if ( (M4OSA_Int32)M4OSA_WAIT_FOREVER == timeout)
    146    {
    147        if ( 0 != sem_wait(&semaphoreContext->semaphore) )
    148        {
    149            M4OSA_DEBUG(M4ERR_BAD_CONTEXT,
    150                   "M4OSA_semaphoreWait: OS semaphore wait failed");
    151 
    152            return M4ERR_BAD_CONTEXT ;
    153        }
    154    }
    155    else
    156    {
    157        result = sem_trywait(&semaphoreContext->semaphore);
    158        while ( ((EBUSY == result) || (EAGAIN == result)) && ( 0 < timeout ) )
    159        {
    160            ts.tv_sec  = 0;
    161            if (1 <= timeout)
    162            {
    163                ts.tv_nsec = 1000000;
    164                timeout -= 1;
    165            }
    166            else
    167            {
    168                ts.tv_nsec = timeout * 1000000;
    169                timeout = 0;
    170            }
    171            nanosleep(&ts, &left);
    172            result = sem_trywait(&semaphoreContext->semaphore);
    173        }
    174        if (0 != result)
    175        {
    176            if ((EBUSY == result) || (EAGAIN == result))
    177            {
    178                return M4WAR_TIME_OUT;
    179            }
    180            else
    181            {
    182                M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait: OS semaphore wait failed");
    183                return M4ERR_BAD_CONTEXT;
    184            }
    185        }
    186    }
    187 
    188    return M4NO_ERROR;
    189 }
    190 
    191 
    192 
    193 
    194 
    195 /**
    196  ************************************************************************
    197  * @brief      This method increments the semaphore counter. The semaphore is
    198  *             identified by its context
    199  * @note       If the semaphore counter is upper than zero (after addition),
    200  *             the M4OSA_semaphoreWait call of the thread with the highest
    201  *             priority is unblocked and made ready to run.
    202  * @note       No hypotheses can be made on which thread will be unblocked
    203  *             between threads with the same priority.
    204  * @param      context:(IN/OUT) Context of the semaphore
    205  * @return     M4NO_ERROR: there is no error
    206  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    207  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    208 ************************************************************************
    209 */
    210 M4OSA_ERR M4OSA_semaphorePost(M4OSA_Context context)
    211 {
    212    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
    213 
    214    M4OSA_TRACE1_1("M4OSA_semaphorePost\t\tM4OSA_Context 0x%x", context);
    215 
    216    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    217                    M4ERR_PARAMETER, "M4OSA_semaphorePost");
    218 
    219    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
    220                    M4ERR_BAD_CONTEXT, "M4OSA_semaphorePost");
    221 
    222    sem_post(&semaphoreContext->semaphore);
    223 
    224    return M4NO_ERROR;
    225 }
    226 
    227 
    228 
    229 
    230 
    231 /**
    232  ************************************************************************
    233  * @brief      This method deletes a semaphore (identify by its context).
    234  *             After this call the semaphore and its context is no more
    235  *             useable. This function frees all the memory related to this
    236  *             semaphore.
    237  * @note       It is an application issue to warrant no more threads are locked
    238  *             on the deleted semaphore.
    239  * @param      context:(IN/OUT) Context of the semaphore
    240  * @return     M4NO_ERROR: there is no error
    241  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    242  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one.
    243 ************************************************************************
    244 */
    245 M4OSA_ERR M4OSA_semaphoreClose(M4OSA_Context context)
    246 {
    247    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
    248 
    249    M4OSA_TRACE1_1("M4OSA_semaphoreClose\t\tM4OSA_Context 0x%x", context);
    250 
    251    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    252                    M4ERR_PARAMETER, "M4OSA_semaphoreClose");
    253 
    254    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
    255                    M4ERR_BAD_CONTEXT, "M4OSA_semaphoreClose");
    256 
    257    sem_destroy(&semaphoreContext->semaphore);
    258 
    259    free(semaphoreContext);
    260 
    261    return M4NO_ERROR;
    262 }
    263 
    264