172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/*
272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * Copyright (C) Texas Instruments - http://www.ti.com/
372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng *
472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * Licensed under the Apache License, Version 2.0 (the "License");
572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * you may not use this file except in compliance with the License.
672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * You may obtain a copy of the License at
772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng *
872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng *      http://www.apache.org/licenses/LICENSE-2.0
972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng *
1072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * Unless required by applicable law or agreed to in writing, software
1172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * distributed under the License is distributed on an "AS IS" BASIS,
1272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * See the License for the specific language governing permissions and
1472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng * limitations under the License.
1572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
1672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
1772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
1872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
1972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng#include "Semaphore.h"
2072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng#include "ErrorUtils.h"
2172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng#include <utils/Log.h>
2272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng#include <time.h>
2372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
24f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsnamespace Ti {
25f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsnamespace Utils {
2672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
2772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
2872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Constructor for the semaphore class
2972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
3072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param none
3172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return none
3272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
3372dbc3152137ec7b77deddede4229f73149e92c8Akwasi BoatengSemaphore::Semaphore()
3472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
3572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Initialize the semaphore to NULL
3672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    mSemaphore = NULL;
3772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
3872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
3972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
4072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Destructor of the semaphore class
4172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
4272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param none
4372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return none
4472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
4572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
4672dbc3152137ec7b77deddede4229f73149e92c8Akwasi BoatengSemaphore::~Semaphore()
4772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
4872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    Release();
4972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
5072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
5172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
5272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief: Releases semaphore
5372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
5472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param count >=0
5572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return NO_ERROR On Success
5672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return One of the android error codes based on semaphore de-initialization
5772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
5872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
5972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengstatus_t Semaphore::Release()
6072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
6172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    int status = 0;
6272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
6372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Destroy only if the semaphore has been created
6472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(mSemaphore)
6572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
6672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        status = sem_destroy(mSemaphore);
6772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
6872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        free(mSemaphore);
6972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
7072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        mSemaphore = NULL;
7172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
7272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
7372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Initialize the semaphore and return the status
7472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return ErrorUtils::posixToAndroidError(status);
7572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
7672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
7772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
7872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
7972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Create the semaphore with initial count value
8072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
8172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param count >=0
8272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return NO_ERROR On Success
8372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return NO_MEMORY If unable to allocate memory for the semaphore
8472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return BAD_VALUE If an invalid count value is passed (<0)
8572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return One of the android error codes based on semaphore initialization
8672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
8772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
8872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengstatus_t Semaphore::Create(int count)
8972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
9072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    status_t ret = NO_ERROR;
9172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
9272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///count cannot be less than zero
9372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(count<0)
9472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
9572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return BAD_VALUE;
9672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
9772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
9872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ret = Release();
9972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if ( NO_ERROR != ret )
10072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
10172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return ret;
10272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
10372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
10472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///allocate memory for the semaphore
10572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ;
10672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
10772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///if memory is unavailable, return error
10872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(!mSemaphore)
10972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
11072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return NO_MEMORY;
11172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
11272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
11372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Initialize the semaphore and return the status
11472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count));
11572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
11672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
11772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
11872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
11972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Wait operation
12072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
12172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param none
12272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return BAD_VALUE if the semaphore is not initialized
12372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return NO_ERROR On success
12472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return One of the android error codes based on semaphore wait operation
12572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
12672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengstatus_t Semaphore::Wait()
12772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
12872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///semaphore should have been created first
12972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(!mSemaphore)
13072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
13172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return BAD_VALUE;
13272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
13372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
13472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Wait and return the status after signalling
13572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore));
13672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
13772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
13872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
13972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
14072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
14172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
14272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Signal operation
14372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
14472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param none
14572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return BAD_VALUE if the semaphore is not initialized
14672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return NO_ERROR On success
14772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return One of the android error codes based on semaphore signal operation
14872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   */
14972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
15072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengstatus_t Semaphore::Signal()
15172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
15272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///semaphore should have been created first
15372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(!mSemaphore)
15472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
15572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return BAD_VALUE;
15672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
15772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
15872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///Post to the semaphore
15972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return ErrorUtils::posixToAndroidError(sem_post(mSemaphore));
16072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
16172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
16272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
16372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
16472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Current semaphore count
16572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
16672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @param none
16772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @return Current count value of the semaphore
16872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng */
16972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengint Semaphore::Count()
17072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
17172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    int val;
17272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
17372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///semaphore should have been created first
17472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if(!mSemaphore)
17572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
17672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        return BAD_VALUE;
17772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
17872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
17972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///get the value of the semaphore
18072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    sem_getvalue(mSemaphore, &val);
18172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
18272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return val;
18372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
18472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
18572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng/**
18672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   @brief Wait operation with a timeout
18772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
18872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @param timeoutMicroSecs The timeout period in micro seconds
18972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return BAD_VALUE if the semaphore is not initialized
19072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return NO_ERROR On success
19172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng     @return One of the android error codes based on semaphore wait operation
19272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng   */
19372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
19472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boatengstatus_t Semaphore::WaitTimeout(int timeoutMicroSecs)
19572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng{
19672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    status_t ret = NO_ERROR;
19772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
19872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    struct timespec timeSpec;
19972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    struct timeval currentTime;
20072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
20172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    ///semaphore should have been created first
20272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if( NULL == mSemaphore)
20372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
20472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        ret = BAD_VALUE;
20572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
20672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
20772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if ( NO_ERROR == ret )
20872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        {
20972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
21072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        ///setup the timeout values - timeout is specified in seconds and nanoseconds
21172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        gettimeofday(&currentTime, NULL);
21272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        timeSpec.tv_sec = currentTime.tv_sec;
21372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        timeSpec.tv_nsec = currentTime.tv_usec * 1000;
21472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 );
21572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000;
21672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
21772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        ///Wait for the timeout or signal and return the result based on whichever event occurred first
21872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        ret = sem_timedwait(mSemaphore, &timeSpec);
21972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        }
22072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
22172dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    if ( NO_ERROR != ret )
22272dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng      {
22372dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        Signal();
22472dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng        Create(0);
22572dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng      }
22672dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
22772dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng    return ret;
22872dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng}
22972dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
23072dbc3152137ec7b77deddede4229f73149e92c8Akwasi Boateng
231f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} // namespace Utils
232f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} // namespace Ti
233