Home | History | Annotate | Download | only in libtiutils
      1 /*
      2  * Copyright (C) Texas Instruments - http://www.ti.com/
      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 
     19 #include "Semaphore.h"
     20 #include "ErrorUtils.h"
     21 #include <utils/Log.h>
     22 #include <time.h>
     23 
     24 namespace Ti {
     25 namespace Utils {
     26 
     27 /**
     28    @brief Constructor for the semaphore class
     29 
     30    @param none
     31    @return none
     32  */
     33 Semaphore::Semaphore()
     34 {
     35     ///Initialize the semaphore to NULL
     36     mSemaphore = NULL;
     37 }
     38 
     39 /**
     40    @brief Destructor of the semaphore class
     41 
     42    @param none
     43    @return none
     44 
     45  */
     46 Semaphore::~Semaphore()
     47 {
     48     Release();
     49 }
     50 
     51 /**
     52    @brief: Releases semaphore
     53 
     54    @param count >=0
     55    @return NO_ERROR On Success
     56    @return One of the android error codes based on semaphore de-initialization
     57  */
     58 
     59 status_t Semaphore::Release()
     60 {
     61     int status = 0;
     62 
     63     ///Destroy only if the semaphore has been created
     64     if(mSemaphore)
     65         {
     66         status = sem_destroy(mSemaphore);
     67 
     68         free(mSemaphore);
     69 
     70         mSemaphore = NULL;
     71         }
     72 
     73     ///Initialize the semaphore and return the status
     74     return ErrorUtils::posixToAndroidError(status);
     75 
     76 }
     77 
     78 /**
     79    @brief Create the semaphore with initial count value
     80 
     81    @param count >=0
     82    @return NO_ERROR On Success
     83    @return NO_MEMORY If unable to allocate memory for the semaphore
     84    @return BAD_VALUE If an invalid count value is passed (<0)
     85    @return One of the android error codes based on semaphore initialization
     86  */
     87 
     88 status_t Semaphore::Create(int count)
     89 {
     90     status_t ret = NO_ERROR;
     91 
     92     ///count cannot be less than zero
     93     if(count<0)
     94         {
     95         return BAD_VALUE;
     96         }
     97 
     98     ret = Release();
     99     if ( NO_ERROR != ret )
    100         {
    101         return ret;
    102         }
    103 
    104     ///allocate memory for the semaphore
    105     mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ;
    106 
    107     ///if memory is unavailable, return error
    108     if(!mSemaphore)
    109         {
    110         return NO_MEMORY;
    111         }
    112 
    113     ///Initialize the semaphore and return the status
    114     return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count));
    115 
    116 }
    117 
    118 /**
    119    @brief Wait operation
    120 
    121    @param none
    122    @return BAD_VALUE if the semaphore is not initialized
    123    @return NO_ERROR On success
    124    @return One of the android error codes based on semaphore wait operation
    125  */
    126 status_t Semaphore::Wait()
    127 {
    128     ///semaphore should have been created first
    129     if(!mSemaphore)
    130         {
    131         return BAD_VALUE;
    132         }
    133 
    134     ///Wait and return the status after signalling
    135     return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore));
    136 
    137 
    138 }
    139 
    140 
    141 /**
    142    @brief Signal operation
    143 
    144    @param none
    145      @return BAD_VALUE if the semaphore is not initialized
    146      @return NO_ERROR On success
    147      @return One of the android error codes based on semaphore signal operation
    148    */
    149 
    150 status_t Semaphore::Signal()
    151 {
    152     ///semaphore should have been created first
    153     if(!mSemaphore)
    154         {
    155         return BAD_VALUE;
    156         }
    157 
    158     ///Post to the semaphore
    159     return ErrorUtils::posixToAndroidError(sem_post(mSemaphore));
    160 
    161 }
    162 
    163 /**
    164    @brief Current semaphore count
    165 
    166    @param none
    167    @return Current count value of the semaphore
    168  */
    169 int Semaphore::Count()
    170 {
    171     int val;
    172 
    173     ///semaphore should have been created first
    174     if(!mSemaphore)
    175         {
    176         return BAD_VALUE;
    177         }
    178 
    179     ///get the value of the semaphore
    180     sem_getvalue(mSemaphore, &val);
    181 
    182     return val;
    183 }
    184 
    185 /**
    186    @brief Wait operation with a timeout
    187 
    188      @param timeoutMicroSecs The timeout period in micro seconds
    189      @return BAD_VALUE if the semaphore is not initialized
    190      @return NO_ERROR On success
    191      @return One of the android error codes based on semaphore wait operation
    192    */
    193 
    194 status_t Semaphore::WaitTimeout(int timeoutMicroSecs)
    195 {
    196     status_t ret = NO_ERROR;
    197 
    198     struct timespec timeSpec;
    199     struct timeval currentTime;
    200 
    201     ///semaphore should have been created first
    202     if( NULL == mSemaphore)
    203         {
    204         ret = BAD_VALUE;
    205         }
    206 
    207     if ( NO_ERROR == ret )
    208         {
    209 
    210         ///setup the timeout values - timeout is specified in seconds and nanoseconds
    211         gettimeofday(&currentTime, NULL);
    212         timeSpec.tv_sec = currentTime.tv_sec;
    213         timeSpec.tv_nsec = currentTime.tv_usec * 1000;
    214         timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 );
    215         timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000;
    216 
    217         ///Wait for the timeout or signal and return the result based on whichever event occurred first
    218         ret = sem_timedwait(mSemaphore, &timeSpec);
    219         }
    220 
    221     if ( NO_ERROR != ret )
    222       {
    223         Signal();
    224         Create(0);
    225       }
    226 
    227     return ret;
    228 }
    229 
    230 
    231 } // namespace Utils
    232 } // namespace Ti
    233