1 /* posix-lock.c - GPGRT lock functions for POSIX systems
2 Copyright (C) 2005-2009 Free Software Foundation, Inc.
3 Copyright (C) 2014 g10 Code GmbH
5 This file is part of libgpg-error.
7 libgpg-error is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 libgpg-error is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 Parts of the code, in particular use_pthreads_p, are based on code
21 from gettext, written by Bruno Haible <bruno@clisp.org>, 2005.
28 #ifdef HAVE_W32_SYSTEM
29 # error This module may not be build for Windows.
41 #include "gpg-error.h"
43 #include "posix-lock-obj.h"
47 # if USE_POSIX_THREADS_WEAK
48 /* On ELF systems it is easy to use pthreads using weak
49 references. Take care not to test the address of a weak
50 referenced function we actually use; some GCC versions have a
51 bug were &foo != NULL is always evaluated to true in PIC mode. */
52 # pragma weak pthread_cancel
53 # pragma weak pthread_mutex_init
54 # pragma weak pthread_mutex_lock
55 # pragma weak pthread_mutex_unlock
56 # pragma weak pthread_mutex_destroy
57 # if ! PTHREAD_IN_USE_DETECTION_HARD
58 # define use_pthread_p() (!!pthread_cancel)
60 # else /*!USE_POSIX_THREADS_WEAK*/
61 # if ! PTHREAD_IN_USE_DETECTION_HARD
62 # define use_pthread_p() (1)
64 # endif /*!USE_POSIX_THREADS_WEAK*/
65 # if PTHREAD_IN_USE_DETECTION_HARD
66 /* The function to be executed by a dummy thread. */
68 dummy_thread_func (void *arg)
77 static int result; /* 1: linked with -lpthread, 0: only with libc */
83 if (pthread_create (&thread, NULL, dummy_thread_func, NULL))
84 result = 0; /* Thread creation failed. */
87 /* Thread creation works. */
89 if (pthread_join (thread, &retval) != 0)
97 #endif /*PTHREAD_IN_USE_DETECTION_HARD*/
98 #endif /*USE_POSIX_THREADS*/
102 static _gpgrt_lock_t *
103 get_lock_object (gpgrt_lock_t *lockhd)
105 _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
107 if (lock->vers != LOCK_ABI_VERSION)
109 if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
117 gpgrt_lock_init (gpgrt_lock_t *lockhd)
119 _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
122 /* If VERS is zero we assume that no static initialization has been
123 done, so we setup our ABI version right here. The caller might
124 have called us to test whether lock support is at all available. */
127 if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
129 lock->vers = LOCK_ABI_VERSION;
131 else /* Run the usual check. */
132 lock = get_lock_object (lockhd);
134 #if USE_POSIX_THREADS
137 rc = pthread_mutex_init (&lock->u.mtx, NULL);
139 rc = gpg_err_code_from_errno (rc);
142 rc = 0; /* Threads are not used. */
143 #else /* Unknown thread system. */
144 rc = GPG_ERR_NOT_IMPLEMENTED;
145 #endif /* Unknown thread system. */
152 gpgrt_lock_lock (gpgrt_lock_t *lockhd)
154 _gpgrt_lock_t *lock = get_lock_object (lockhd);
157 #if USE_POSIX_THREADS
160 rc = pthread_mutex_lock (&lock->u.mtx);
162 rc = gpg_err_code_from_errno (rc);
165 rc = 0; /* Threads are not used. */
166 #else /* Unknown thread system. */
167 rc = GPG_ERR_NOT_IMPLEMENTED;
168 #endif /* Unknown thread system. */
175 gpgrt_lock_unlock (gpgrt_lock_t *lockhd)
177 _gpgrt_lock_t *lock = get_lock_object (lockhd);
180 #if USE_POSIX_THREADS
183 rc = pthread_mutex_unlock (&lock->u.mtx);
185 rc = gpg_err_code_from_errno (rc);
188 rc = 0; /* Threads are not used. */
189 #else /* Unknown thread system. */
190 rc = GPG_ERR_NOT_IMPLEMENTED;
191 #endif /* Unknown thread system. */
197 /* Note: Use this function only if no other thread holds or waits for
200 gpgrt_lock_destroy (gpgrt_lock_t *lockhd)
202 _gpgrt_lock_t *lock = get_lock_object (lockhd);
205 #if USE_POSIX_THREADS
208 rc = pthread_mutex_destroy (&lock->u.mtx);
210 rc = gpg_err_code_from_errno (rc);
213 /* Re-init the mutex so that it can be re-used. */
214 gpgrt_lock_t tmp = GPGRT_LOCK_INITIALIZER;
215 memcpy (lockhd, &tmp, sizeof tmp);
219 rc = 0; /* Threads are not used. */
220 #else /* Unknown thread system. */
221 rc = GPG_ERR_NOT_IMPLEMENTED;
222 #endif /* Unknown thread system. */