cyclonedds/src/os/src/windows/os_platform_sync.c
Jeroen Koekkoek ac020f62f7 Add read-write locks for POSIX
Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
2018-11-30 23:32:26 +01:00

221 lines
4.6 KiB
C

/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "os/os.h"
void os_mutexInit(
_Out_ os_mutex *mutex)
{
assert(mutex != NULL);
InitializeSRWLock(&mutex->lock);
}
void os_mutexDestroy(
_Inout_ _Post_invalid_ os_mutex *mutex)
{
assert(mutex != NULL);
}
_Acquires_nonreentrant_lock_(&mutex->lock)
void os_mutexLock(
_Inout_ os_mutex *mutex)
{
assert(mutex != NULL);
AcquireSRWLockExclusive(&mutex->lock);
}
_Check_return_
_When_(return == os_resultSuccess, _Acquires_nonreentrant_lock_(&mutex->lock))
os_result os_mutexLock_s(
_Inout_ os_mutex *mutex)
{
os_mutexLock(mutex);
return os_resultSuccess;
}
_Check_return_
_When_(return == os_resultSuccess, _Acquires_nonreentrant_lock_(&mutex->lock))
os_result
os_mutexTryLock(
_Inout_ os_mutex *mutex)
{
assert(mutex != NULL);
return TryAcquireSRWLockExclusive(&mutex->lock) ? os_resultSuccess : os_resultBusy;
}
_Releases_nonreentrant_lock_(&mutex->lock)
void os_mutexUnlock(
_Inout_ os_mutex *mutex)
{
assert(mutex != NULL);
ReleaseSRWLockExclusive(&mutex->lock);
}
void os_condInit(
_Out_ os_cond *cond,
_In_ os_mutex *dummymtx)
{
assert(cond != NULL);
assert(dummymtx != NULL);
(void)dummymtx;
InitializeConditionVariable(&cond->cond);
}
void os_condDestroy(
_Inout_ _Post_invalid_ os_cond *cond)
{
assert(cond != NULL);
}
void os_condWait(os_cond *cond, os_mutex *mutex)
{
assert(cond != NULL);
assert(mutex != NULL);
if (!SleepConditionVariableSRW(&cond->cond, &mutex->lock, INFINITE, 0)) {
abort();
}
}
os_result os_condTimedWait(os_cond *cond, os_mutex *mutex, const os_time *time)
{
DWORD timems;
assert(cond != NULL);
assert(mutex != NULL);
timems = time->tv_sec * 1000 + (time->tv_nsec + 999999999) / 1000000;
if (SleepConditionVariableSRW(&cond->cond, &mutex->lock, timems, 0)) {
return os_resultSuccess;
} else if (GetLastError() != ERROR_TIMEOUT) {
abort();
} else if (timems != INFINITE) {
return os_resultTimeout;
} else {
return os_resultSuccess;
}
}
void os_condSignal(os_cond *cond)
{
assert(cond != NULL);
WakeConditionVariable(&cond->cond);
}
void os_condBroadcast(os_cond *cond)
{
assert(cond != NULL);
WakeAllConditionVariable(&cond->cond);
}
void os_rwlockInit(_Out_ os_rwlock *rwlock)
{
assert(rwlock);
InitializeSRWLock(&rwlock->lock);
rwlock->state = 0;
}
void os_rwlockDestroy(_Inout_ _Post_invalid_ os_rwlock *rwlock)
{
assert(rwlock);
}
void os_rwlockRead(os_rwlock *rwlock)
{
assert(rwlock);
AcquireSRWLockShared(&rwlock->lock);
rwlock->state = 1;
}
void os_rwlockWrite(os_rwlock *rwlock)
{
assert(rwlock);
AcquireSRWLockExclusive(&rwlock->lock);
rwlock->state = -1;
}
os_result os_rwlockTryRead(os_rwlock *rwlock)
{
assert(rwlock);
if (TryAcquireSRWLockShared(&rwlock->lock)) {
rwlock->state = 1;
return os_resultSuccess;
}
return os_resultBusy;
}
os_result os_rwlockTryWrite(os_rwlock *rwlock)
{
assert(rwlock);
if (TryAcquireSRWLockExclusive(&rwlock->lock)) {
rwlock->state = -1;
return os_resultSuccess;
}
return os_resultBusy;
}
void os_rwlockUnlock(os_rwlock *rwlock)
{
assert(rwlock);
assert(rwlock->state != 0);
if (rwlock->state > 0) {
ReleaseSRWLockShared(&rwlock->lock);
} else {
ReleaseSRWLockExclusive(&rwlock->lock);
}
}
struct os__onceWrapper {
os_once_fn init_fn;
};
static BOOL WINAPI
os__onceWrapper(
_Inout_ PINIT_ONCE InitOnce,
_Inout_opt_ PVOID Parameter,
_Outptr_opt_result_maybenull_ PVOID *Context)
{
struct os__onceWrapper *wrap = (struct os__onceWrapper *) Parameter;
/* Only to be invoked from os_once, so assume inputs to be as
* expected instead of implementing checks officially needed to
* fulfill SAL. */
_Analysis_assume_(wrap);
_Analysis_assume_(Context == NULL);
wrap->init_fn();
return TRUE;
}
void
os_once(
_Inout_ os_once_t *control,
_In_ os_once_fn init_fn)
{
struct os__onceWrapper wrap = { .init_fn = init_fn };
(void) InitOnceExecuteOnce(control, &os__onceWrapper, &wrap, NULL);
}