pthread_mutex.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * File : pthread_mutex.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2010-10-26 Bernard the first version
  23. */
  24. #include <rtthread.h>
  25. #include "pthread.h"
  26. #define MUTEXATTR_SHARED_MASK 0x0010
  27. #define MUTEXATTR_TYPE_MASK 0x000f
  28. const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;
  29. int pthread_mutexattr_init(pthread_mutexattr_t *attr)
  30. {
  31. if (attr)
  32. {
  33. *attr = pthread_default_mutexattr;
  34. return 0;
  35. }
  36. return EINVAL;
  37. }
  38. RTM_EXPORT(pthread_mutexattr_init);
  39. int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
  40. {
  41. if (attr)
  42. {
  43. *attr = -1;
  44. return 0;
  45. }
  46. return EINVAL;
  47. }
  48. RTM_EXPORT(pthread_mutexattr_destroy);
  49. int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
  50. {
  51. if (attr && type)
  52. {
  53. int atype = (*attr & MUTEXATTR_TYPE_MASK);
  54. if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK)
  55. {
  56. *type = atype;
  57. return 0;
  58. }
  59. }
  60. return EINVAL;
  61. }
  62. RTM_EXPORT(pthread_mutexattr_gettype);
  63. int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
  64. {
  65. if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_ERRORCHECK)
  66. {
  67. *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
  68. return 0;
  69. }
  70. return EINVAL;
  71. }
  72. RTM_EXPORT(pthread_mutexattr_settype);
  73. int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
  74. {
  75. if (!attr)
  76. return EINVAL;
  77. switch (pshared)
  78. {
  79. case PTHREAD_PROCESS_PRIVATE:
  80. *attr &= ~MUTEXATTR_SHARED_MASK;
  81. return 0;
  82. case PTHREAD_PROCESS_SHARED:
  83. *attr |= MUTEXATTR_SHARED_MASK;
  84. return 0;
  85. }
  86. return EINVAL;
  87. }
  88. RTM_EXPORT(pthread_mutexattr_setpshared);
  89. int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
  90. {
  91. if (!attr || !pshared)
  92. return EINVAL;
  93. *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
  94. : PTHREAD_PROCESS_PRIVATE;
  95. return 0;
  96. }
  97. RTM_EXPORT(pthread_mutexattr_getpshared);
  98. int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
  99. {
  100. rt_err_t result;
  101. char name[RT_NAME_MAX];
  102. static rt_uint16_t pthread_mutex_number = 0;
  103. if (!mutex)
  104. return EINVAL;
  105. /* build mutex name */
  106. rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
  107. if (attr == RT_NULL)
  108. mutex->attr = pthread_default_mutexattr;
  109. else
  110. mutex->attr = *attr;
  111. /* init mutex lock */
  112. result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO);
  113. if (result != RT_EOK)
  114. return EINVAL;
  115. /* detach the object from system object container */
  116. rt_object_detach(&(mutex->lock.parent.parent));
  117. return 0;
  118. }
  119. RTM_EXPORT(pthread_mutex_init);
  120. int pthread_mutex_destroy(pthread_mutex_t *mutex)
  121. {
  122. if (!mutex || mutex->attr == -1)
  123. return EINVAL;
  124. /* it's busy */
  125. if (mutex->lock.owner != RT_NULL)
  126. return EBUSY;
  127. rt_memset(mutex, 0, sizeof(pthread_mutex_t));
  128. mutex->attr = -1;
  129. return 0;
  130. }
  131. RTM_EXPORT(pthread_mutex_destroy);
  132. int pthread_mutex_lock(pthread_mutex_t *mutex)
  133. {
  134. int mtype;
  135. rt_err_t result;
  136. if (!mutex)
  137. return EINVAL;
  138. if (mutex->attr == -1)
  139. {
  140. /* init mutex */
  141. pthread_mutex_init(mutex, RT_NULL);
  142. }
  143. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  144. rt_enter_critical();
  145. if (mutex->lock.owner == rt_thread_self() &&
  146. mtype != PTHREAD_MUTEX_RECURSIVE)
  147. {
  148. rt_exit_critical();
  149. return EDEADLK;
  150. }
  151. rt_exit_critical();
  152. result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
  153. if (result == RT_EOK)
  154. return 0;
  155. return EINVAL;
  156. }
  157. RTM_EXPORT(pthread_mutex_lock);
  158. int pthread_mutex_unlock(pthread_mutex_t *mutex)
  159. {
  160. rt_err_t result;
  161. if (!mutex)
  162. return EINVAL;
  163. if (mutex->attr == -1)
  164. {
  165. /* init mutex */
  166. pthread_mutex_init(mutex, RT_NULL);
  167. }
  168. if (mutex->lock.owner != rt_thread_self())
  169. {
  170. int mtype;
  171. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  172. /* error check, return EPERM */
  173. if (mtype == PTHREAD_MUTEX_ERRORCHECK)
  174. return EPERM;
  175. /* no thread waiting on this mutex */
  176. if (mutex->lock.owner == RT_NULL)
  177. return 0;
  178. }
  179. result = rt_mutex_release(&(mutex->lock));
  180. if (result == RT_EOK)
  181. return 0;
  182. return EINVAL;
  183. }
  184. RTM_EXPORT(pthread_mutex_unlock);
  185. int pthread_mutex_trylock(pthread_mutex_t *mutex)
  186. {
  187. rt_err_t result;
  188. if (!mutex)
  189. return EINVAL;
  190. if (mutex->attr == -1)
  191. {
  192. /* init mutex */
  193. pthread_mutex_init(mutex, RT_NULL);
  194. }
  195. result = rt_mutex_take(&(mutex->lock), 0);
  196. if (result == RT_EOK)
  197. return 0;
  198. return EBUSY;
  199. }
  200. RTM_EXPORT(pthread_mutex_trylock);