pthread_mutex.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2010-10-26 Bernard the first version
  9. */
  10. #include <rtthread.h>
  11. #include "pthread.h"
  12. #define MUTEXATTR_SHARED_MASK 0x0010
  13. #define MUTEXATTR_TYPE_MASK 0x000f
  14. const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;
  15. int pthread_mutexattr_init(pthread_mutexattr_t *attr)
  16. {
  17. if (attr)
  18. {
  19. *attr = pthread_default_mutexattr;
  20. return 0;
  21. }
  22. return EINVAL;
  23. }
  24. RTM_EXPORT(pthread_mutexattr_init);
  25. int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
  26. {
  27. if (attr)
  28. {
  29. *attr = -1;
  30. return 0;
  31. }
  32. return EINVAL;
  33. }
  34. RTM_EXPORT(pthread_mutexattr_destroy);
  35. int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
  36. {
  37. if (attr && type)
  38. {
  39. int atype = (*attr & MUTEXATTR_TYPE_MASK);
  40. if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK)
  41. {
  42. *type = atype;
  43. return 0;
  44. }
  45. }
  46. return EINVAL;
  47. }
  48. RTM_EXPORT(pthread_mutexattr_gettype);
  49. int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
  50. {
  51. if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_ERRORCHECK)
  52. {
  53. *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
  54. return 0;
  55. }
  56. return EINVAL;
  57. }
  58. RTM_EXPORT(pthread_mutexattr_settype);
  59. int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
  60. {
  61. if (!attr)
  62. return EINVAL;
  63. switch (pshared)
  64. {
  65. case PTHREAD_PROCESS_PRIVATE:
  66. *attr &= ~MUTEXATTR_SHARED_MASK;
  67. return 0;
  68. case PTHREAD_PROCESS_SHARED:
  69. *attr |= MUTEXATTR_SHARED_MASK;
  70. return 0;
  71. }
  72. return EINVAL;
  73. }
  74. RTM_EXPORT(pthread_mutexattr_setpshared);
  75. int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
  76. {
  77. if (!attr || !pshared)
  78. return EINVAL;
  79. *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
  80. : PTHREAD_PROCESS_PRIVATE;
  81. return 0;
  82. }
  83. RTM_EXPORT(pthread_mutexattr_getpshared);
  84. int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
  85. {
  86. rt_err_t result;
  87. char name[RT_NAME_MAX];
  88. static rt_uint16_t pthread_mutex_number = 0;
  89. if (!mutex)
  90. return EINVAL;
  91. /* build mutex name */
  92. rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
  93. if (attr == RT_NULL)
  94. mutex->attr = pthread_default_mutexattr;
  95. else
  96. mutex->attr = *attr;
  97. /* init mutex lock */
  98. result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_PRIO);
  99. if (result != RT_EOK)
  100. return EINVAL;
  101. /* detach the object from system object container */
  102. rt_object_detach(&(mutex->lock.parent.parent));
  103. mutex->lock.parent.parent.type = RT_Object_Class_Mutex;
  104. return 0;
  105. }
  106. RTM_EXPORT(pthread_mutex_init);
  107. int pthread_mutex_destroy(pthread_mutex_t *mutex)
  108. {
  109. if (!mutex || mutex->attr == -1)
  110. return EINVAL;
  111. /* it's busy */
  112. if (mutex->lock.owner != RT_NULL)
  113. return EBUSY;
  114. rt_memset(mutex, 0, sizeof(pthread_mutex_t));
  115. mutex->attr = -1;
  116. return 0;
  117. }
  118. RTM_EXPORT(pthread_mutex_destroy);
  119. int pthread_mutex_lock(pthread_mutex_t *mutex)
  120. {
  121. int mtype;
  122. rt_err_t result;
  123. if (!mutex)
  124. return EINVAL;
  125. if (mutex->attr == -1)
  126. {
  127. /* init mutex */
  128. pthread_mutex_init(mutex, RT_NULL);
  129. }
  130. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  131. rt_enter_critical();
  132. if (mutex->lock.owner == rt_thread_self() &&
  133. mtype != PTHREAD_MUTEX_RECURSIVE)
  134. {
  135. rt_exit_critical();
  136. return EDEADLK;
  137. }
  138. rt_exit_critical();
  139. result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
  140. if (result == RT_EOK)
  141. return 0;
  142. return EINVAL;
  143. }
  144. RTM_EXPORT(pthread_mutex_lock);
  145. int pthread_mutex_unlock(pthread_mutex_t *mutex)
  146. {
  147. rt_err_t result;
  148. if (!mutex)
  149. return EINVAL;
  150. if (mutex->attr == -1)
  151. {
  152. /* init mutex */
  153. pthread_mutex_init(mutex, RT_NULL);
  154. }
  155. if (mutex->lock.owner != rt_thread_self())
  156. {
  157. int mtype;
  158. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  159. /* error check, return EPERM */
  160. if (mtype == PTHREAD_MUTEX_ERRORCHECK)
  161. return EPERM;
  162. /* no thread waiting on this mutex */
  163. if (mutex->lock.owner == RT_NULL)
  164. return 0;
  165. }
  166. result = rt_mutex_release(&(mutex->lock));
  167. if (result == RT_EOK)
  168. return 0;
  169. return EINVAL;
  170. }
  171. RTM_EXPORT(pthread_mutex_unlock);
  172. int pthread_mutex_trylock(pthread_mutex_t *mutex)
  173. {
  174. rt_err_t result;
  175. int mtype;
  176. if (!mutex)
  177. return EINVAL;
  178. if (mutex->attr == -1)
  179. {
  180. /* init mutex */
  181. pthread_mutex_init(mutex, RT_NULL);
  182. }
  183. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  184. rt_enter_critical();
  185. if (mutex->lock.owner == rt_thread_self() &&
  186. mtype != PTHREAD_MUTEX_RECURSIVE)
  187. {
  188. rt_exit_critical();
  189. return EDEADLK;
  190. }
  191. rt_exit_critical();
  192. result = rt_mutex_take(&(mutex->lock), 0);
  193. if (result == RT_EOK) return 0;
  194. return EBUSY;
  195. }
  196. RTM_EXPORT(pthread_mutex_trylock);
  197. int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling)
  198. {
  199. return EINVAL;
  200. }
  201. RTM_EXPORT(pthread_mutexattr_getprioceiling);
  202. int pthread_mutexattr_setprioceiling(const pthread_mutexattr_t *attr, int prioceiling)
  203. {
  204. return EINVAL;
  205. }
  206. RTM_EXPORT(pthread_mutexattr_setprioceiling);
  207. int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
  208. {
  209. return EINVAL;
  210. }
  211. RTM_EXPORT(pthread_mutexattr_getprotocol);
  212. int pthread_mutexattr_setprotocol(const pthread_mutexattr_t *attr, int protocol)
  213. {
  214. return EINVAL;
  215. }
  216. RTM_EXPORT(pthread_mutexattr_setprotocol);
  217. int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling)
  218. {
  219. return pthread_mutexattr_getprioceiling(&mutex->attr, prioceiling);
  220. }
  221. RTM_EXPORT(pthread_mutex_getprioceiling);
  222. int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling)
  223. {
  224. *old_ceiling = pthread_mutexattr_getprioceiling(&mutex->attr, old_ceiling);
  225. if(*old_ceiling != 0)
  226. {
  227. return EINVAL;
  228. }
  229. return pthread_mutexattr_setprioceiling(&mutex->attr, prioceiling);
  230. }
  231. RTM_EXPORT(pthread_mutex_setprioceiling);