| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * 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. |
| * ------------------------------------------------------------------- |
| */ |
| // -*- c++ -*- |
| // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |
| |
| |
| // OSCL_S E M A P H O R E (S E M A P H O R E I M P L E M E N T A T I O N) |
| |
| |
| // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |
| |
| /*! \file oscl_semaphore.cpp .This file provides SEMAPHORE implementation that can be ported |
| to three OS LINUX, SYMBIAN, WIN32 |
| */ |
| |
| // Implementation file for OSCL Semaphores |
| #include "oscl_semaphore.h" |
| #include "oscl_assert.h" |
| |
| |
| |
| // Class contructor |
| OSCL_EXPORT_REF OsclSemaphore::OsclSemaphore() |
| { |
| bCreated = false; |
| } |
| |
| OSCL_EXPORT_REF OsclSemaphore::~OsclSemaphore() |
| { |
| //make sure it was closed |
| OSCL_ASSERT(!bCreated); |
| } |
| |
| |
| /** |
| * Creates the Semaphore |
| * |
| * @param Intialcount & Maximum count |
| * |
| * @return Returns the Error whether it is success or failure. |
| * Incase of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Create(uint32 InitialCount) |
| { |
| if (bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| |
| iCount = InitialCount; |
| if (pthread_cond_init(&ObjCondition, NULL) == 0 |
| && pthread_mutex_init(&ObjMutex, NULL) == 0) |
| { |
| bCreated = true; |
| return OsclProcStatus::SUCCESS_ERROR; |
| } |
| return OsclProcStatus::OTHER_ERROR; |
| |
| } |
| |
| |
| /** |
| * Closes the Semaphore |
| * |
| * @param It wont take any parameters |
| * |
| * @return Returns the Error whether it is success or failure. |
| * Incase of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Close(void) |
| { |
| if (!bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| bCreated = false; |
| return OsclProcStatus::SUCCESS_ERROR; |
| |
| } |
| |
| |
| |
| /** |
| * Waits for access to the Semaphore |
| * |
| * @param It wont take any parameters |
| * |
| * @return Returns the Error whether it is success or failure |
| * Incase of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Wait() |
| { |
| if (!bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| |
| int res = pthread_mutex_lock(&ObjMutex); |
| if (res != 0) |
| return OsclProcStatus::OTHER_ERROR; |
| while (iCount == 0 && res == 0) |
| { // wait till the semaphore is signaled |
| // or an error has occurred |
| res = pthread_cond_wait(&ObjCondition, &ObjMutex); |
| } |
| if (res == 0) |
| { // signaled |
| iCount--; |
| } |
| pthread_mutex_unlock(&ObjMutex); |
| if (res != 0) |
| { // error occurred |
| // invalid condition or mutex |
| return OsclProcStatus::OTHER_ERROR; |
| } |
| return OsclProcStatus::SUCCESS_ERROR; |
| |
| } |
| |
| #include "osclconfig_time.h" |
| static void getAbsTime(struct timespec &abs, uint32 timeout_msec) |
| { |
| //convert timeout msec to sec + usec. |
| uint32 timeout_sec = timeout_msec / 1000; |
| uint32 timeout_usec = (timeout_msec % 1000) * 1000; |
| |
| //compute target time = time now plus timeout. |
| |
| struct timeval timenow; |
| gettimeofday(&timenow, NULL); |
| |
| uint32 targ_sec = timenow.tv_sec + timeout_sec; |
| uint32 targ_usec = timenow.tv_usec + timeout_usec; |
| while (targ_usec >= 1000000) |
| { |
| targ_sec++; |
| targ_usec -= 1000000; |
| } |
| |
| //convert target time to timespec. |
| abs.tv_sec = targ_sec; |
| abs.tv_nsec = targ_usec * 1000; |
| } |
| |
| /** |
| * Makes the thread to wait on the Semaphore, with a timeout. |
| * |
| * @param timeout in milliseconds. |
| * |
| * @return Returns WAIT_TIMEOUT_ERROR if the timeout expires, |
| * SUCCESS_ERROR if the semaphore is obtained, or in |
| * case of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Wait(uint32 timeout_msec) |
| { |
| if (!bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| |
| int res = pthread_mutex_lock(&ObjMutex); |
| if (res != 0) |
| return OsclProcStatus::OTHER_ERROR; |
| if (iCount > 0) |
| { |
| iCount--; |
| pthread_mutex_unlock(&ObjMutex); |
| return OsclProcStatus::SUCCESS_ERROR; |
| } |
| |
| struct timespec abs; |
| getAbsTime(abs, timeout_msec); |
| |
| while ((iCount == 0) && (res == 0)) |
| { // wait till semaphore is signaled |
| // or time runs out |
| res = pthread_cond_timedwait(&ObjCondition, &ObjMutex, &abs); |
| } |
| if (res == 0) |
| { // signalied |
| iCount--; |
| } |
| pthread_mutex_unlock(&ObjMutex); |
| if (res == ETIMEDOUT) |
| { // timeour occurred |
| return OsclProcStatus::WAIT_TIMEOUT_ERROR; |
| } |
| else if (res != 0) |
| { // error occurred |
| return OsclProcStatus::OTHER_ERROR; |
| } |
| return OsclProcStatus::SUCCESS_ERROR; |
| |
| } |
| |
| /** |
| * Try to acquire semaphore, if the semaphore is already acquired by another thread, |
| * calling thread immediately returns with out blocking |
| * |
| * @param It wont take any parameters |
| * |
| * @return Returns the Error whether it is success or failure |
| * Incase of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::TryWait() |
| { |
| if (!bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| |
| int res = pthread_mutex_lock(&ObjMutex); |
| if (res != 0) |
| return OsclProcStatus::OTHER_ERROR; |
| if (iCount > 0) |
| {//take it |
| iCount--; |
| pthread_mutex_unlock(&ObjMutex); |
| return OsclProcStatus::SUCCESS_ERROR; |
| } |
| else |
| {//can't take it now so don't block. |
| pthread_mutex_unlock(&ObjMutex); |
| return OsclProcStatus::SEM_NOT_SIGNALED_ERROR; |
| } |
| |
| } |
| |
| |
| /** |
| * Signals that the thread is finished with the Semaphore |
| * |
| * @param It wont take any parameters |
| * |
| * @return Returns the Error whether it is success or failure |
| * Incase of failure it will return what is the specific error |
| */ |
| OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Signal() |
| { |
| if (!bCreated) |
| return OsclProcStatus::INVALID_OPERATION_ERROR; |
| |
| |
| int res = pthread_mutex_lock(&ObjMutex); |
| if (res != 0) |
| return OsclProcStatus::OTHER_ERROR; |
| iCount++; |
| res = pthread_cond_signal(&ObjCondition); |
| pthread_mutex_unlock(&ObjMutex); |
| if (res != 0) |
| return OsclProcStatus::OTHER_ERROR; |
| return OsclProcStatus::SUCCESS_ERROR; |
| |
| |
| } |
| |