pthread_mutex.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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. mutex->lock.parent.parent.type = RT_Object_Class_Mutex;
  118. return 0;
  119. }
  120. RTM_EXPORT(pthread_mutex_init);
  121. int pthread_mutex_destroy(pthread_mutex_t *mutex)
  122. {
  123. if (!mutex || mutex->attr == -1)
  124. return EINVAL;
  125. /* it's busy */
  126. if (mutex->lock.owner != RT_NULL)
  127. return EBUSY;
  128. rt_memset(mutex, 0, sizeof(pthread_mutex_t));
  129. mutex->attr = -1;
  130. return 0;
  131. }
  132. RTM_EXPORT(pthread_mutex_destroy);
  133. int pthread_mutex_lock(pthread_mutex_t *mutex)
  134. {
  135. int mtype;
  136. rt_err_t result;
  137. if (!mutex)
  138. return EINVAL;
  139. if (mutex->attr == -1)
  140. {
  141. /* init mutex */
  142. pthread_mutex_init(mutex, RT_NULL);
  143. }
  144. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  145. rt_enter_critical();
  146. if (mutex->lock.owner == rt_thread_self() &&
  147. mtype != PTHREAD_MUTEX_RECURSIVE)
  148. {
  149. rt_exit_critical();
  150. return EDEADLK;
  151. }
  152. rt_exit_critical();
  153. result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
  154. if (result == RT_EOK)
  155. return 0;
  156. return EINVAL;
  157. }
  158. RTM_EXPORT(pthread_mutex_lock);
  159. int pthread_mutex_unlock(pthread_mutex_t *mutex)
  160. {
  161. rt_err_t result;
  162. if (!mutex)
  163. return EINVAL;
  164. if (mutex->attr == -1)
  165. {
  166. /* init mutex */
  167. pthread_mutex_init(mutex, RT_NULL);
  168. }
  169. if (mutex->lock.owner != rt_thread_self())
  170. {
  171. int mtype;
  172. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  173. /* error check, return EPERM */
  174. if (mtype == PTHREAD_MUTEX_ERRORCHECK)
  175. return EPERM;
  176. /* no thread waiting on this mutex */
  177. if (mutex->lock.owner == RT_NULL)
  178. return 0;
  179. }
  180. result = rt_mutex_release(&(mutex->lock));
  181. if (result == RT_EOK)
  182. return 0;
  183. return EINVAL;
  184. }
  185. RTM_EXPORT(pthread_mutex_unlock);
  186. int pthread_mutex_trylock(pthread_mutex_t *mutex)
  187. {
  188. rt_err_t result;
  189. int mtype;
  190. if (!mutex)
  191. return EINVAL;
  192. if (mutex->attr == -1)
  193. {
  194. /* init mutex */
  195. pthread_mutex_init(mutex, RT_NULL);
  196. }
  197. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  198. rt_enter_critical();
  199. if (mutex->lock.owner == rt_thread_self() &&
  200. mtype != PTHREAD_MUTEX_RECURSIVE)
  201. {
  202. rt_exit_critical();
  203. return EDEADLK;
  204. }
  205. rt_exit_critical();
  206. result = rt_mutex_take(&(mutex->lock), 0);
  207. if (result == RT_EOK) return 0;
  208. return EBUSY;
  209. }
  210. RTM_EXPORT(pthread_mutex_trylock);