swsignal.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /************************************************************************
  2. * AUTHOR: NiuJiuRu
  3. * FILENAME: swsignal.c
  4. * DESCRIPTION: 信号量
  5. * NOTE: 主要用于状态通知
  6. * HISTORY:
  7. * 1, [2010-12-17] created by NiuJiuRu
  8. * 2, [2025-11-24] 优化修改"sw_signal_wait()"函数, 避免依赖系统时间, 导致的
  9. * 超时误差或跳变,具体修改如下:
  10. * - 将 "gettimeofday()" 替换成 "clock_gettime()"
  11. * - 将 "sem_timedwait()" 替换成 "sem_clockwait()"
  12. ***********************************************************************/
  13. #include "swapi.h"
  14. #include "swmem.h"
  15. #include "swsignal.h"
  16. /* 创建信号量 */
  17. void *sw_signal_create()
  18. {
  19. sem_t *sem = NULL;
  20. sem = (sem_t *)sw_heap_malloc(sizeof(sem_t));
  21. if(sem)
  22. {
  23. memset(sem, 0, sizeof(sem_t));
  24. sem_init(sem, 0, 0);
  25. }
  26. return sem;
  27. }
  28. /* 销毁信号量 */
  29. void sw_signal_destroy(void *hSignal)
  30. {
  31. sem_t *sem = (sem_t *)hSignal;
  32. sem_destroy(sem);
  33. sw_heap_free(sem);
  34. }
  35. /* 等待信号量, timeout(ms) = -1时表示无限等待 */
  36. int sw_signal_wait(void *hSignal, int timeout)
  37. {
  38. sem_t *sem = (sem_t *)hSignal;
  39. int ret;
  40. if(timeout < 0)
  41. {
  42. wait_p1:
  43. ret = sem_wait(sem);
  44. if(ret < 0 && errno == EINTR) goto wait_p1;
  45. else return ret;
  46. }
  47. else
  48. {
  49. struct timespec ts, now;
  50. clock_gettime(CLOCK_MONOTONIC/*单调时钟, 不受系统时间影响*/, &now); // "CLOCK_REALTIME"依赖系统时间
  51. ts.tv_sec = now.tv_sec + timeout/1000;
  52. ts.tv_nsec = now.tv_nsec + (timeout%1000)*1000*1000;
  53. if(ts.tv_nsec >= (1000*1000*1000))
  54. {
  55. ts.tv_sec += ts.tv_nsec/(1000*1000*1000);
  56. ts.tv_nsec %= (1000*1000*1000);
  57. }
  58. wait_p2:
  59. ret = sem_clockwait(sem, CLOCK_MONOTONIC, &ts); // 非POSIX标准, GNU扩展, 需定义:"_GNU_SOURCE"支持
  60. // , 同时glic库版本需大于等于2.28
  61. if(ret < 0 && errno == EINTR) goto wait_p2;
  62. else return ret;
  63. }
  64. }
  65. /* 点亮信号量 */
  66. void sw_signal_give(void *hSignal)
  67. {
  68. sem_t *sem = (sem_t *)hSignal;
  69. sem_post(sem);
  70. }