th-lock.c revision 55714
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 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#include <openssl/lhash.h> 78#include <openssl/crypto.h> 79#include <openssl/buffer.h> 80#include <openssl/e_os.h> 81#include <openssl/x509.h> 82#include <openssl/ssl.h> 83#include <openssl/err.h> 84 85int CRYPTO_thread_setup(void); 86void CRYPTO_thread_cleanup(void); 87 88static void irix_locking_callback(int mode,int type,char *file,int line); 89static void solaris_locking_callback(int mode,int type,char *file,int line); 90static void win32_locking_callback(int mode,int type,char *file,int line); 91static void pthreads_locking_callback(int mode,int type,char *file,int line); 92 93static unsigned long irix_thread_id(void ); 94static unsigned long solaris_thread_id(void ); 95static unsigned long pthreads_thread_id(void ); 96 97/* usage: 98 * CRYPTO_thread_setup(); 99 * applicaion code 100 * CRYPTO_thread_cleanup(); 101 */ 102 103#define THREAD_STACK_SIZE (16*1024) 104 105#ifdef WIN32 106 107static HANDLE lock_cs[CRYPTO_NUM_LOCKS]; 108 109int CRYPTO_thread_setup(void) 110 { 111 int i; 112 113 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 114 { 115 lock_cs[i]=CreateMutex(NULL,FALSE,NULL); 116 } 117 118 CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback); 119 /* id callback defined */ 120 return(1); 121 } 122 123static void CRYPTO_thread_cleanup(void) 124 { 125 int i; 126 127 CRYPTO_set_locking_callback(NULL); 128 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 129 CloseHandle(lock_cs[i]); 130 } 131 132void win32_locking_callback(int mode, int type, char *file, int line) 133 { 134 if (mode & CRYPTO_LOCK) 135 { 136 WaitForSingleObject(lock_cs[type],INFINITE); 137 } 138 else 139 { 140 ReleaseMutex(lock_cs[type]); 141 } 142 } 143 144#endif /* WIN32 */ 145 146#ifdef SOLARIS 147 148#define USE_MUTEX 149 150static mutex_t lock_cs[CRYPTO_NUM_LOCKS]; 151#ifdef USE_MUTEX 152static long lock_count[CRYPTO_NUM_LOCKS]; 153#else 154static rwlock_t lock_cs[CRYPTO_NUM_LOCKS]; 155#endif 156 157void CRYPTO_thread_setup(void) 158 { 159 int i; 160 161 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 162 { 163 lock_count[i]=0; 164#ifdef USE_MUTEX 165 mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL); 166#else 167 rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); 168#endif 169 } 170 171 CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id); 172 CRYPTO_set_locking_callback((void (*)())solaris_locking_callback); 173 } 174 175void CRYPTO_thread_cleanup(void) 176 { 177 int i; 178 179 CRYPTO_set_locking_callback(NULL); 180 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 181 { 182#ifdef USE_MUTEX 183 mutex_destroy(&(lock_cs[i])); 184#else 185 rwlock_destroy(&(lock_cs[i])); 186#endif 187 } 188 } 189 190void solaris_locking_callback(int mode, int type, char *file, int line) 191 { 192#if 0 193 fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n", 194 CRYPTO_thread_id(), 195 (mode&CRYPTO_LOCK)?"l":"u", 196 (type&CRYPTO_READ)?"r":"w",file,line); 197#endif 198 199#if 0 200 if (CRYPTO_LOCK_SSL_CERT == type) 201 fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", 202 CRYPTO_thread_id(), 203 mode,file,line); 204#endif 205 if (mode & CRYPTO_LOCK) 206 { 207#ifdef USE_MUTEX 208 mutex_lock(&(lock_cs[type])); 209#else 210 if (mode & CRYPTO_READ) 211 rw_rdlock(&(lock_cs[type])); 212 else 213 rw_wrlock(&(lock_cs[type])); 214#endif 215 lock_count[type]++; 216 } 217 else 218 { 219#ifdef USE_MUTEX 220 mutex_unlock(&(lock_cs[type])); 221#else 222 rw_unlock(&(lock_cs[type])); 223#endif 224 } 225 } 226 227unsigned long solaris_thread_id(void) 228 { 229 unsigned long ret; 230 231 ret=(unsigned long)thr_self(); 232 return(ret); 233 } 234#endif /* SOLARIS */ 235 236#ifdef IRIX 237/* I don't think this works..... */ 238 239static usptr_t *arena; 240static usema_t *lock_cs[CRYPTO_NUM_LOCKS]; 241 242void CRYPTO_thread_setup(void) 243 { 244 int i; 245 char filename[20]; 246 247 strcpy(filename,"/tmp/mttest.XXXXXX"); 248 mktemp(filename); 249 250 usconfig(CONF_STHREADIOOFF); 251 usconfig(CONF_STHREADMALLOCOFF); 252 usconfig(CONF_INITUSERS,100); 253 usconfig(CONF_LOCKTYPE,US_DEBUGPLUS); 254 arena=usinit(filename); 255 unlink(filename); 256 257 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 258 { 259 lock_cs[i]=usnewsema(arena,1); 260 } 261 262 CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id); 263 CRYPTO_set_locking_callback((void (*)())irix_locking_callback); 264 } 265 266void CRYPTO_thread_cleanup(void) 267 { 268 int i; 269 270 CRYPTO_set_locking_callback(NULL); 271 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 272 { 273 char buf[10]; 274 275 sprintf(buf,"%2d:",i); 276 usdumpsema(lock_cs[i],stdout,buf); 277 usfreesema(lock_cs[i],arena); 278 } 279 } 280 281void irix_locking_callback(int mode, int type, char *file, int line) 282 { 283 if (mode & CRYPTO_LOCK) 284 { 285 uspsema(lock_cs[type]); 286 } 287 else 288 { 289 usvsema(lock_cs[type]); 290 } 291 } 292 293unsigned long irix_thread_id(void) 294 { 295 unsigned long ret; 296 297 ret=(unsigned long)getpid(); 298 return(ret); 299 } 300#endif /* IRIX */ 301 302/* Linux and a few others */ 303#ifdef PTHREADS 304 305static pthread_mutex_t lock_cs[CRYPTO_NUM_LOCKS]; 306static long lock_count[CRYPTO_NUM_LOCKS]; 307 308void CRYPTO_thread_setup(void) 309 { 310 int i; 311 312 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 313 { 314 lock_count[i]=0; 315 pthread_mutex_init(&(lock_cs[i]),NULL); 316 } 317 318 CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); 319 CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); 320 } 321 322void thread_cleanup(void) 323 { 324 int i; 325 326 CRYPTO_set_locking_callback(NULL); 327 for (i=0; i<CRYPTO_NUM_LOCKS; i++) 328 { 329 pthread_mutex_destroy(&(lock_cs[i])); 330 } 331 } 332 333void pthreads_locking_callback(int mode, int type, char *file, 334 int line) 335 { 336#if 0 337 fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n", 338 CRYPTO_thread_id(), 339 (mode&CRYPTO_LOCK)?"l":"u", 340 (type&CRYPTO_READ)?"r":"w",file,line); 341#endif 342#if 0 343 if (CRYPTO_LOCK_SSL_CERT == type) 344 fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", 345 CRYPTO_thread_id(), 346 mode,file,line); 347#endif 348 if (mode & CRYPTO_LOCK) 349 { 350 pthread_mutex_lock(&(lock_cs[type])); 351 lock_count[type]++; 352 } 353 else 354 { 355 pthread_mutex_unlock(&(lock_cs[type])); 356 } 357 } 358 359unsigned long pthreads_thread_id(void) 360 { 361 unsigned long ret; 362 363 ret=(unsigned long)pthread_self(); 364 return(ret); 365 } 366 367#endif /* PTHREADS */ 368 369