| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- /************************************************************************
- * AUTHOR: NiuJiuRu
- * FILENAME: swsignal.c
- * DESCRIPTION: 信号量
- * NOTE: 主要用于状态通知
- * HISTORY:
- * 1, [2010-12-17] created by NiuJiuRu
- * 2, [2025-11-24] 优化修改"sw_signal_wait()"函数, 避免依赖系统时间, 导致的
- * 超时误差或跳变,具体修改如下:
- * - 将 "gettimeofday()" 替换成 "clock_gettime()"
- * - 将 "sem_timedwait()" 替换成 "sem_clockwait()"
- ***********************************************************************/
- #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;
- int ret;
-
- if(timeout < 0)
- {
- wait_p1:
- ret = sem_wait(sem);
- if(ret < 0 && errno == EINTR) goto wait_p1;
- else return ret;
- }
- else
- {
- struct timespec ts, now;
- clock_gettime(CLOCK_MONOTONIC/*单调时钟, 不受系统时间影响*/, &now); // "CLOCK_REALTIME"依赖系统时间
- ts.tv_sec = now.tv_sec + timeout/1000;
- ts.tv_nsec = now.tv_nsec + (timeout%1000)*1000*1000;
- if(ts.tv_nsec >= (1000*1000*1000))
- {
- ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
- ts.tv_nsec %= (1000*1000*1000);
- }
- wait_p2:
- ret = sem_clockwait(sem, CLOCK_MONOTONIC, &ts); // 非POSIX标准, GNU扩展, 需定义:"_GNU_SOURCE"支持
- // , 同时glic库版本需大于等于2.28
- 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);
- }
|