semaphore.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <errno.h>
  2. #include <sys/fcntl.h>
  3. #include <rtthread.h>
  4. #include "semaphore.h"
  5. int sem_close(sem_t *sem)
  6. {
  7. if (!sem) return EINVAL;
  8. /* delete semaphore allocated in sem_open */
  9. rt_sem_delete(sem);
  10. return 0;
  11. }
  12. int sem_destroy(sem_t *sem)
  13. {
  14. rt_err_t result;
  15. if (!sem) return EINVAL;
  16. /* check whether semaphore is busy or not */
  17. result = rt_sem_trytake(sem);
  18. if (result != RT_EOK) return EBUSY;
  19. rt_memset(sem, 0, sizeof(sem_t));
  20. return 0;
  21. }
  22. int sem_unlink(const char *name)
  23. {
  24. return EACCES;
  25. }
  26. int sem_getvalue(sem_t *sem, int *sval)
  27. {
  28. RT_ASSERT(sem != RT_NULL);
  29. if (sval) *sval = sem->value;
  30. }
  31. int sem_init(sem_t *sem, int pshared, unsigned int value)
  32. {
  33. rt_err_t result;
  34. char name[RT_NAME_MAX];
  35. static rt_uint16_t psem_number = 0;
  36. RT_ASSERT(sem != RT_NULL);
  37. rt_snprintf(name, sizeof(name), "psem%02d", psem_number++);
  38. result = rt_sem_init(sem, name, value, RT_IPC_FLAG_FIFO);
  39. if (result == RT_EOK)
  40. {
  41. /* detach kernel object */
  42. rt_object_detach(&(sem->parent.parent));
  43. return 0;
  44. }
  45. return ENOSPC;
  46. }
  47. /* introduce from kservice.c */
  48. #define rt_list_entry(node, type, member) \
  49. ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
  50. sem_t *sem_open(const char *name, int oflag, ...)
  51. {
  52. rt_sem_t sem;
  53. sem = RT_NULL;
  54. if (oflag == O_CREAT)
  55. {
  56. sem = rt_sem_create(name, 1, RT_IPC_FLAG_FIFO);
  57. if (sem == RT_NULL)
  58. rt_set_errno(ENOSPC);
  59. }
  60. /* find semaphore */
  61. if (oflag == O_EXCL)
  62. {
  63. struct rt_object* object;
  64. struct rt_list_node* node;
  65. struct rt_object_information *information;
  66. extern struct rt_object_information rt_object_container[];
  67. /* enter critical */
  68. rt_enter_critical();
  69. /* try to find device object */
  70. information = &rt_object_container[RT_Object_Class_Semaphore];
  71. for (node = information->object_list.next; node != &(information->object_list); node = node->next)
  72. {
  73. object = rt_list_entry(node, struct rt_object, list);
  74. if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
  75. {
  76. /* leave critical */
  77. rt_exit_critical();
  78. return (rt_sem_t)object;
  79. }
  80. }
  81. /* leave critical */
  82. rt_exit_critical();
  83. rt_set_errno(ENOENT);
  84. return RT_NULL;
  85. }
  86. return sem;
  87. }
  88. int sem_post(sem_t *sem)
  89. {
  90. rt_sem_release(sem);
  91. }
  92. int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
  93. {
  94. rt_err_t result;
  95. rt_int32_t tick;
  96. if (!sem || !abs_timeout) return EINVAL;
  97. /* calculate os tick */
  98. tick = abs_timeout->tv_sec/RT_TICK_PER_SECOND + (abs_timeout->tv_nsec/1000) * (1000/RT_TICK_PER_SECOND);
  99. result = rt_sem_take(sem, tick);
  100. if (result == -RT_ETIMEOUT) return ETIMEDOUT;
  101. if (result == RT_EOK) return 0;
  102. return EINTR;
  103. }
  104. int sem_trywait(sem_t *sem)
  105. {
  106. rt_err_t result;
  107. if (!sem) return EINVAL;
  108. result = rt_sem_take(sem, RT_WAITING_FOREVER);
  109. if (result == -RT_ETIMEOUT) return EAGAIN;
  110. if (result == RT_EOK) return 0;
  111. return EINTR;
  112. }
  113. int sem_wait(sem_t *sem)
  114. {
  115. rt_err_t result;
  116. result = rt_sem_take(sem, RT_WAITING_FOREVER);
  117. if (result == RT_EOK) return 0;
  118. return EINTR;
  119. }