/************************************************************************
 * AUTHOR: NiuJiuRu
 * FILENAME: swmutex.c
 * DESCRIPTION: 互斥量, 也称独占锁
 * NOTE: 主要用于多线程同步访问全局共享资源
 * HISTORY:
 * 1, [2010-12-17] created by NiuJiuRu
 * 2, [2026-03-17] 优化修改"sw_mutex_lock()"函数, 避免依赖系统时间, 导致的超
 *                 时误差或跳变问题
 ***********************************************************************/
#include "swapi.h"
#include "swmem.h"
#include "swmutex.h"

/* 创建互斥量 */
void *sw_mutex_create()
{
	pthread_mutex_t *mt = NULL;
	pthread_mutexattr_t attr;
	
	mt = (pthread_mutex_t *)sw_heap_malloc(sizeof(pthread_mutex_t));
	if(mt)
	{
		if(pthread_mutexattr_init(&attr) != 0) { sw_heap_free(mt); return NULL; }
		if(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0 || pthread_mutex_init(mt, &attr) != 0) { sw_heap_free(mt); mt = NULL; }
		pthread_mutexattr_destroy(&attr);
	}
	
	return mt;	
}

/* 销毁互斥量 */
void sw_mutex_destroy(void *hMutex)
{
	pthread_mutex_t *mt = (pthread_mutex_t *)hMutex;
	pthread_mutex_destroy(mt);
	sw_heap_free(mt);
}

/* 互斥量上锁(超时设置的时间单位为: 毫秒, 并且当timeout = -1时表示无限等待) */
int sw_mutex_lock(void *hMutex, int timeout)
{
	pthread_mutex_t *mt = (pthread_mutex_t *)hMutex;
	struct timespec start, now; int ret;
	
	if(timeout < 0)
	{
		return pthread_mutex_lock(mt);
	}
	
	clock_gettime(CLOCK_MONOTONIC, &start);
	while((ret = pthread_mutex_trylock(mt)) == EBUSY)
	{
		clock_gettime(CLOCK_MONOTONIC, &now);
		long long elapsed = (now.tv_sec*1000LL + now.tv_nsec/1000000) - (start.tv_sec*1000LL + start.tv_nsec/1000000);
		if(elapsed >= timeout) { errno = ETIMEDOUT; return -1; }
		else delay_ms(1); // 释放CPU占用, 避免过载
	}
	
	return ret == 0 ? 0 : -1;
}

/* 互斥量解锁 */
void sw_mutex_unlock(void *hMutex)
{
	pthread_mutex_t *mt = (pthread_mutex_t *)hMutex;
	pthread_mutex_unlock(mt);
}
