/************************************************************************
 * AUTHOR: NiuJiuRu
 * FILENAME: swsignal.c
 * DESCRIPTION: 信号量
 * NOTE: 主要用于状态通知
 * HISTORY:
 * 1, [2010-12-17] created by NiuJiuRu
 ***********************************************************************/
#include "swapi.h"
#include "swmem.h"
#include "swsignal.h"

/* 创建信号量 */
void *sw_signal_create()
{
	sem_t *sem = NULL;
	
	sem = (sem_t *)sw_heap_malloc(sizeof(sem_t));
	if(sem)
	{
		memset(sem, 0, sizeof(sem_t));
		sem_init(sem, 0, 0);
	}
	
	return sem;
}

/* 销毁信号量 */
void sw_signal_destroy(void *hSignal)
{
	sem_t *sem = (sem_t *)hSignal;
	sem_destroy(sem);
	sw_heap_free(sem);
}

/* 等待信号量, timeout(ms) = -1时表示无限等待 */
int sw_signal_wait(void *hSignal, int timeout)
{
	sem_t *sem = (sem_t *)hSignal;
	struct timeval tv = { 0 };
	struct timespec ts = { 0 };
	int ret;
	
	if(timeout < 0)
	{
wait_p1:
		ret = sem_wait(sem);
		if(ret < 0 && errno == EINTR) goto wait_p1;
		else return ret;
	}
	else
	{
		gettimeofday(&tv, NULL);
		ts.tv_sec = tv.tv_sec + timeout/1000;
		ts.tv_nsec = tv.tv_usec*1000 + (timeout%1000)*1000*1000;
		ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
		ts.tv_nsec %= (1000*1000*1000);
wait_p2:
		ret = sem_timedwait(sem, &ts);
		if(ret < 0 && errno == EINTR) goto wait_p2;
		else return ret;
	}
}

/* 点亮信号量 */
void sw_signal_give(void *hSignal)
{
	sem_t *sem = (sem_t *)hSignal;
	sem_post(sem);
}
