Return to rwlock.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / threading / windows |
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: }