Completed switch to a simpler thread model.
[libgcrypt.git] / src / ath.c
1 /* ath.c - A Thread-safeness library.
2  *  Copyright (C) 2002, 2003, 2004, 2011 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
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/>.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #if USE_POSIX_THREADS_WEAK
28 # include <pthread.h>
29 #endif
30
31 #include "ath.h"
32
33
34 \f
35 /* On an ELF system it is easy to use pthreads using weak references.
36    Take care not to test the address of a weak referenced function we
37    actually use; some GCC versions have a bug were &foo != NULL is
38    always evaluated to true in PIC mode.  USING_PTHREAD_AS_DEFAULT is
39    used by ath_install to detect the default usage of pthread.  */
40 #if USE_POSIX_THREADS_WEAK
41 # pragma weak pthread_cancel
42 # pragma weak pthread_mutex_init
43 # pragma weak pthread_mutex_lock
44 # pragma weak pthread_mutex_unlock
45 # pragma weak pthread_mutex_destroy
46 #endif
47
48 /* For the dummy interface.  The MUTEX_NOTINIT value is used to check
49    that a mutex has been initialized.  Because its value is there is
50    no need to explicit initialized a mutex variable because it is
51    anyway static and we store a pointer to allocated memory there
52    after initialization.  The same thing works with other thread
53    models. */
54 #define MUTEX_NOTINIT   ((ath_mutex_t) 0)
55 #define MUTEX_UNLOCKED  ((ath_mutex_t) 1)
56 #define MUTEX_LOCKED    ((ath_mutex_t) 2)
57 #define MUTEX_DESTROYED ((ath_mutex_t) 3)
58
59
60 /* Return the thread type from the option field. */
61 #define GET_OPTION(a)    ((a) & 0xff)
62
63
64 \f
65 enum ath_thread_model {
66   ath_model_undefined = 0,
67   ath_model_none,          /* No thread support.  */
68   ath_model_pthreads_weak, /* POSIX threads using weak symbols.  */
69   ath_model_pthreads,      /* POSIX threads directly linked.  */
70   ath_model_w32            /* Microsoft Windows threads.  */
71 };
72
73
74 /* The thread model in use.  */
75 static enum ath_thread_model thread_model;
76
77
78 /* Initialize the ath subsystem.  This is called as part of the
79    Libgcrypt initialization.  It's purpose is to initialize the
80    locking system.  It returns 0 on sucess or an ERRNO value on error.
81    In the latter case it is not defined whether ERRNO was changed.
82
83    Note: This should be called as early as possible because it is not
84    always possible to detect the thread model to use while already
85    running multi threaded.  */
86 int
87 ath_init (void)
88 {
89   int err = 0;
90
91   if (thread_model)
92     return 0; /* Already initialized - no error.  */
93
94   if (0)
95     ;
96 #if USE_POSIX_THREADS_WEAK
97   else if (pthread_cancel)
98     {
99       thread_model = ath_model_pthreads_weak;
100     }
101 #endif
102   else
103     {
104       /* Assume a single threaded application.  */
105       thread_model = ath_model_none;
106     }
107
108   return err;
109 }
110
111
112 /* Return the used thread model as string for display purposes an if
113    R_MODEL is not null store its internal number at R_MODEL.  */
114 const char *
115 ath_get_model (int *r_model)
116 {
117   if (r_model)
118     *r_model = thread_model;
119   switch (thread_model)
120     {
121     case ath_model_undefined:     return "undefined";
122     case ath_model_none:          return "none";
123     case ath_model_pthreads_weak: return "pthread(weak)";
124     case ath_model_pthreads:      return "pthread";
125     case ath_model_w32:           return "w32";
126     default:                      return "?";
127     }
128 }
129
130
131 /* This function was used in old Libgcrypt versions (via
132    GCRYCTL_SET_THREAD_CBS) to register the thread callback functions.
133    It is not anymore required.  However to allow existing code to
134    continue to work, we keep this function and check that no user
135    defined callbacks are used and that the requested thread system
136    matches the one Libgcrypt is using.  */
137 gpg_err_code_t
138 ath_install (struct ath_ops *ath_ops)
139 {
140   unsigned int thread_option;
141
142   /* Check if the requested thread option is compatible to the
143      thread option we are already committed to.  */
144   thread_option = ath_ops? GET_OPTION (ath_ops->option) : 0;
145
146   /* Return an error if the requested thread model does not match the
147      configured one.  */
148   if (0)
149     ;
150 #if USE_POSIX_THREADS_WEAK
151   else if (thread_model == ath_model_pthreads_weak)
152     {
153       if (thread_option == ATH_THREAD_OPTION_PTHREAD)
154         return 0; /* Okay - compatible.  */
155     }
156 #endif /*USE_POSIX_THREADS_WEAK*/
157   else if (thread_option == ATH_THREAD_OPTION_DEFAULT)
158     return 0; /* No thread support requested.  */
159
160   return GPG_ERR_NOT_SUPPORTED;
161 }
162
163
164 /* Initialize a new mutex.  This function returns 0 on success or an
165    system error code (i.e. an ERRNO value).  ERRNO may or may not be
166    changed on error.  */
167 int
168 ath_mutex_init (ath_mutex_t *lock)
169 {
170   int err;
171
172   switch (thread_model)
173     {
174     case ath_model_none:
175       *lock = MUTEX_UNLOCKED;
176       err = 0;
177       break;
178
179 #if USE_POSIX_THREADS_WEAK
180     case ath_model_pthreads_weak:
181       {
182         pthread_mutex_t *plck;
183
184         plck = malloc (sizeof *plck);
185         if (!plck)
186           err = errno? errno : ENOMEM;
187         else
188           {
189             err = pthread_mutex_init (plck, NULL);
190             if (err)
191               free (plck);
192             else
193               *lock = (void*)plck;
194           }
195       }
196       break;
197 #endif /*USE_POSIX_THREADS_WEAK*/
198
199     default:
200       err = EINVAL;
201       break;
202     }
203
204   return err;
205 }
206
207
208 /* Destroy a mutex.  This function is a NOP if LOCK is NULL.  If the
209    mutex is still locked it can't be destroyed and the function
210    returns EBUSY.  ERRNO may or may not be changed on error.  */
211 int
212 ath_mutex_destroy (ath_mutex_t *lock)
213 {
214   int err;
215
216   if (!*lock)
217     return 0;
218
219   switch (thread_model)
220     {
221     case ath_model_none:
222       if (*lock != MUTEX_UNLOCKED)
223         err = EBUSY;
224       else
225         {
226           *lock = MUTEX_DESTROYED;
227           err = 0;
228         }
229       break;
230
231 #if USE_POSIX_THREADS_WEAK
232     case ath_model_pthreads_weak:
233       {
234         pthread_mutex_t *plck = (pthread_mutex_t*)lock;
235
236         err = pthread_mutex_destroy (plck);
237         if (!err)
238           {
239             free (plck);
240             lock = NULL;
241           }
242       }
243       break;
244 #endif /*USE_POSIX_THREADS_WEAK*/
245
246     default:
247       err = EINVAL;
248       break;
249     }
250
251   return err;
252 }
253
254
255 /* Lock the mutex LOCK.  On success the function returns 0; on error
256    an error code.  ERRNO may or may not be changed on error.  */
257 int
258 ath_mutex_lock (ath_mutex_t *lock)
259 {
260   int err;
261
262   switch (thread_model)
263     {
264     case ath_model_none:
265       if (*lock == MUTEX_NOTINIT)
266         err = EINVAL;
267       else if (*lock == MUTEX_UNLOCKED)
268         {
269           *lock = MUTEX_LOCKED;
270           err = 0;
271         }
272       else
273         err = EDEADLK;
274       break;
275
276 #if USE_POSIX_THREADS_WEAK
277     case ath_model_pthreads_weak:
278       err = pthread_mutex_lock ((pthread_mutex_t*)lock);
279       break;
280 #endif /*USE_POSIX_THREADS_WEAK*/
281
282     default:
283       err = EINVAL;
284       break;
285     }
286
287   return err;
288 }
289
290 /* Unlock the mutex LOCK.  On success the function returns 0; on error
291    an error code.  ERRNO may or may not be changed on error.  */
292 int
293 ath_mutex_unlock (ath_mutex_t *lock)
294 {
295   int err;
296
297   switch (thread_model)
298     {
299     case ath_model_none:
300       if (*lock == MUTEX_NOTINIT)
301         err = EINVAL;
302       else if (*lock == MUTEX_LOCKED)
303         {
304           *lock = MUTEX_UNLOCKED;
305           err = 0;
306         }
307       else
308         err = EPERM;
309       break;
310
311 #if USE_POSIX_THREADS_WEAK
312     case ath_model_pthreads_weak:
313       err = pthread_mutex_unlock ((pthread_mutex_t*)lock);
314       break;
315 #endif /*USE_POSIX_THREADS_WEAK*/
316
317     default:
318       err = EINVAL;
319       break;
320     }
321
322   return err;
323 }