Annotation of embedaddon/strongswan/src/libstrongswan/threading/windows/rwlock.c, revision 1.1.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>