|
|
@@ -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;
|
|
|
}
|
|
|
|
|
|
/* 读写锁解锁 */
|