1
0

pthread_mutex.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include <rtthread.h>
  2. #include "pthread.h"
  3. #define MUTEXATTR_SHARED_MASK 0x0010
  4. #define MUTEXATTR_TYPE_MASK 0x000f
  5. const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;
  6. int pthread_mutexattr_init(pthread_mutexattr_t *attr)
  7. {
  8. if (attr)
  9. {
  10. *attr = pthread_default_mutexattr;
  11. return 0;
  12. }
  13. return EINVAL;
  14. }
  15. RTM_EXPORT(pthread_mutexattr_init);
  16. int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
  17. {
  18. if (attr)
  19. {
  20. *attr = -1;
  21. return 0;
  22. }
  23. return EINVAL;
  24. }
  25. RTM_EXPORT(pthread_mutexattr_destroy);
  26. int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
  27. {
  28. if (attr && type)
  29. {
  30. int atype = (*attr & MUTEXATTR_TYPE_MASK);
  31. if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK)
  32. {
  33. *type = atype;
  34. return 0;
  35. }
  36. }
  37. return EINVAL;
  38. }
  39. RTM_EXPORT(pthread_mutexattr_gettype);
  40. int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
  41. {
  42. if (attr && type >= PTHREAD_MUTEX_NORMAL &&
  43. type <= PTHREAD_MUTEX_ERRORCHECK )
  44. {
  45. *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
  46. return 0;
  47. }
  48. return EINVAL;
  49. }
  50. RTM_EXPORT(pthread_mutexattr_settype);
  51. int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
  52. {
  53. if (!attr) return EINVAL;
  54. switch (pshared)
  55. {
  56. case PTHREAD_PROCESS_PRIVATE:
  57. *attr &= ~MUTEXATTR_SHARED_MASK;
  58. return 0;
  59. case PTHREAD_PROCESS_SHARED:
  60. *attr |= MUTEXATTR_SHARED_MASK;
  61. return 0;
  62. }
  63. return EINVAL;
  64. }
  65. RTM_EXPORT(pthread_mutexattr_setpshared);
  66. int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
  67. {
  68. if (!attr || !pshared) return EINVAL;
  69. *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
  70. : PTHREAD_PROCESS_PRIVATE;
  71. return 0;
  72. }
  73. RTM_EXPORT(pthread_mutexattr_getpshared);
  74. int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
  75. {
  76. rt_err_t result;
  77. char name[RT_NAME_MAX];
  78. static rt_uint16_t pthread_mutex_number = 0;
  79. if (!mutex) return EINVAL;
  80. /* build mutex name */
  81. rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
  82. if (attr == RT_NULL) mutex->attr = pthread_default_mutexattr;
  83. else mutex->attr = *attr;
  84. /* init mutex lock */
  85. result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO);
  86. if (result != RT_EOK) return EINVAL;
  87. /* detach the object from system object container */
  88. rt_object_detach(&(mutex->lock.parent.parent));
  89. return 0;
  90. }
  91. RTM_EXPORT(pthread_mutex_init);
  92. int pthread_mutex_destroy(pthread_mutex_t *mutex)
  93. {
  94. if (!mutex || mutex->attr == -1) return EINVAL;
  95. /* it's busy */
  96. if (mutex->lock.owner != RT_NULL) return EBUSY;
  97. rt_memset(mutex, 0, sizeof(pthread_mutex_t));
  98. mutex->attr = -1;
  99. return 0;
  100. }
  101. RTM_EXPORT(pthread_mutex_destroy);
  102. int pthread_mutex_lock(pthread_mutex_t *mutex)
  103. {
  104. int mtype;
  105. rt_err_t result;
  106. if (!mutex) return EINVAL;
  107. if (mutex->attr == -1)
  108. {
  109. /* init mutex */
  110. pthread_mutex_init(mutex, RT_NULL);
  111. }
  112. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  113. rt_enter_critical();
  114. if (mutex->lock.owner == rt_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE)
  115. {
  116. rt_exit_critical();
  117. return EDEADLK;
  118. }
  119. rt_exit_critical();
  120. result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
  121. if (result == RT_EOK) return 0;
  122. return EINVAL;
  123. }
  124. RTM_EXPORT(pthread_mutex_lock);
  125. int pthread_mutex_unlock(pthread_mutex_t *mutex)
  126. {
  127. rt_err_t result;
  128. if (!mutex) return EINVAL;
  129. if (mutex->attr == -1)
  130. {
  131. /* init mutex */
  132. pthread_mutex_init(mutex, RT_NULL);
  133. }
  134. if (mutex->lock.owner != rt_thread_self())
  135. {
  136. int mtype;
  137. mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
  138. /* error check, return EPERM */
  139. if (mtype == PTHREAD_MUTEX_ERRORCHECK) return EPERM;
  140. /* no thread waiting on this mutex */
  141. if (mutex->lock.owner == RT_NULL) return 0;
  142. }
  143. result = rt_mutex_release(&(mutex->lock));
  144. if (result == RT_EOK) return 0;
  145. return EINVAL;
  146. }
  147. RTM_EXPORT(pthread_mutex_unlock);
  148. int pthread_mutex_trylock(pthread_mutex_t *mutex)
  149. {
  150. rt_err_t result;
  151. if (!mutex) return EINVAL;
  152. if (mutex->attr == -1)
  153. {
  154. /* init mutex */
  155. pthread_mutex_init(mutex, RT_NULL);
  156. }
  157. result = rt_mutex_take(&(mutex->lock), 0);
  158. if (result == RT_EOK) return 0;
  159. return EBUSY;
  160. }
  161. RTM_EXPORT(pthread_mutex_trylock);