/* * Copyright (C) Texas Instruments - http://www.ti.com/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Semaphore.h" #include "ErrorUtils.h" #include <utils/Log.h> #include <time.h> namespace android { /** @brief Constructor for the semaphore class @param none @return none */ Semaphore::Semaphore() { ///Initialize the semaphore to NULL mSemaphore = NULL; } /** @brief Destructor of the semaphore class @param none @return none */ Semaphore::~Semaphore() { Release(); } /** @brief: Releases semaphore @param count >=0 @return NO_ERROR On Success @return One of the android error codes based on semaphore de-initialization */ status_t Semaphore::Release() { int status = 0; ///Destroy only if the semaphore has been created if(mSemaphore) { status = sem_destroy(mSemaphore); free(mSemaphore); mSemaphore = NULL; } ///Initialize the semaphore and return the status return ErrorUtils::posixToAndroidError(status); } /** @brief Create the semaphore with initial count value @param count >=0 @return NO_ERROR On Success @return NO_MEMORY If unable to allocate memory for the semaphore @return BAD_VALUE If an invalid count value is passed (<0) @return One of the android error codes based on semaphore initialization */ status_t Semaphore::Create(int count) { status_t ret = NO_ERROR; ///count cannot be less than zero if(count<0) { return BAD_VALUE; } ret = Release(); if ( NO_ERROR != ret ) { return ret; } ///allocate memory for the semaphore mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ; ///if memory is unavailable, return error if(!mSemaphore) { return NO_MEMORY; } ///Initialize the semaphore and return the status return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count)); } /** @brief Wait operation @param none @return BAD_VALUE if the semaphore is not initialized @return NO_ERROR On success @return One of the android error codes based on semaphore wait operation */ status_t Semaphore::Wait() { ///semaphore should have been created first if(!mSemaphore) { return BAD_VALUE; } ///Wait and return the status after signalling return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore)); } /** @brief Signal operation @param none @return BAD_VALUE if the semaphore is not initialized @return NO_ERROR On success @return One of the android error codes based on semaphore signal operation */ status_t Semaphore::Signal() { ///semaphore should have been created first if(!mSemaphore) { return BAD_VALUE; } ///Post to the semaphore return ErrorUtils::posixToAndroidError(sem_post(mSemaphore)); } /** @brief Current semaphore count @param none @return Current count value of the semaphore */ int Semaphore::Count() { int val; ///semaphore should have been created first if(!mSemaphore) { return BAD_VALUE; } ///get the value of the semaphore sem_getvalue(mSemaphore, &val); return val; } /** @brief Wait operation with a timeout @param timeoutMicroSecs The timeout period in micro seconds @return BAD_VALUE if the semaphore is not initialized @return NO_ERROR On success @return One of the android error codes based on semaphore wait operation */ status_t Semaphore::WaitTimeout(int timeoutMicroSecs) { status_t ret = NO_ERROR; struct timespec timeSpec; struct timeval currentTime; ///semaphore should have been created first if( NULL == mSemaphore) { ret = BAD_VALUE; } if ( NO_ERROR == ret ) { ///setup the timeout values - timeout is specified in seconds and nanoseconds gettimeofday(¤tTime, NULL); timeSpec.tv_sec = currentTime.tv_sec; timeSpec.tv_nsec = currentTime.tv_usec * 1000; timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 ); timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000; ///Wait for the timeout or signal and return the result based on whichever event occurred first ret = sem_timedwait(mSemaphore, &timeSpec); } if ( NO_ERROR != ret ) { Signal(); Create(0); } return ret; } };