big svn cleanup
[anytun.git] / src / openvpn / thread.c
blobdc246c1c71f697fd61ba00e6fc6cd2298d0afa0e
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef WIN32
26 #include "config-win32.h"
27 #else
28 #include "config.h"
29 #endif
31 #include "syshead.h"
33 #ifdef USE_PTHREAD
35 #include "thread.h"
36 #include "buffer.h"
37 #include "common.h"
38 #include "error.h"
39 #include "crypto.h"
41 #include "memdbg.h"
43 static struct sparse_mutex *ssl_mutex; /* GLOBAL */
45 static void
46 ssl_pthreads_locking_callback (int mode, int type, char *file, int line)
48 dmsg (D_OPENSSL_LOCK, "SSL LOCK thread=%4lu mode=%s lock=%s %s:%d",
49 CRYPTO_thread_id (),
50 (mode & CRYPTO_LOCK) ? "l" : "u",
51 (type & CRYPTO_READ) ? "r" : "w", file, line);
53 if (mode & CRYPTO_LOCK)
54 pthread_mutex_lock (&ssl_mutex[type].mutex);
55 else
56 pthread_mutex_unlock (&ssl_mutex[type].mutex);
59 static unsigned long
60 ssl_pthreads_thread_id (void)
62 unsigned long ret;
64 ret = (unsigned long) pthread_self ();
65 return ret;
68 static void
69 ssl_thread_setup (void)
71 int i;
73 #error L_MSG needs to be initialized as a recursive mutex
75 ssl_mutex = OPENSSL_malloc (CRYPTO_num_locks () * sizeof (struct sparse_mutex));
76 for (i = 0; i < CRYPTO_num_locks (); i++)
77 pthread_mutex_init (&ssl_mutex[i].mutex, NULL);
79 CRYPTO_set_id_callback ((unsigned long (*)(void)) ssl_pthreads_thread_id);
80 CRYPTO_set_locking_callback ((void (*)(int, int, const char*, int)) ssl_pthreads_locking_callback);
83 static void
84 ssl_thread_cleanup (void)
86 int i;
88 dmsg (D_OPENSSL_LOCK, "SSL LOCK cleanup");
89 CRYPTO_set_locking_callback (NULL);
90 for (i = 0; i < CRYPTO_num_locks (); i++)
91 pthread_mutex_destroy (&ssl_mutex[i].mutex);
92 OPENSSL_free (ssl_mutex);
95 struct sparse_mutex mutex_array[N_MUTEXES]; /* GLOBAL */
96 bool pthread_initialized; /* GLOBAL */
98 openvpn_thread_t
99 openvpn_thread_create (void *(*start_routine) (void *), void* arg)
101 openvpn_thread_t ret;
102 ASSERT (pthread_initialized);
103 ASSERT (!pthread_create (&ret, NULL, start_routine, arg));
104 dmsg (D_THREAD_DEBUG, "CREATE THREAD ID=%lu", (unsigned long)ret);
105 return ret;
108 void
109 openvpn_thread_join (openvpn_thread_t id)
111 ASSERT (pthread_initialized);
112 pthread_join (id, NULL);
115 void
116 openvpn_thread_init ()
118 int i;
120 ASSERT (!pthread_initialized);
122 msg (M_INFO, "PTHREAD support initialized");
124 /* initialize OpenSSL library locking */
125 #if defined(USE_CRYPTO) && defined(USE_SSL)
126 ssl_thread_setup();
127 #endif
129 /* initialize static mutexes */
130 for (i = 0; i < N_MUTEXES; i++)
131 ASSERT (!pthread_mutex_init (&mutex_array[i].mutex, NULL));
133 msg_thread_init ();
135 pthread_initialized = true;
138 void
139 openvpn_thread_cleanup ()
141 if (pthread_initialized)
143 int i;
145 pthread_initialized = false;
147 /* cleanup OpenSSL library locking */
148 #if defined(USE_CRYPTO) && defined(USE_SSL)
149 ssl_thread_cleanup();
150 #endif
152 /* destroy static mutexes */
153 for (i = 0; i < N_MUTEXES; i++)
154 ASSERT (!pthread_mutex_destroy (&mutex_array[i].mutex));
156 msg_thread_uninit ();
160 #else
161 static void dummy(void) {}
162 #endif