sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/utils/tsemaphore.c

268 lines
6.2 KiB
C
Executable File

//#include <CDX_LogNDebug.h>
#define LOG_TAG "SEM"
#include <utils/plat_log.h>
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#include "tsemaphore.h"
/** Initializes the semaphore at a given value
*
* @param tsem the semaphore to initialize
* @param val the initial value of the semaphore
*
*/
int cdx_sem_init(cdx_sem_t* tsem, unsigned int val)
{
int i;
pthread_condattr_t condAttr;
pthread_condattr_init(&condAttr);
pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
i = pthread_cond_init(&tsem->condition, &condAttr);
if (i!=0)
return -1;
i = pthread_mutex_init(&tsem->mutex, NULL);
if (i!=0)
return -1;
tsem->semval = val;
return 0;
}
/** Destroy the semaphore
*
* @param tsem the semaphore to destroy
*/
void cdx_sem_deinit(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
pthread_cond_destroy(&tsem->condition);
pthread_mutex_unlock(&tsem->mutex);
pthread_mutex_destroy(&tsem->mutex);
}
/** Decreases the value of the semaphore. Blocks if the semaphore
* value is zero.
*
* @param tsem the semaphore to decrease
*/
void cdx_sem_down(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
alogv("semdown:%p val:%d",tsem,tsem->semval);
while (tsem->semval == 0)
{
alogv("semdown wait:%p val:%d",tsem,tsem->semval);
pthread_cond_wait(&tsem->condition, &tsem->mutex);
alogv("semdown wait end:%p val:%d",tsem,tsem->semval);
}
tsem->semval--;
pthread_mutex_unlock(&tsem->mutex);
}
int cdx_sem_down_timedwait(cdx_sem_t* tsem, unsigned int timeout)
{
int ret = 0;
pthread_mutex_lock(&tsem->mutex);
alogv("semdown:%p val:%d",tsem,tsem->semval);
while(tsem->semval == 0)
{
alogv("semdown wait:%p val:%d",tsem, tsem->semval);
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
int relative_sec = timeout/1000;
int relative_nsec = (timeout%1000)*1000000;
ts.tv_sec += relative_sec;
ts.tv_nsec += relative_nsec;
ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
ts.tv_nsec = ts.tv_nsec%(1000*1000*1000);
ret = pthread_cond_timedwait(&tsem->condition, &tsem->mutex, &ts);
if(ETIMEDOUT == ret)
{
//alogd("pthread cond timeout np timeout[%d]", ret);
break;
}
else if(0 == ret)
{
}
else
{
aloge("fatal error! pthread cond timedwait[%d]", ret);
}
alogv("semdown wait end:%p val:%d",tsem,tsem->semval);
}
if(tsem->semval > 0)
{
if(ret != 0)
{
if(ETIMEDOUT == ret)
{
aloge("fatal error! semval[%d]>0 when ETIMEDOUT[%d], check code!", tsem->semval, ret);
}
else
{
aloge("fatal error! semval[%d]>0 when ret[%d], check code!", tsem->semval, ret);
}
ret = 0;
}
tsem->semval--;
}
pthread_mutex_unlock(&tsem->mutex);
return ret;
}
/** Increases the value of the semaphore
*
* @param tsem the semaphore to increase
*/
void cdx_sem_up(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
tsem->semval++;
alogv("semup signal:%p val:%d",tsem,tsem->semval);
pthread_cond_signal(&tsem->condition);
pthread_mutex_unlock(&tsem->mutex);
}
void cdx_sem_wait_unique(cdx_sem_t* tsem)
{
int ret = 0;
pthread_mutex_lock(&tsem->mutex);
while(0 == tsem->semval)
{
ret = pthread_cond_wait(&tsem->condition, &tsem->mutex);
if(ret != 0)
{
aloge("fatal error! pthread cond wait fail[%d]", ret);
}
}
pthread_mutex_unlock(&tsem->mutex);
}
/*
* @timeout unit:ms
*/
int cdx_sem_timedwait_unique(cdx_sem_t* tsem, unsigned int timeout)
{
int ret = 0;
pthread_mutex_lock(&tsem->mutex);
while(0 == tsem->semval)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
int relative_sec = timeout/1000;
int relative_nsec = (timeout%1000)*1000000;
ts.tv_sec += relative_sec;
ts.tv_nsec += relative_nsec;
ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
ts.tv_nsec = ts.tv_nsec%(1000*1000*1000);
ret = pthread_cond_timedwait(&tsem->condition, &tsem->mutex, &ts);
if(ETIMEDOUT == ret)
{
//alogd("Be careful! pthread cond timedwait timeout[%d]", ret);
break;
}
else if(0 == ret)
{
}
else
{
aloge("fatal error! pthread cond timedwait[%d]", ret);
}
}
pthread_mutex_unlock(&tsem->mutex);
return ret;
}
void cdx_sem_up_unique(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
if(0 == tsem->semval)
{
tsem->semval++;
pthread_cond_signal(&tsem->condition);
}
pthread_mutex_unlock(&tsem->mutex);
}
/** Reset the value of the semaphore
*
* @param tsem the semaphore to reset
*/
void cdx_sem_reset(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
tsem->semval=0;
pthread_mutex_unlock(&tsem->mutex);
}
/** Wait on the condition.
*
* @param tsem the semaphore to wait
*/
void cdx_sem_wait(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
pthread_cond_wait(&tsem->condition, &tsem->mutex);
pthread_mutex_unlock(&tsem->mutex);
}
/** Wait on the condition.
*
* @param tsem the semaphore to wait with time
*/
int cdx_sem_timewait(cdx_sem_t* tsem, unsigned int msec)
{
int ret;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
int relative_sec = msec/1000;
int relative_nsec = (msec%1000)*1000000;
ts.tv_sec += relative_sec;
ts.tv_nsec += relative_nsec;
ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
ts.tv_nsec = ts.tv_nsec%(1000*1000*1000);
pthread_mutex_lock(&tsem->mutex);
ret = pthread_cond_timedwait(&tsem->condition, &tsem->mutex, &ts);
pthread_mutex_unlock(&tsem->mutex);
return ret;
}
/** Signal the condition,if waiting
*
* @param tsem the semaphore to signal
*/
void cdx_sem_signal(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
pthread_cond_signal(&tsem->condition);
pthread_mutex_unlock(&tsem->mutex);
}
unsigned int cdx_sem_get_val(cdx_sem_t* tsem)
{
pthread_mutex_lock(&tsem->mutex);
unsigned int val = tsem->semval;
pthread_mutex_unlock(&tsem->mutex);
return val;
}