1
0

rwlock.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. rwlock.c
  9. Abstract:
  10. This module implements support for POSIX read/write locks.
  11. Author:
  12. Evan Green 28-Apr-2015
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "pthreadp.h"
  20. //
  21. // ---------------------------------------------------------------- Definitions
  22. //
  23. //
  24. // ------------------------------------------------------ Data Type Definitions
  25. //
  26. //
  27. // ----------------------------------------------- Internal Function Prototypes
  28. //
  29. //
  30. // -------------------------------------------------------------------- Globals
  31. //
  32. //
  33. // ------------------------------------------------------------------ Functions
  34. //
  35. PTHREAD_API
  36. int
  37. pthread_rwlock_init (
  38. pthread_rwlock_t *Lock,
  39. pthread_rwlockattr_t *Attribute
  40. )
  41. /*++
  42. Routine Description:
  43. This routine initializes a read/write lock.
  44. Arguments:
  45. Lock - Supplies a pointer to the read/write lock.
  46. Attribute - Supplies an optional pointer to an initialized attribute
  47. structure governing the internal behavior of the lock.
  48. Return Value:
  49. 0 on success.
  50. Returns an error number on failure.
  51. --*/
  52. {
  53. PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
  54. ULONG Flags;
  55. PPTHREAD_RWLOCK LockInternal;
  56. ASSERT(sizeof(PTHREAD_RWLOCK) <= sizeof(pthread_rwlock_t));
  57. LockInternal = (PPTHREAD_RWLOCK)Lock;
  58. Flags = 0;
  59. if (Attribute != NULL) {
  60. AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
  61. Flags = AttributeInternal->Flags;
  62. }
  63. OsRwLockInitialize(&(LockInternal->Lock), Flags);
  64. return 0;
  65. }
  66. PTHREAD_API
  67. int
  68. pthread_rwlock_destroy (
  69. pthread_rwlock_t *Lock
  70. )
  71. /*++
  72. Routine Description:
  73. This routine destroys a read/write lock.
  74. Arguments:
  75. Lock - Supplies a pointer to the read/write lock.
  76. Return Value:
  77. 0 on success.
  78. Returns an error number on failure.
  79. --*/
  80. {
  81. PPTHREAD_RWLOCK LockInternal;
  82. LockInternal = (PPTHREAD_RWLOCK)Lock;
  83. if (LockInternal->Lock.State != 0) {
  84. return EBUSY;
  85. }
  86. //
  87. // Set it to some crazy value for debugability sake.
  88. //
  89. LockInternal->Lock.State = -2;
  90. return 0;
  91. }
  92. PTHREAD_API
  93. int
  94. pthread_rwlock_rdlock (
  95. pthread_rwlock_t *Lock
  96. )
  97. /*++
  98. Routine Description:
  99. This routine acquires the read/write lock for read access. Multiple readers
  100. can acquire the lock simultaneously, but any writes that try to acquire
  101. the lock while it's held for read will block. Readers that try to
  102. acquire the lock while it's held for write will also block.
  103. Arguments:
  104. Lock - Supplies a pointer to the read/write lock.
  105. Return Value:
  106. 0 on success.
  107. Returns an error number on failure.
  108. --*/
  109. {
  110. PPTHREAD_RWLOCK LockInternal;
  111. KSTATUS Status;
  112. LockInternal = (PPTHREAD_RWLOCK)Lock;
  113. Status = OsRwLockRead(&(LockInternal->Lock));
  114. if (Status == STATUS_SUCCESS) {
  115. return Status;
  116. }
  117. return ClConvertKstatusToErrorNumber(Status);
  118. }
  119. PTHREAD_API
  120. int
  121. pthread_rwlock_timedrdlock (
  122. pthread_rwlock_t *Lock,
  123. const struct timespec *AbsoluteTimeout
  124. )
  125. /*++
  126. Routine Description:
  127. This routine acquires the read/write lock for read access just like the
  128. read lock function, except that this function will return after the
  129. specified deadline if the lock could not be acquired.
  130. Arguments:
  131. Lock - Supplies a pointer to the read/write lock.
  132. AbsoluteTimeout - Supplies a pointer to the absolute deadline after which
  133. this function should give up and return failure.
  134. Return Value:
  135. 0 on success.
  136. ETIMEDOUT if the operation timed out. This thread will not own the lock.
  137. Returns an error number on failure.
  138. --*/
  139. {
  140. PPTHREAD_RWLOCK LockInternal;
  141. KSTATUS Status;
  142. ULONG TimeoutInMilliseconds;
  143. LockInternal = (PPTHREAD_RWLOCK)Lock;
  144. if (AbsoluteTimeout != NULL) {
  145. TimeoutInMilliseconds =
  146. ClpConvertAbsoluteTimespecToRelativeMilliseconds(AbsoluteTimeout,
  147. CLOCK_REALTIME);
  148. } else {
  149. TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  150. }
  151. Status = OsRwLockReadTimed(&(LockInternal->Lock), TimeoutInMilliseconds);
  152. if (Status == STATUS_SUCCESS) {
  153. return Status;
  154. }
  155. return ClConvertKstatusToErrorNumber(Status);
  156. }
  157. PTHREAD_API
  158. int
  159. pthread_rwlock_tryrdlock (
  160. pthread_rwlock_t *Lock
  161. )
  162. /*++
  163. Routine Description:
  164. This routine performs a single attempt at acquiring the lock for read
  165. access.
  166. Arguments:
  167. Lock - Supplies a pointer to the read/write lock.
  168. Return Value:
  169. 0 on success.
  170. Returns an error number on failure.
  171. --*/
  172. {
  173. PPTHREAD_RWLOCK LockInternal;
  174. KSTATUS Status;
  175. LockInternal = (PPTHREAD_RWLOCK)Lock;
  176. Status = OsRwLockTryRead(&(LockInternal->Lock));
  177. if (Status == STATUS_SUCCESS) {
  178. return Status;
  179. }
  180. return ClConvertKstatusToErrorNumber(Status);
  181. }
  182. PTHREAD_API
  183. int
  184. pthread_rwlock_wrlock (
  185. pthread_rwlock_t *Lock
  186. )
  187. /*++
  188. Routine Description:
  189. This routine acquires the read/write lock for write access. The lock can
  190. only be acquired for write access if there are no readers and no other
  191. writers.
  192. Arguments:
  193. Lock - Supplies a pointer to the read/write lock.
  194. Return Value:
  195. 0 on success.
  196. Returns an error number on failure.
  197. --*/
  198. {
  199. PPTHREAD_RWLOCK LockInternal;
  200. KSTATUS Status;
  201. LockInternal = (PPTHREAD_RWLOCK)Lock;
  202. Status = OsRwLockWrite(&(LockInternal->Lock));
  203. if (Status == STATUS_SUCCESS) {
  204. return Status;
  205. }
  206. return ClConvertKstatusToErrorNumber(Status);
  207. }
  208. PTHREAD_API
  209. int
  210. pthread_rwlock_timedwrlock (
  211. pthread_rwlock_t *Lock,
  212. const struct timespec *AbsoluteTimeout
  213. )
  214. /*++
  215. Routine Description:
  216. This routine acquires the read/write lock for write access just like the
  217. write lock function, except that this function will return after the
  218. specified deadline if the lock could not be acquired.
  219. Arguments:
  220. Lock - Supplies a pointer to the read/write lock.
  221. AbsoluteTimeout - Supplies a pointer to the absolute deadline after which
  222. this function should give up and return failure.
  223. Return Value:
  224. 0 on success.
  225. ETIMEDOUT if the operation timed out. This thread will not own the lock.
  226. Returns an error number on failure.
  227. --*/
  228. {
  229. PPTHREAD_RWLOCK LockInternal;
  230. KSTATUS Status;
  231. ULONG TimeoutInMilliseconds;
  232. LockInternal = (PPTHREAD_RWLOCK)Lock;
  233. if (AbsoluteTimeout != NULL) {
  234. TimeoutInMilliseconds =
  235. ClpConvertAbsoluteTimespecToRelativeMilliseconds(AbsoluteTimeout,
  236. CLOCK_REALTIME);
  237. } else {
  238. TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  239. }
  240. Status = OsRwLockWriteTimed(&(LockInternal->Lock), TimeoutInMilliseconds);
  241. if (Status == STATUS_SUCCESS) {
  242. return Status;
  243. }
  244. return ClConvertKstatusToErrorNumber(Status);
  245. }
  246. PTHREAD_API
  247. int
  248. pthread_rwlock_trywrlock (
  249. pthread_rwlock_t *Lock
  250. )
  251. /*++
  252. Routine Description:
  253. This routine performs a single attempt at acquiring the lock for write
  254. access.
  255. Arguments:
  256. Lock - Supplies a pointer to the read/write lock.
  257. Return Value:
  258. 0 on success.
  259. Returns an error number on failure.
  260. --*/
  261. {
  262. PPTHREAD_RWLOCK LockInternal;
  263. KSTATUS Status;
  264. LockInternal = (PPTHREAD_RWLOCK)Lock;
  265. Status = OsRwLockTryWrite(&(LockInternal->Lock));
  266. if (Status == STATUS_SUCCESS) {
  267. return Status;
  268. }
  269. return ClConvertKstatusToErrorNumber(Status);
  270. }
  271. PTHREAD_API
  272. int
  273. pthread_rwlock_unlock (
  274. pthread_rwlock_t *Lock
  275. )
  276. /*++
  277. Routine Description:
  278. This routine unlocks a read/write lock that's been acquired by this thread
  279. for either read or write.
  280. Arguments:
  281. Lock - Supplies a pointer to the read/write lock.
  282. Return Value:
  283. 0 on success.
  284. Returns an error number on failure.
  285. --*/
  286. {
  287. PPTHREAD_RWLOCK LockInternal;
  288. KSTATUS Status;
  289. LockInternal = (PPTHREAD_RWLOCK)Lock;
  290. Status = OsRwLockUnlock(&(LockInternal->Lock));
  291. if (Status == STATUS_SUCCESS) {
  292. return Status;
  293. }
  294. return ClConvertKstatusToErrorNumber(Status);
  295. }
  296. PTHREAD_API
  297. int
  298. pthread_rwlockattr_init (
  299. pthread_rwlockattr_t *Attribute
  300. )
  301. /*++
  302. Routine Description:
  303. This routine initializes a read/write lock attribute structure.
  304. Arguments:
  305. Attribute - Supplies a pointer to the read/write lock attribute.
  306. Return Value:
  307. 0 on success.
  308. Returns an error number on failure.
  309. --*/
  310. {
  311. PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
  312. AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
  313. AttributeInternal->Flags = 0;
  314. return 0;
  315. }
  316. PTHREAD_API
  317. int
  318. pthread_rwlockattr_destroy (
  319. pthread_rwlockattr_t *Attribute
  320. )
  321. /*++
  322. Routine Description:
  323. This routine destroys a read/write lock attribute structure.
  324. Arguments:
  325. Attribute - Supplies a pointer to the read/write lock attribute.
  326. Return Value:
  327. 0 on success.
  328. Returns an error number on failure.
  329. --*/
  330. {
  331. PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
  332. AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
  333. AttributeInternal->Flags = -1;
  334. return 0;
  335. }
  336. PTHREAD_API
  337. int
  338. pthread_rwlockattr_getpshared (
  339. const pthread_rwlockattr_t *Attribute,
  340. int *Shared
  341. )
  342. /*++
  343. Routine Description:
  344. This routine reads the shared attribute from a read/write lock attributes
  345. structure.
  346. Arguments:
  347. Attribute - Supplies a pointer to the read/write lock attribute.
  348. Shared - Supplies a pointer where the shared attribute of the lock will be
  349. returned on success. See PTHREAD_PROCESS_* definitions.
  350. Return Value:
  351. 0 on success.
  352. Returns an error number on failure.
  353. --*/
  354. {
  355. PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
  356. AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
  357. *Shared = PTHREAD_PROCESS_PRIVATE;
  358. if ((AttributeInternal->Flags & OS_RWLOCK_SHARED) != 0) {
  359. *Shared = PTHREAD_PROCESS_SHARED;
  360. }
  361. return 0;
  362. }
  363. PTHREAD_API
  364. int
  365. pthread_rwlockattr_setpshared (
  366. pthread_rwlockattr_t *Attribute,
  367. int Shared
  368. )
  369. /*++
  370. Routine Description:
  371. This routine sets the shared attribute in a read/write lock attributes
  372. structure.
  373. Arguments:
  374. Attribute - Supplies a pointer to the read/write lock attribute.
  375. Shared - Supplies the new shared value to set. See PTHREAD_PROCESS_*
  376. definitions.
  377. Return Value:
  378. 0 on success.
  379. Returns an error number on failure.
  380. --*/
  381. {
  382. PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
  383. AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
  384. if (Shared == PTHREAD_PROCESS_PRIVATE) {
  385. AttributeInternal->Flags &= ~OS_RWLOCK_SHARED;
  386. } else if (Shared == PTHREAD_PROCESS_SHARED) {
  387. AttributeInternal->Flags |= OS_RWLOCK_SHARED;
  388. } else {
  389. return EINVAL;
  390. }
  391. return 0;
  392. }
  393. //
  394. // --------------------------------------------------------- Internal Functions
  395. //