pthread_rwlock.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include <pthread.h>
  2. int pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
  3. {
  4. if (!attr) return EINVAL;
  5. *attr = PTHREAD_PROCESS_PRIVATE;
  6. return 0;
  7. }
  8. RTM_EXPORT(pthread_rwlockattr_init);
  9. int pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
  10. {
  11. if (!attr) return EINVAL;
  12. return 0;
  13. }
  14. RTM_EXPORT(pthread_rwlockattr_destroy);
  15. int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, int *pshared)
  16. {
  17. if (!attr || !pshared) return EINVAL;
  18. *pshared = PTHREAD_PROCESS_PRIVATE;
  19. return 0;
  20. }
  21. RTM_EXPORT(pthread_rwlockattr_getpshared);
  22. int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared)
  23. {
  24. if (!attr || pshared != PTHREAD_PROCESS_PRIVATE) return EINVAL;
  25. return 0;
  26. }
  27. RTM_EXPORT(pthread_rwlockattr_setpshared);
  28. int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t * attr)
  29. {
  30. if (!rwlock) return EINVAL;
  31. rwlock->attr = PTHREAD_PROCESS_PRIVATE;
  32. pthread_mutex_init(&(rwlock->rw_mutex), NULL);
  33. pthread_cond_init(&(rwlock->rw_condreaders), NULL);
  34. pthread_cond_init(&(rwlock->rw_condwriters), NULL);
  35. rwlock->rw_nwaitwriters = 0;
  36. rwlock->rw_nwaitreaders = 0;
  37. rwlock->rw_refcount = 0;
  38. return 0;
  39. }
  40. RTM_EXPORT(pthread_rwlock_init);
  41. int pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
  42. {
  43. int result;
  44. if (!rwlock) return EINVAL;
  45. if (rwlock->attr == -1) return 0; /* rwlock is not initialized */
  46. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  47. return(result);
  48. if (rwlock->rw_refcount != 0 ||
  49. rwlock->rw_nwaitreaders != 0 || rwlock->rw_nwaitwriters != 0)
  50. {
  51. result = EBUSY;
  52. return(EBUSY);
  53. }
  54. else
  55. {
  56. /* check whether busy */
  57. result = rt_sem_trytake(&(rwlock->rw_condreaders.sem));
  58. if (result == RT_EOK)
  59. {
  60. result = rt_sem_trytake(&(rwlock->rw_condwriters.sem));
  61. if (result == RT_EOK)
  62. {
  63. rt_sem_release(&(rwlock->rw_condreaders.sem));
  64. rt_sem_release(&(rwlock->rw_condwriters.sem));
  65. pthread_cond_destroy(&rwlock->rw_condreaders);
  66. pthread_cond_destroy(&rwlock->rw_condwriters);
  67. }
  68. else
  69. {
  70. rt_sem_release(&(rwlock->rw_condreaders.sem));
  71. result = EBUSY;
  72. }
  73. }
  74. else result = EBUSY;
  75. }
  76. pthread_mutex_unlock(&rwlock->rw_mutex);
  77. if (result == 0) pthread_mutex_destroy(&rwlock->rw_mutex);
  78. return result;
  79. }
  80. RTM_EXPORT(pthread_rwlock_destroy);
  81. int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
  82. {
  83. int result;
  84. if (!rwlock) return EINVAL;
  85. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  86. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  87. return(result);
  88. /* give preference to waiting writers */
  89. while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0)
  90. {
  91. rwlock->rw_nwaitreaders++;
  92. /* rw_mutex will be released when waiting for rw_condreaders */
  93. result = pthread_cond_wait(&rwlock->rw_condreaders, &rwlock->rw_mutex);
  94. /* rw_mutex should have been taken again when returned from waiting */
  95. rwlock->rw_nwaitreaders--;
  96. if (result != 0) /* wait error */
  97. break;
  98. }
  99. /* another reader has a read lock */
  100. if (result == 0) rwlock->rw_refcount++;
  101. pthread_mutex_unlock(&rwlock->rw_mutex);
  102. return (result);
  103. }
  104. RTM_EXPORT(pthread_rwlock_rdlock);
  105. int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
  106. {
  107. int result;
  108. if (!rwlock) return EINVAL;
  109. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  110. if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  111. return(result);
  112. if (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0)
  113. result = EBUSY; /* held by a writer or waiting writers */
  114. else
  115. rwlock->rw_refcount++; /* increment count of reader locks */
  116. pthread_mutex_unlock(&rwlock->rw_mutex);
  117. return(result);
  118. }
  119. RTM_EXPORT(pthread_rwlock_tryrdlock);
  120. int pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock, const struct timespec *abstime)
  121. {
  122. int result;
  123. if (!rwlock) return EINVAL;
  124. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  125. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  126. return(result);
  127. /* give preference to waiting writers */
  128. while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0)
  129. {
  130. rwlock->rw_nwaitreaders++;
  131. /* rw_mutex will be released when waiting for rw_condreaders */
  132. result = pthread_cond_timedwait(&rwlock->rw_condreaders, &rwlock->rw_mutex, abstime);
  133. /* rw_mutex should have been taken again when returned from waiting */
  134. rwlock->rw_nwaitreaders--;
  135. if (result != 0)
  136. break;
  137. }
  138. /* another reader has a read lock */
  139. if (result == 0) rwlock->rw_refcount++;
  140. pthread_mutex_unlock(&rwlock->rw_mutex);
  141. return (result);
  142. }
  143. RTM_EXPORT(pthread_rwlock_timedrdlock);
  144. int pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime)
  145. {
  146. int result;
  147. if (!rwlock) return EINVAL;
  148. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  149. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  150. return(result);
  151. while (rwlock->rw_refcount != 0)
  152. {
  153. rwlock->rw_nwaitwriters++;
  154. /* rw_mutex will be released when waiting for rw_condwriters */
  155. result = pthread_cond_timedwait(&rwlock->rw_condwriters, &rwlock->rw_mutex, abstime);
  156. /* rw_mutex should have been taken again when returned from waiting */
  157. rwlock->rw_nwaitwriters--;
  158. if (result != 0) break;
  159. }
  160. if (result == 0) rwlock->rw_refcount = -1;
  161. pthread_mutex_unlock(&rwlock->rw_mutex);
  162. return(result);
  163. }
  164. RTM_EXPORT(pthread_rwlock_timedwrlock);
  165. int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
  166. {
  167. int result;
  168. if (!rwlock) return EINVAL;
  169. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  170. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  171. return(result);
  172. if (rwlock->rw_refcount != 0)
  173. result = EBUSY; /* held by either writer or reader(s) */
  174. else
  175. rwlock->rw_refcount = -1; /* available, indicate a writer has it */
  176. pthread_mutex_unlock(&rwlock->rw_mutex);
  177. return(result);
  178. }
  179. RTM_EXPORT(pthread_rwlock_trywrlock);
  180. int pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
  181. {
  182. int result;
  183. if (!rwlock) return EINVAL;
  184. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  185. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  186. return(result);
  187. if (rwlock->rw_refcount > 0)
  188. rwlock->rw_refcount--; /* releasing a reader */
  189. else if (rwlock->rw_refcount == -1)
  190. rwlock->rw_refcount = 0; /* releasing a writer */
  191. /* give preference to waiting writers over waiting readers */
  192. if (rwlock->rw_nwaitwriters > 0)
  193. {
  194. if (rwlock->rw_refcount == 0)
  195. result = pthread_cond_signal(&rwlock->rw_condwriters);
  196. }
  197. else if (rwlock->rw_nwaitreaders > 0)
  198. {
  199. result = pthread_cond_broadcast(&rwlock->rw_condreaders);
  200. }
  201. pthread_mutex_unlock(&rwlock->rw_mutex);
  202. return(result);
  203. }
  204. RTM_EXPORT(pthread_rwlock_unlock);
  205. int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
  206. {
  207. int result;
  208. if (!rwlock) return EINVAL;
  209. if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL);
  210. if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0)
  211. return(result);
  212. while (rwlock->rw_refcount != 0)
  213. {
  214. rwlock->rw_nwaitwriters++;
  215. /* rw_mutex will be released when waiting for rw_condwriters */
  216. result = pthread_cond_wait(&rwlock->rw_condwriters, &rwlock->rw_mutex);
  217. /* rw_mutex should have been taken again when returned from waiting */
  218. rwlock->rw_nwaitwriters--;
  219. if (result != 0) break;
  220. }
  221. if (result == 0) rwlock->rw_refcount = -1;
  222. pthread_mutex_unlock(&rwlock->rw_mutex);
  223. return(result);
  224. }
  225. RTM_EXPORT(pthread_rwlock_wrlock);