2003-05-21 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / src / ath-pthread.c
1 /* ath-pthread.c - pthread module for self-adapting thread-safeness library
2  *      Copyright (C) 2002 g10 Code GmbH
3  *      Copyright (C) 2002 Free Software Foundation, Inc.
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <pthread.h>
25
26 #include "ath.h"
27
28 /* Need to include pthread_create in our check, as the GNU C library
29    has the pthread_mutex_* functions in their public interface.  */
30 #pragma weak pthread_create
31 #pragma weak pthread_mutex_init
32 #pragma weak pthread_mutex_destroy
33 #pragma weak pthread_mutex_lock
34 #pragma weak pthread_mutex_unlock
35
36 /* The lock we take while checking for lazy lock initialization.  */
37 static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER;
38
39 /* Initialize the mutex *PRIV.  If JUST_CHECK is true, only do this if
40    it is not already initialized.  */
41 static int
42 mutex_pthread_init (void **priv, int just_check)
43 {
44   int err = 0;
45
46   if (just_check)
47     pthread_mutex_lock (&check_init_lock);
48   if (!*priv || !just_check)
49     {
50       pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
51       if (!lock)
52         err = ENOMEM;
53       if (!err)
54         {
55           err = pthread_mutex_init (lock, NULL);
56           if (err)
57             free (lock);
58           else
59             *priv = lock;
60         }
61     }
62   if (just_check)
63     pthread_mutex_unlock (&check_init_lock);
64   return err;
65 }
66
67
68 static int
69 mutex_pthread_destroy (void *priv)
70 {
71   int err = pthread_mutex_destroy ((pthread_mutex_t *) priv);
72   free (priv);
73   return err;
74 }
75
76
77 static struct ath_ops ath_pthread_ops =
78   {
79     mutex_pthread_init,
80     mutex_pthread_destroy,
81     (int (*) (void *)) pthread_mutex_lock,
82     (int (*) (void *)) pthread_mutex_unlock,
83     NULL,       /* read */
84     NULL,       /* write */
85     NULL,       /* select */
86     NULL        /* waitpid */
87   };
88
89
90 struct ath_ops *
91 ath_pthread_available (void)
92 {
93   /* Need to include pthread_create in our check, as the GNU C library
94      has the pthread_mutex_* functions in their public interface.  */
95   if (pthread_create
96       && pthread_mutex_init && pthread_mutex_destroy
97       && pthread_mutex_lock && pthread_mutex_unlock)
98     return &ath_pthread_ops;
99   else
100     return 0;
101 }