Bladeren bron

优化swapi底层c库, 使得信号量、互斥量、读写锁相关超时函数不再依赖系统时间

niujiuru 3 weken geleden
bovenliggende
commit
b3353fb883
4 gewijzigde bestanden met toevoegingen van 52 en 42 verwijderingen
  1. 28 22
      swapi/sw_rwlock.c
  2. 5 2
      swapi/swapi.h
  3. 14 11
      swapi/swmutex.c
  4. 5 7
      swapi/swsignal.c

+ 28 - 22
swapi/sw_rwlock.c

@@ -5,6 +5,8 @@
  * NOTE: 主要用于多线程同步访问全局共享资源
  * HISTORY:
  * 1, [2014-01-24] created by NiuJiuRu
+ * 2, [2026-03-17] 优化修改"sw_rwlock_rdlock()"和"sw_rwlock_wrlock()"函数,
+ *                 避免依赖系统时间, 导致的超时误差或跳变问题
  ***********************************************************************/
 #include "swapi.h"
 #include "swmem.h"
@@ -19,13 +21,11 @@ void *sw_rwlock_create()
     rwlock = (pthread_rwlock_t *)sw_heap_malloc(sizeof(pthread_rwlock_t));
     if(rwlock)
     {
-        memset(rwlock, 0, sizeof(pthread_rwlock_t));
-        pthread_rwlockattr_init(&attr);
+        if(pthread_rwlockattr_init(&attr) != 0) { sw_heap_free(rwlock); return NULL; }
         // note: "If the process-shared attribute is PTHREAD_PRO-CESS_PRIVATE, the read-write lock shall only be 
         // operated upon by threads created within the same process as the thread that initialized the read-write lock;
         // if threads of differing processes attempt to operate on such a read-write lock, the behavior is undefined."
-        if(pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE) == 0) pthread_rwlock_init(rwlock, &attr);
-        else{ sw_heap_free(rwlock); rwlock = NULL; }
+        if(pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE) != 0 || pthread_rwlock_init(rwlock, &attr) != 0) { sw_heap_free(rwlock); rwlock = NULL; }
         pthread_rwlockattr_destroy(&attr);
     }
     
@@ -44,40 +44,46 @@ void sw_rwlock_destroy(void *hRWLock)
 int sw_rwlock_rdlock(void *hRWLock, int timeout)
 {
     pthread_rwlock_t *rwlock = (pthread_rwlock_t *)hRWLock;
-    struct timespec ts = { 0 };
+    struct timespec start, now; int ret;
     
     if(timeout < 0)
     {
         return pthread_rwlock_rdlock(rwlock);
     }
-    else
-    {
-        ts.tv_sec = time(NULL) + timeout/1000;
-        ts.tv_nsec = (timeout%1000)*1000;
-        if(pthread_rwlock_timedrdlock(rwlock, &ts) != 0) return -1;
-    }
-    
-    return 0;
+	
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	while((ret = pthread_rwlock_tryrdlock(rwlock)) == 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;
 }
 
 /* 读写锁上锁-写(超时设置的时间单位为: 毫秒, 并且当timeout = -1时表示无限等待) */
 int sw_rwlock_wrlock(void *hRWLock, int timeout)
 {
     pthread_rwlock_t *rwlock = (pthread_rwlock_t *)hRWLock;
-    struct timespec ts = { 0 };
+    struct timespec start, now; int ret;
     
     if(timeout < 0)
     {
         return pthread_rwlock_wrlock(rwlock);
     }
-    else
-    {
-        ts.tv_sec = time(NULL) + timeout/1000;
-        ts.tv_nsec = (timeout%1000)*1000;
-        if(pthread_rwlock_timedwrlock(rwlock, &ts) != 0) return -1;
-    }
-    
-    return 0;
+	
+    clock_gettime(CLOCK_MONOTONIC, &start);
+	while((ret = pthread_rwlock_trywrlock(rwlock)) == 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;
 }
 
 /* 读写锁解锁 */

+ 5 - 2
swapi/swapi.h

@@ -226,10 +226,13 @@
 
 //////////////////////////////////////////////////////////////////////////
 // 7, Define common data types and macro
-// 等待线程状态切换完成的延时时间, 单位: 毫秒
+#include "swthrd.h"
+#define delay_ms(ms) sw_thrd_delay(ms)
+
+// 等待线程状态切换完成的延时时间, 单位: ms
 #define THRDWAIT_DELAY 10
 
-// 等待线程安全退出的超时, 单位: 毫秒
+// 用户等待线程安全退出的超时时间, 单位: ms
 #define WAITTHRD_SAFEEXIT_TIMEOUT 3000
 
 // IPv4字符串最大长度(包含'\0'结尾符, 例如: xxx.xxx.xxx.xxx)

+ 14 - 11
swapi/swmutex.c

@@ -5,6 +5,8 @@
  * NOTE: 主要用于多线程同步访问全局共享资源
  * HISTORY:
  * 1, [2010-12-17] created by NiuJiuRu
+ * 2, [2026-03-17] 优化修改"sw_mutex_lock()"函数, 避免依赖系统时间, 导致的超
+ *                 时误差或跳变问题
  ***********************************************************************/
 #include "swapi.h"
 #include "swmem.h"
@@ -19,10 +21,8 @@ void *sw_mutex_create()
 	mt = (pthread_mutex_t *)sw_heap_malloc(sizeof(pthread_mutex_t));
 	if(mt)
 	{
-		memset(mt, 0, sizeof(pthread_mutex_t));
-		pthread_mutexattr_init(&attr);
-		if(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP) == 0) pthread_mutex_init(mt, &attr); // 检错锁
-		else{ sw_heap_free(mt); mt = NULL; }
+		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);
 	}
 	
@@ -41,25 +41,28 @@ void sw_mutex_destroy(void *hMutex)
 int sw_mutex_lock(void *hMutex, int timeout)
 {
 	pthread_mutex_t *mt = (pthread_mutex_t *)hMutex;
-	struct timespec ts = { 0 };
+	struct timespec start, now; int ret;
 	
 	if(timeout < 0)
 	{
 		return pthread_mutex_lock(mt);
 	}
-	else
+	
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	while((ret = pthread_mutex_trylock(mt)) == EBUSY)
 	{
-		ts.tv_sec = time(NULL) + timeout/1000;
-		ts.tv_nsec = (timeout%1000)*1000;
-		if(pthread_mutex_timedlock(mt, &ts) != 0) return -1;
+		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 0;
+	return ret == 0 ? 0 : -1;
 }
 
 /* 互斥量解锁 */
 void sw_mutex_unlock(void *hMutex)
 {
 	pthread_mutex_t *mt = (pthread_mutex_t *)hMutex;
-	if(mt) pthread_mutex_unlock(mt);
+	pthread_mutex_unlock(mt);
 }

+ 5 - 7
swapi/swsignal.c

@@ -18,10 +18,9 @@ void *sw_signal_create()
 	sem_t *sem = NULL;
 	
 	sem = (sem_t *)sw_heap_malloc(sizeof(sem_t));
-	if(sem)
+	if(sem && sem_init(sem, 0, 0) != 0)
 	{
-		memset(sem, 0, sizeof(sem_t));
-		sem_init(sem, 0, 0);
+		sw_heap_free(sem); sem = NULL;
 	}
 	
 	return sem;
@@ -66,14 +65,13 @@ wait_p2:
 		if(ret < 0 && errno == EINTR) goto wait_p2;
 		else return ret;
 #else
-		struct timespec start, now; struct timespec ts = { 0, 1000*1000 };
-		clock_gettime(CLOCK_MONOTONIC, &start);
+		struct timespec start, now; clock_gettime(CLOCK_MONOTONIC, &start);
 		while((ret = sem_trywait(sem)) < 0 && errno == EAGAIN)
 		{
 		  clock_gettime(CLOCK_MONOTONIC, &now);
-		  long elapsed = (now.tv_sec - start.tv_sec)*1000 + (now.tv_nsec-start.tv_nsec)/(1000*1000);
+		  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; }
-			nanosleep(&ts, NULL);
+		  else delay_ms(1); // 释放CPU占用, 避免过载
 		}
 		return ret;
 #endif