1 /* w32-lock.c - GPGRT lock functions for Windows
2 Copyright (C) 2014 g10 Code GmbH
4 This file is part of libgpg-error.
6 libgpg-error is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License
8 as published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 libgpg-error is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #ifndef HAVE_W32_SYSTEM
25 # error This module may only be build for Windows.
32 #include <gpg-error.h>
33 #define WIN32_LEAN_AND_MEAN
37 #include "w32-lock-obj.h"
40 static _gpgrt_lock_t *
41 get_lock_object (gpgrt_lock_t *lockhd)
43 _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
45 if (lock->vers != LOCK_ABI_VERSION)
53 gpgrt_lock_init (gpgrt_lock_t *lockhd)
55 _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
57 /* If VERS is zero we assume that no static initialization has been
58 done, so we setup our ABI version right here. The caller might
59 have called us to test whether lock support is at all available. */
62 if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
64 lock->vers = LOCK_ABI_VERSION;
66 else /* Run the usual check. */
68 lock = get_lock_object (lockhd);
69 if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
73 InitializeCriticalSection (&lock->csec);
79 gpgrt_lock_lock (gpgrt_lock_t *lockhd)
81 _gpgrt_lock_t *lock = get_lock_object (lockhd);
85 if (!InterlockedIncrement (&lock->started))
87 /* The new value of started is 0. Because the initial value
88 if the variable was -1 we known that this thread is the
89 first who needs this lock. Thus we initialize now. All
90 other threads won't get 0 back from InterlockedIncrement
91 and thus fall into the wait loop below. We ignore that
92 STARTED may in theory overflow if this thread starves for
94 gpgrt_lock_init (lockhd);
98 while (!lock->initdone)
103 EnterCriticalSection (&lock->csec);
109 gpgrt_lock_unlock (gpgrt_lock_t *lockhd)
111 _gpgrt_lock_t *lock = get_lock_object (lockhd);
114 return GPG_ERR_INV_LOCK_OBJ;
115 LeaveCriticalSection (&lock->csec);
120 /* Note: Use this function only if no other thread holds or waits for
123 gpgrt_lock_destroy (gpgrt_lock_t *lockhd)
125 _gpgrt_lock_t *lock = get_lock_object (lockhd);
128 return GPG_ERR_INV_LOCK_OBJ;
129 DeleteCriticalSection (&lock->csec);