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