th-lock.c revision 160814
155714Skris/* crypto/threads/th-lock.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <string.h> 6255714Skris#include <errno.h> 6355714Skris#ifdef LINUX 6455714Skris#include <typedefs.h> 6555714Skris#endif 66109998Smarkm#ifdef OPENSSL_SYS_WIN32 6755714Skris#include <windows.h> 6855714Skris#endif 6955714Skris#ifdef SOLARIS 7055714Skris#include <synch.h> 7155714Skris#include <thread.h> 7255714Skris#endif 7355714Skris#ifdef IRIX 7455714Skris#include <ulocks.h> 7555714Skris#include <sys/prctl.h> 7655714Skris#endif 7759191Skris#ifdef PTHREADS 7859191Skris#include <pthread.h> 7959191Skris#endif 8055714Skris#include <openssl/lhash.h> 8155714Skris#include <openssl/crypto.h> 8255714Skris#include <openssl/buffer.h> 83160814Ssimon#include "../../e_os.h" 8455714Skris#include <openssl/x509.h> 8555714Skris#include <openssl/ssl.h> 8655714Skris#include <openssl/err.h> 8755714Skris 8859191Skrisvoid CRYPTO_thread_setup(void); 8955714Skrisvoid CRYPTO_thread_cleanup(void); 9055714Skris 9155714Skrisstatic void irix_locking_callback(int mode,int type,char *file,int line); 9255714Skrisstatic void solaris_locking_callback(int mode,int type,char *file,int line); 9355714Skrisstatic void win32_locking_callback(int mode,int type,char *file,int line); 9455714Skrisstatic void pthreads_locking_callback(int mode,int type,char *file,int line); 9555714Skris 9655714Skrisstatic unsigned long irix_thread_id(void ); 9755714Skrisstatic unsigned long solaris_thread_id(void ); 9855714Skrisstatic unsigned long pthreads_thread_id(void ); 9955714Skris 10055714Skris/* usage: 10155714Skris * CRYPTO_thread_setup(); 10259191Skris * application code 10355714Skris * CRYPTO_thread_cleanup(); 10455714Skris */ 10555714Skris 10655714Skris#define THREAD_STACK_SIZE (16*1024) 10755714Skris 108109998Smarkm#ifdef OPENSSL_SYS_WIN32 10955714Skris 11059191Skrisstatic HANDLE *lock_cs; 11155714Skris 11259191Skrisvoid CRYPTO_thread_setup(void) 11355714Skris { 11455714Skris int i; 11555714Skris 11668651Skris lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE)); 11759191Skris for (i=0; i<CRYPTO_num_locks(); i++) 11855714Skris { 11955714Skris lock_cs[i]=CreateMutex(NULL,FALSE,NULL); 12055714Skris } 12155714Skris 12255714Skris CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback); 12355714Skris /* id callback defined */ 12455714Skris return(1); 12555714Skris } 12655714Skris 12755714Skrisstatic void CRYPTO_thread_cleanup(void) 12855714Skris { 12955714Skris int i; 13055714Skris 13155714Skris CRYPTO_set_locking_callback(NULL); 13259191Skris for (i=0; i<CRYPTO_num_locks(); i++) 13355714Skris CloseHandle(lock_cs[i]); 13468651Skris OPENSSL_free(lock_cs); 13555714Skris } 13655714Skris 13755714Skrisvoid win32_locking_callback(int mode, int type, char *file, int line) 13855714Skris { 13955714Skris if (mode & CRYPTO_LOCK) 14055714Skris { 14155714Skris WaitForSingleObject(lock_cs[type],INFINITE); 14255714Skris } 14355714Skris else 14455714Skris { 14555714Skris ReleaseMutex(lock_cs[type]); 14655714Skris } 14755714Skris } 14855714Skris 149109998Smarkm#endif /* OPENSSL_SYS_WIN32 */ 15055714Skris 15155714Skris#ifdef SOLARIS 15255714Skris 15355714Skris#define USE_MUTEX 15455714Skris 15555714Skris#ifdef USE_MUTEX 15659191Skrisstatic mutex_t *lock_cs; 15755714Skris#else 15859191Skrisstatic rwlock_t *lock_cs; 15955714Skris#endif 16059191Skrisstatic long *lock_count; 16155714Skris 16255714Skrisvoid CRYPTO_thread_setup(void) 16355714Skris { 16455714Skris int i; 16555714Skris 16659191Skris#ifdef USE_MUTEX 16768651Skris lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t)); 16859191Skris#else 16968651Skris lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(rwlock_t)); 17059191Skris#endif 17168651Skris lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); 17259191Skris for (i=0; i<CRYPTO_num_locks(); i++) 17355714Skris { 17455714Skris lock_count[i]=0; 17555714Skris#ifdef USE_MUTEX 17655714Skris mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL); 17755714Skris#else 17855714Skris rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); 17955714Skris#endif 18055714Skris } 18155714Skris 18255714Skris CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id); 18355714Skris CRYPTO_set_locking_callback((void (*)())solaris_locking_callback); 18455714Skris } 18555714Skris 18655714Skrisvoid CRYPTO_thread_cleanup(void) 18755714Skris { 18855714Skris int i; 18955714Skris 19055714Skris CRYPTO_set_locking_callback(NULL); 19159191Skris for (i=0; i<CRYPTO_num_locks(); i++) 19255714Skris { 19355714Skris#ifdef USE_MUTEX 19455714Skris mutex_destroy(&(lock_cs[i])); 19555714Skris#else 19655714Skris rwlock_destroy(&(lock_cs[i])); 19755714Skris#endif 19855714Skris } 19968651Skris OPENSSL_free(lock_cs); 20068651Skris OPENSSL_free(lock_count); 20155714Skris } 20255714Skris 20355714Skrisvoid solaris_locking_callback(int mode, int type, char *file, int line) 20455714Skris { 20555714Skris#if 0 20655714Skris fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n", 20755714Skris CRYPTO_thread_id(), 20855714Skris (mode&CRYPTO_LOCK)?"l":"u", 20955714Skris (type&CRYPTO_READ)?"r":"w",file,line); 21055714Skris#endif 21155714Skris 21255714Skris#if 0 21355714Skris if (CRYPTO_LOCK_SSL_CERT == type) 21455714Skris fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", 21555714Skris CRYPTO_thread_id(), 21655714Skris mode,file,line); 21755714Skris#endif 21855714Skris if (mode & CRYPTO_LOCK) 21955714Skris { 22055714Skris#ifdef USE_MUTEX 22155714Skris mutex_lock(&(lock_cs[type])); 22255714Skris#else 22355714Skris if (mode & CRYPTO_READ) 22455714Skris rw_rdlock(&(lock_cs[type])); 22555714Skris else 22655714Skris rw_wrlock(&(lock_cs[type])); 22755714Skris#endif 22855714Skris lock_count[type]++; 22955714Skris } 23055714Skris else 23155714Skris { 23255714Skris#ifdef USE_MUTEX 23355714Skris mutex_unlock(&(lock_cs[type])); 23455714Skris#else 23555714Skris rw_unlock(&(lock_cs[type])); 23655714Skris#endif 23755714Skris } 23855714Skris } 23955714Skris 24055714Skrisunsigned long solaris_thread_id(void) 24155714Skris { 24255714Skris unsigned long ret; 24355714Skris 24455714Skris ret=(unsigned long)thr_self(); 24555714Skris return(ret); 24655714Skris } 24755714Skris#endif /* SOLARIS */ 24855714Skris 24955714Skris#ifdef IRIX 25055714Skris/* I don't think this works..... */ 25155714Skris 25255714Skrisstatic usptr_t *arena; 25359191Skrisstatic usema_t **lock_cs; 25455714Skris 25555714Skrisvoid CRYPTO_thread_setup(void) 25655714Skris { 25755714Skris int i; 25855714Skris char filename[20]; 25955714Skris 26055714Skris strcpy(filename,"/tmp/mttest.XXXXXX"); 26155714Skris mktemp(filename); 26255714Skris 26355714Skris usconfig(CONF_STHREADIOOFF); 26455714Skris usconfig(CONF_STHREADMALLOCOFF); 26555714Skris usconfig(CONF_INITUSERS,100); 26655714Skris usconfig(CONF_LOCKTYPE,US_DEBUGPLUS); 26755714Skris arena=usinit(filename); 26855714Skris unlink(filename); 26955714Skris 27068651Skris lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *)); 27159191Skris for (i=0; i<CRYPTO_num_locks(); i++) 27255714Skris { 27355714Skris lock_cs[i]=usnewsema(arena,1); 27455714Skris } 27555714Skris 27655714Skris CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id); 27755714Skris CRYPTO_set_locking_callback((void (*)())irix_locking_callback); 27855714Skris } 27955714Skris 28055714Skrisvoid CRYPTO_thread_cleanup(void) 28155714Skris { 28255714Skris int i; 28355714Skris 28455714Skris CRYPTO_set_locking_callback(NULL); 28559191Skris for (i=0; i<CRYPTO_num_locks(); i++) 28655714Skris { 28755714Skris char buf[10]; 28855714Skris 28955714Skris sprintf(buf,"%2d:",i); 29055714Skris usdumpsema(lock_cs[i],stdout,buf); 29155714Skris usfreesema(lock_cs[i],arena); 29255714Skris } 29368651Skris OPENSSL_free(lock_cs); 29455714Skris } 29555714Skris 29655714Skrisvoid irix_locking_callback(int mode, int type, char *file, int line) 29755714Skris { 29855714Skris if (mode & CRYPTO_LOCK) 29955714Skris { 30055714Skris uspsema(lock_cs[type]); 30155714Skris } 30255714Skris else 30355714Skris { 30455714Skris usvsema(lock_cs[type]); 30555714Skris } 30655714Skris } 30755714Skris 30855714Skrisunsigned long irix_thread_id(void) 30955714Skris { 31055714Skris unsigned long ret; 31155714Skris 31255714Skris ret=(unsigned long)getpid(); 31355714Skris return(ret); 31455714Skris } 31555714Skris#endif /* IRIX */ 31655714Skris 31755714Skris/* Linux and a few others */ 31855714Skris#ifdef PTHREADS 31955714Skris 32059191Skrisstatic pthread_mutex_t *lock_cs; 32159191Skrisstatic long *lock_count; 32255714Skris 32355714Skrisvoid CRYPTO_thread_setup(void) 32455714Skris { 32555714Skris int i; 32655714Skris 32768651Skris lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); 32868651Skris lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); 32959191Skris for (i=0; i<CRYPTO_num_locks(); i++) 33055714Skris { 33155714Skris lock_count[i]=0; 33255714Skris pthread_mutex_init(&(lock_cs[i]),NULL); 33355714Skris } 33455714Skris 33555714Skris CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); 33655714Skris CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); 33755714Skris } 33855714Skris 33955714Skrisvoid thread_cleanup(void) 34055714Skris { 34155714Skris int i; 34255714Skris 34355714Skris CRYPTO_set_locking_callback(NULL); 34459191Skris for (i=0; i<CRYPTO_num_locks(); i++) 34555714Skris { 34655714Skris pthread_mutex_destroy(&(lock_cs[i])); 34755714Skris } 34868651Skris OPENSSL_free(lock_cs); 34968651Skris OPENSSL_free(lock_count); 35055714Skris } 35155714Skris 35255714Skrisvoid pthreads_locking_callback(int mode, int type, char *file, 35355714Skris int line) 35455714Skris { 35555714Skris#if 0 35655714Skris fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n", 35755714Skris CRYPTO_thread_id(), 35855714Skris (mode&CRYPTO_LOCK)?"l":"u", 35955714Skris (type&CRYPTO_READ)?"r":"w",file,line); 36055714Skris#endif 36155714Skris#if 0 36255714Skris if (CRYPTO_LOCK_SSL_CERT == type) 36355714Skris fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", 36455714Skris CRYPTO_thread_id(), 36555714Skris mode,file,line); 36655714Skris#endif 36755714Skris if (mode & CRYPTO_LOCK) 36855714Skris { 36955714Skris pthread_mutex_lock(&(lock_cs[type])); 37055714Skris lock_count[type]++; 37155714Skris } 37255714Skris else 37355714Skris { 37455714Skris pthread_mutex_unlock(&(lock_cs[type])); 37555714Skris } 37655714Skris } 37755714Skris 37855714Skrisunsigned long pthreads_thread_id(void) 37955714Skris { 38055714Skris unsigned long ret; 38155714Skris 38255714Skris ret=(unsigned long)pthread_self(); 38355714Skris return(ret); 38455714Skris } 38555714Skris 38655714Skris#endif /* PTHREADS */ 38755714Skris 388