th-lock.c revision 296465
1/* crypto/threads/th-lock.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62#include <errno.h> 63#ifdef LINUX 64# include <typedefs.h> 65#endif 66#ifdef OPENSSL_SYS_WIN32 67# include <windows.h> 68#endif 69#ifdef SOLARIS 70# include <synch.h> 71# include <thread.h> 72#endif 73#ifdef IRIX 74# include <ulocks.h> 75# include <sys/prctl.h> 76#endif 77#ifdef PTHREADS 78# include <pthread.h> 79#endif 80#include <openssl/lhash.h> 81#include <openssl/crypto.h> 82#include <openssl/buffer.h> 83#include "../../e_os.h" 84#include <openssl/x509.h> 85#include <openssl/ssl.h> 86#include <openssl/err.h> 87 88void CRYPTO_thread_setup(void); 89void CRYPTO_thread_cleanup(void); 90 91static void irix_locking_callback(int mode, int type, char *file, int line); 92static void solaris_locking_callback(int mode, int type, char *file, 93 int line); 94static void win32_locking_callback(int mode, int type, char *file, int line); 95static void pthreads_locking_callback(int mode, int type, char *file, 96 int line); 97 98static unsigned long irix_thread_id(void); 99static unsigned long solaris_thread_id(void); 100static unsigned long pthreads_thread_id(void); 101 102/*- 103 * usage: 104 * CRYPTO_thread_setup(); 105 * application code 106 * CRYPTO_thread_cleanup(); 107 */ 108 109#define THREAD_STACK_SIZE (16*1024) 110 111#ifdef OPENSSL_SYS_WIN32 112 113static HANDLE *lock_cs; 114 115void CRYPTO_thread_setup(void) 116{ 117 int i; 118 119 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE)); 120 for (i = 0; i < CRYPTO_num_locks(); i++) { 121 lock_cs[i] = CreateMutex(NULL, FALSE, NULL); 122 } 123 124 CRYPTO_set_locking_callback((void (*)(int, int, char *, int)) 125 win32_locking_callback); 126 /* id callback defined */ 127 return (1); 128} 129 130static void CRYPTO_thread_cleanup(void) 131{ 132 int i; 133 134 CRYPTO_set_locking_callback(NULL); 135 for (i = 0; i < CRYPTO_num_locks(); i++) 136 CloseHandle(lock_cs[i]); 137 OPENSSL_free(lock_cs); 138} 139 140void win32_locking_callback(int mode, int type, char *file, int line) 141{ 142 if (mode & CRYPTO_LOCK) { 143 WaitForSingleObject(lock_cs[type], INFINITE); 144 } else { 145 ReleaseMutex(lock_cs[type]); 146 } 147} 148 149#endif /* OPENSSL_SYS_WIN32 */ 150 151#ifdef SOLARIS 152 153# define USE_MUTEX 154 155# ifdef USE_MUTEX 156static mutex_t *lock_cs; 157# else 158static rwlock_t *lock_cs; 159# endif 160static long *lock_count; 161 162void CRYPTO_thread_setup(void) 163{ 164 int i; 165 166# ifdef USE_MUTEX 167 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t)); 168# else 169 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(rwlock_t)); 170# endif 171 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); 172 for (i = 0; i < CRYPTO_num_locks(); i++) { 173 lock_count[i] = 0; 174# ifdef USE_MUTEX 175 mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL); 176# else 177 rwlock_init(&(lock_cs[i]), USYNC_THREAD, NULL); 178# endif 179 } 180 181 CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id); 182 CRYPTO_set_locking_callback((void (*)())solaris_locking_callback); 183} 184 185void CRYPTO_thread_cleanup(void) 186{ 187 int i; 188 189 CRYPTO_set_locking_callback(NULL); 190 for (i = 0; i < CRYPTO_num_locks(); i++) { 191# ifdef USE_MUTEX 192 mutex_destroy(&(lock_cs[i])); 193# else 194 rwlock_destroy(&(lock_cs[i])); 195# endif 196 } 197 OPENSSL_free(lock_cs); 198 OPENSSL_free(lock_count); 199} 200 201void solaris_locking_callback(int mode, int type, char *file, int line) 202{ 203# if 0 204 fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n", 205 CRYPTO_thread_id(), 206 (mode & CRYPTO_LOCK) ? "l" : "u", 207 (type & CRYPTO_READ) ? "r" : "w", file, line); 208# endif 209 210# if 0 211 if (CRYPTO_LOCK_SSL_CERT == type) 212 fprintf(stderr, "(t,m,f,l) %ld %d %s %d\n", 213 CRYPTO_thread_id(), mode, file, line); 214# endif 215 if (mode & CRYPTO_LOCK) { 216# ifdef USE_MUTEX 217 mutex_lock(&(lock_cs[type])); 218# else 219 if (mode & CRYPTO_READ) 220 rw_rdlock(&(lock_cs[type])); 221 else 222 rw_wrlock(&(lock_cs[type])); 223# endif 224 lock_count[type]++; 225 } else { 226# ifdef USE_MUTEX 227 mutex_unlock(&(lock_cs[type])); 228# else 229 rw_unlock(&(lock_cs[type])); 230# endif 231 } 232} 233 234unsigned long solaris_thread_id(void) 235{ 236 unsigned long ret; 237 238 ret = (unsigned long)thr_self(); 239 return (ret); 240} 241#endif /* SOLARIS */ 242 243#ifdef IRIX 244/* I don't think this works..... */ 245 246static usptr_t *arena; 247static usema_t **lock_cs; 248 249void CRYPTO_thread_setup(void) 250{ 251 int i; 252 char filename[20]; 253 254 strcpy(filename, "/tmp/mttest.XXXXXX"); 255 mktemp(filename); 256 257 usconfig(CONF_STHREADIOOFF); 258 usconfig(CONF_STHREADMALLOCOFF); 259 usconfig(CONF_INITUSERS, 100); 260 usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); 261 arena = usinit(filename); 262 unlink(filename); 263 264 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *)); 265 for (i = 0; i < CRYPTO_num_locks(); i++) { 266 lock_cs[i] = usnewsema(arena, 1); 267 } 268 269 CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id); 270 CRYPTO_set_locking_callback((void (*)())irix_locking_callback); 271} 272 273void CRYPTO_thread_cleanup(void) 274{ 275 int i; 276 277 CRYPTO_set_locking_callback(NULL); 278 for (i = 0; i < CRYPTO_num_locks(); i++) { 279 char buf[10]; 280 281 sprintf(buf, "%2d:", i); 282 usdumpsema(lock_cs[i], stdout, buf); 283 usfreesema(lock_cs[i], arena); 284 } 285 OPENSSL_free(lock_cs); 286} 287 288void irix_locking_callback(int mode, int type, char *file, int line) 289{ 290 if (mode & CRYPTO_LOCK) { 291 uspsema(lock_cs[type]); 292 } else { 293 usvsema(lock_cs[type]); 294 } 295} 296 297unsigned long irix_thread_id(void) 298{ 299 unsigned long ret; 300 301 ret = (unsigned long)getpid(); 302 return (ret); 303} 304#endif /* IRIX */ 305 306/* Linux and a few others */ 307#ifdef PTHREADS 308 309static pthread_mutex_t *lock_cs; 310static long *lock_count; 311 312void CRYPTO_thread_setup(void) 313{ 314 int i; 315 316 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); 317 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); 318 for (i = 0; i < CRYPTO_num_locks(); i++) { 319 lock_count[i] = 0; 320 pthread_mutex_init(&(lock_cs[i]), NULL); 321 } 322 323 CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); 324 CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); 325} 326 327void thread_cleanup(void) 328{ 329 int i; 330 331 CRYPTO_set_locking_callback(NULL); 332 for (i = 0; i < CRYPTO_num_locks(); i++) { 333 pthread_mutex_destroy(&(lock_cs[i])); 334 } 335 OPENSSL_free(lock_cs); 336 OPENSSL_free(lock_count); 337} 338 339void pthreads_locking_callback(int mode, int type, char *file, int line) 340{ 341# if 0 342 fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n", 343 CRYPTO_thread_id(), 344 (mode & CRYPTO_LOCK) ? "l" : "u", 345 (type & CRYPTO_READ) ? "r" : "w", file, line); 346# endif 347# if 0 348 if (CRYPTO_LOCK_SSL_CERT == type) 349 fprintf(stderr, "(t,m,f,l) %ld %d %s %d\n", 350 CRYPTO_thread_id(), mode, file, line); 351# endif 352 if (mode & CRYPTO_LOCK) { 353 pthread_mutex_lock(&(lock_cs[type])); 354 lock_count[type]++; 355 } else { 356 pthread_mutex_unlock(&(lock_cs[type])); 357 } 358} 359 360unsigned long pthreads_thread_id(void) 361{ 362 unsigned long ret; 363 364 ret = (unsigned long)pthread_self(); 365 return (ret); 366} 367 368#endif /* PTHREADS */ 369