Return to mutex.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/mutex.h> 20: #include <threading/condvar.h> 21: 22: typedef struct private_mutex_t private_mutex_t; 23: typedef struct private_condvar_t private_condvar_t; 24: 25: /** 26: * private data of mutex 27: */ 28: struct private_mutex_t { 29: 30: /** 31: * public functions 32: */ 33: mutex_t public; 34: 35: /** 36: * wrapped critical section 37: */ 38: CRITICAL_SECTION cs; 39: 40: /** 41: * Recursive lock count 42: */ 43: u_int times; 44: }; 45: 46: /** 47: * private data of condvar 48: */ 49: struct private_condvar_t { 50: 51: /** 52: * public functions 53: */ 54: condvar_t public; 55: 56: /** 57: * wrapped condition variable 58: */ 59: CONDITION_VARIABLE cv; 60: }; 61: 62: 63: METHOD(mutex_t, lock, void, 64: private_mutex_t *this) 65: { 66: EnterCriticalSection(&this->cs); 67: this->times++; 68: } 69: 70: METHOD(mutex_t, unlock, void, 71: private_mutex_t *this) 72: { 73: this->times--; 74: LeaveCriticalSection(&this->cs); 75: } 76: 77: METHOD(mutex_t, mutex_destroy, void, 78: private_mutex_t *this) 79: { 80: DeleteCriticalSection(&this->cs); 81: free(this); 82: } 83: 84: /* 85: * see header file 86: */ 87: mutex_t *mutex_create(mutex_type_t type) 88: { 89: private_mutex_t *this; 90: 91: INIT(this, 92: .public = { 93: .lock = _lock, 94: .unlock = _unlock, 95: .destroy = _mutex_destroy, 96: }, 97: ); 98: 99: /* CriticalSections are recursive, we use it for all mutex types. */ 100: InitializeCriticalSection(&this->cs); 101: 102: return &this->public; 103: } 104: 105: METHOD(condvar_t, timed_wait, bool, 106: private_condvar_t *this, mutex_t *pubmutex, u_int timeout) 107: { 108: private_mutex_t *mutex = (private_mutex_t*)pubmutex; 109: u_int times; 110: bool ret; 111: 112: thread_set_active_condvar(&this->cv); 113: 114: /* while a CriticalSection is recursive, waiting in a condvar releases 115: * only one mutex. So release (and reacquire) all locks except the last. */ 116: times = mutex->times; 117: while (mutex->times-- > 1) 118: { 119: LeaveCriticalSection(&mutex->cs); 120: } 121: 122: ret = SleepConditionVariableCS(&this->cv, &mutex->cs, timeout); 123: 124: while (++mutex->times < times) 125: { 126: EnterCriticalSection(&mutex->cs); 127: } 128: 129: thread_set_active_condvar(NULL); 130: 131: return ret == 0; 132: } 133: 134: METHOD(condvar_t, wait_, void, 135: private_condvar_t *this, mutex_t *mutex) 136: { 137: timed_wait(this, mutex, INFINITE); 138: } 139: 140: METHOD(condvar_t, timed_wait_abs, bool, 141: private_condvar_t *this, mutex_t *mutex, timeval_t tv) 142: { 143: DWORD timeout; 144: timeval_t now, diff; 145: 146: time_monotonic(&now); 147: if (timercmp(&now, &tv, >)) 148: { 149: return TRUE; 150: } 151: timersub(&tv, &now, &diff); 152: timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000; 153: 154: return timed_wait(this, mutex, timeout); 155: } 156: 157: METHOD(condvar_t, signal_, void, 158: private_condvar_t *this) 159: { 160: WakeConditionVariable(&this->cv); 161: } 162: 163: METHOD(condvar_t, broadcast, void, 164: private_condvar_t *this) 165: { 166: WakeAllConditionVariable(&this->cv); 167: } 168: 169: METHOD(condvar_t, condvar_destroy, void, 170: private_condvar_t *this) 171: { 172: free(this); 173: } 174: 175: /* 176: * see header file 177: */ 178: condvar_t *condvar_create(condvar_type_t type) 179: { 180: private_condvar_t *this; 181: 182: INIT(this, 183: .public = { 184: .wait = _wait_, 185: .timed_wait = _timed_wait, 186: .timed_wait_abs = _timed_wait_abs, 187: .signal = _signal_, 188: .broadcast = _broadcast, 189: .destroy = _condvar_destroy, 190: } 191: ); 192: 193: InitializeConditionVariable(&this->cv); 194: 195: return &this->public; 196: }