123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- /*++
- Copyright (c) 2015 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- rwlock.c
- Abstract:
- This module implements support for POSIX read/write locks.
- Author:
- Evan Green 28-Apr-2015
- Environment:
- User Mode C Library
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "pthreadp.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- PTHREAD_API
- int
- pthread_rwlock_init (
- pthread_rwlock_t *Lock,
- pthread_rwlockattr_t *Attribute
- )
- /*++
- Routine Description:
- This routine initializes a read/write lock.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Attribute - Supplies an optional pointer to an initialized attribute
- structure governing the internal behavior of the lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
- ULONG Flags;
- PPTHREAD_RWLOCK LockInternal;
- ASSERT(sizeof(PTHREAD_RWLOCK) <= sizeof(pthread_rwlock_t));
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Flags = 0;
- if (Attribute != NULL) {
- AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
- Flags = AttributeInternal->Flags;
- }
- OsRwLockInitialize(&(LockInternal->Lock), Flags);
- return 0;
- }
- PTHREAD_API
- int
- pthread_rwlock_destroy (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine destroys a read/write lock.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- if (LockInternal->Lock.State != 0) {
- return EBUSY;
- }
- //
- // Set it to some crazy value for debugability sake.
- //
- LockInternal->Lock.State = -2;
- return 0;
- }
- PTHREAD_API
- int
- pthread_rwlock_rdlock (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine acquires the read/write lock for read access. Multiple readers
- can acquire the lock simultaneously, but any writes that try to acquire
- the lock while it's held for read will block. Readers that try to
- acquire the lock while it's held for write will also block.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Status = OsRwLockRead(&(LockInternal->Lock));
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_timedrdlock (
- pthread_rwlock_t *Lock,
- const struct timespec *AbsoluteTimeout
- )
- /*++
- Routine Description:
- This routine acquires the read/write lock for read access just like the
- read lock function, except that this function will return after the
- specified deadline if the lock could not be acquired.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- AbsoluteTimeout - Supplies a pointer to the absolute deadline after which
- this function should give up and return failure.
- Return Value:
- 0 on success.
- ETIMEDOUT if the operation timed out. This thread will not own the lock.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- ULONG TimeoutInMilliseconds;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- if (AbsoluteTimeout != NULL) {
- TimeoutInMilliseconds =
- ClpConvertAbsoluteTimespecToRelativeMilliseconds(AbsoluteTimeout,
- CLOCK_REALTIME);
- } else {
- TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
- }
- Status = OsRwLockReadTimed(&(LockInternal->Lock), TimeoutInMilliseconds);
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_tryrdlock (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine performs a single attempt at acquiring the lock for read
- access.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Status = OsRwLockTryRead(&(LockInternal->Lock));
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_wrlock (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine acquires the read/write lock for write access. The lock can
- only be acquired for write access if there are no readers and no other
- writers.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Status = OsRwLockWrite(&(LockInternal->Lock));
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_timedwrlock (
- pthread_rwlock_t *Lock,
- const struct timespec *AbsoluteTimeout
- )
- /*++
- Routine Description:
- This routine acquires the read/write lock for write access just like the
- write lock function, except that this function will return after the
- specified deadline if the lock could not be acquired.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- AbsoluteTimeout - Supplies a pointer to the absolute deadline after which
- this function should give up and return failure.
- Return Value:
- 0 on success.
- ETIMEDOUT if the operation timed out. This thread will not own the lock.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- ULONG TimeoutInMilliseconds;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- if (AbsoluteTimeout != NULL) {
- TimeoutInMilliseconds =
- ClpConvertAbsoluteTimespecToRelativeMilliseconds(AbsoluteTimeout,
- CLOCK_REALTIME);
- } else {
- TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
- }
- Status = OsRwLockWriteTimed(&(LockInternal->Lock), TimeoutInMilliseconds);
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_trywrlock (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine performs a single attempt at acquiring the lock for write
- access.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Status = OsRwLockTryWrite(&(LockInternal->Lock));
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlock_unlock (
- pthread_rwlock_t *Lock
- )
- /*++
- Routine Description:
- This routine unlocks a read/write lock that's been acquired by this thread
- for either read or write.
- Arguments:
- Lock - Supplies a pointer to the read/write lock.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK LockInternal;
- KSTATUS Status;
- LockInternal = (PPTHREAD_RWLOCK)Lock;
- Status = OsRwLockUnlock(&(LockInternal->Lock));
- if (Status == STATUS_SUCCESS) {
- return Status;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- PTHREAD_API
- int
- pthread_rwlockattr_init (
- pthread_rwlockattr_t *Attribute
- )
- /*++
- Routine Description:
- This routine initializes a read/write lock attribute structure.
- Arguments:
- Attribute - Supplies a pointer to the read/write lock attribute.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
- AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
- AttributeInternal->Flags = 0;
- return 0;
- }
- PTHREAD_API
- int
- pthread_rwlockattr_destroy (
- pthread_rwlockattr_t *Attribute
- )
- /*++
- Routine Description:
- This routine destroys a read/write lock attribute structure.
- Arguments:
- Attribute - Supplies a pointer to the read/write lock attribute.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
- AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
- AttributeInternal->Flags = -1;
- return 0;
- }
- PTHREAD_API
- int
- pthread_rwlockattr_getpshared (
- const pthread_rwlockattr_t *Attribute,
- int *Shared
- )
- /*++
- Routine Description:
- This routine reads the shared attribute from a read/write lock attributes
- structure.
- Arguments:
- Attribute - Supplies a pointer to the read/write lock attribute.
- Shared - Supplies a pointer where the shared attribute of the lock will be
- returned on success. See PTHREAD_PROCESS_* definitions.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
- AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
- *Shared = PTHREAD_PROCESS_PRIVATE;
- if ((AttributeInternal->Flags & OS_RWLOCK_SHARED) != 0) {
- *Shared = PTHREAD_PROCESS_SHARED;
- }
- return 0;
- }
- PTHREAD_API
- int
- pthread_rwlockattr_setpshared (
- pthread_rwlockattr_t *Attribute,
- int Shared
- )
- /*++
- Routine Description:
- This routine sets the shared attribute in a read/write lock attributes
- structure.
- Arguments:
- Attribute - Supplies a pointer to the read/write lock attribute.
- Shared - Supplies the new shared value to set. See PTHREAD_PROCESS_*
- definitions.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PPTHREAD_RWLOCK_ATTRIBUTE AttributeInternal;
- AttributeInternal = (PPTHREAD_RWLOCK_ATTRIBUTE)Attribute;
- if (Shared == PTHREAD_PROCESS_PRIVATE) {
- AttributeInternal->Flags &= ~OS_RWLOCK_SHARED;
- } else if (Shared == PTHREAD_PROCESS_SHARED) {
- AttributeInternal->Flags |= OS_RWLOCK_SHARED;
- } else {
- return EINVAL;
- }
- return 0;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|