Annotation of embedaddon/strongswan/src/libstrongswan/threading/windows/rwlock.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2013 Martin Willi
! 3: * Copyright (C) 2013 revosec AG
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "thread.h"
! 17:
! 18: #include <utils/debug.h>
! 19: #include <threading/rwlock.h>
! 20: #include <threading/rwlock_condvar.h>
! 21: #include <threading/thread_value.h>
! 22:
! 23: typedef struct private_rwlock_t private_rwlock_t;
! 24: typedef struct private_rwlock_condvar_t private_rwlock_condvar_t;
! 25:
! 26: /**
! 27: * private data of rwlock
! 28: */
! 29: struct private_rwlock_t {
! 30:
! 31: /**
! 32: * public functions
! 33: */
! 34: rwlock_t public;
! 35:
! 36: /**
! 37: * wrapped rwlock
! 38: */
! 39: SRWLOCK srw;
! 40:
! 41: /**
! 42: * Thread specific shared lock count
! 43: */
! 44: thread_value_t *shared;
! 45: };
! 46:
! 47: /**
! 48: * private data of condvar
! 49: */
! 50: struct private_rwlock_condvar_t {
! 51:
! 52: /**
! 53: * public interface
! 54: */
! 55: rwlock_condvar_t public;
! 56:
! 57: /**
! 58: * condition variable
! 59: */
! 60: CONDITION_VARIABLE cv;
! 61: };
! 62:
! 63: METHOD(rwlock_t, read_lock, void,
! 64: private_rwlock_t *this)
! 65: {
! 66: uintptr_t count;
! 67:
! 68: /* Recursive read locks are not supported. Use a thread specific
! 69: * recursiveness counter. */
! 70:
! 71: count = (uintptr_t)this->shared->get(this->shared);
! 72: if (count == 0)
! 73: {
! 74: AcquireSRWLockShared(&this->srw);
! 75: }
! 76: this->shared->set(this->shared, (void*)(count + 1));
! 77: }
! 78:
! 79: METHOD(rwlock_t, write_lock, void,
! 80: private_rwlock_t *this)
! 81: {
! 82: AcquireSRWLockExclusive(&this->srw);
! 83: }
! 84:
! 85: METHOD(rwlock_t, try_write_lock, bool,
! 86: private_rwlock_t *this)
! 87: {
! 88: return TryAcquireSRWLockExclusive(&this->srw);
! 89: }
! 90:
! 91: METHOD(rwlock_t, unlock, void,
! 92: private_rwlock_t *this)
! 93: {
! 94: uintptr_t count;
! 95:
! 96: count = (uintptr_t)this->shared->get(this->shared);
! 97: switch (count)
! 98: {
! 99: case 0:
! 100: ReleaseSRWLockExclusive(&this->srw);
! 101: break;
! 102: case 1:
! 103: ReleaseSRWLockShared(&this->srw);
! 104: /* fall */
! 105: default:
! 106: this->shared->set(this->shared, (void*)(count - 1));
! 107: break;
! 108: }
! 109: }
! 110:
! 111: METHOD(rwlock_t, destroy, void,
! 112: private_rwlock_t *this)
! 113: {
! 114: this->shared->destroy(this->shared);
! 115: free(this);
! 116: }
! 117:
! 118: /*
! 119: * see header file
! 120: */
! 121: rwlock_t *rwlock_create(rwlock_type_t type)
! 122: {
! 123: private_rwlock_t *this;
! 124:
! 125: INIT(this,
! 126: .public = {
! 127: .read_lock = _read_lock,
! 128: .write_lock = _write_lock,
! 129: .try_write_lock = _try_write_lock,
! 130: .unlock = _unlock,
! 131: .destroy = _destroy,
! 132: },
! 133: .shared = thread_value_create(NULL),
! 134: );
! 135:
! 136: InitializeSRWLock(&this->srw);
! 137:
! 138: return &this->public;
! 139: }
! 140:
! 141: METHOD(rwlock_condvar_t, timed_wait, bool,
! 142: private_rwlock_condvar_t *this, rwlock_t *pubrwlock, u_int timeout)
! 143: {
! 144: private_rwlock_t *rwlock = (private_rwlock_t*)pubrwlock;
! 145: bool ret;
! 146:
! 147: thread_set_active_condvar(&this->cv);
! 148:
! 149: ret = SleepConditionVariableSRW(&this->cv, &rwlock->srw, timeout, 0);
! 150:
! 151: thread_set_active_condvar(NULL);
! 152:
! 153: return ret == 0;
! 154: }
! 155:
! 156: METHOD(rwlock_condvar_t, wait_, void,
! 157: private_rwlock_condvar_t *this, rwlock_t *lock)
! 158: {
! 159: timed_wait(this, lock, INFINITE);
! 160: }
! 161:
! 162: METHOD(rwlock_condvar_t, timed_wait_abs, bool,
! 163: private_rwlock_condvar_t *this, rwlock_t *lock, timeval_t tv)
! 164: {
! 165: DWORD timeout;
! 166: timeval_t now, diff;
! 167:
! 168: time_monotonic(&now);
! 169: if (timercmp(&now, &tv, >))
! 170: {
! 171: return TRUE;
! 172: }
! 173: timersub(&tv, &now, &diff);
! 174: timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000;
! 175:
! 176: return timed_wait(this, lock, timeout);
! 177: }
! 178:
! 179: METHOD(rwlock_condvar_t, signal_, void,
! 180: private_rwlock_condvar_t *this)
! 181: {
! 182: WakeConditionVariable(&this->cv);
! 183: }
! 184:
! 185: METHOD(rwlock_condvar_t, broadcast, void,
! 186: private_rwlock_condvar_t *this)
! 187: {
! 188: WakeAllConditionVariable(&this->cv);
! 189: }
! 190:
! 191: METHOD(rwlock_condvar_t, condvar_destroy, void,
! 192: private_rwlock_condvar_t *this)
! 193: {
! 194: free(this);
! 195: }
! 196:
! 197: /*
! 198: * see header file
! 199: */
! 200: rwlock_condvar_t *rwlock_condvar_create()
! 201: {
! 202: private_rwlock_condvar_t *this;
! 203:
! 204: INIT(this,
! 205: .public = {
! 206: .wait = _wait_,
! 207: .timed_wait = _timed_wait,
! 208: .timed_wait_abs = _timed_wait_abs,
! 209: .signal = _signal_,
! 210: .broadcast = _broadcast,
! 211: .destroy = _condvar_destroy,
! 212: },
! 213: );
! 214:
! 215: InitializeConditionVariable(&this->cv);
! 216:
! 217: return &this->public;
! 218: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>