Add support for dynamically created and destroyed mutexes. This will
be needed in some ENGINE code, and might serve elsewhere as well. Note that it's implemented in such a way that the locking itself is done through the same CRYPTO_lock function as the static locks. WARNING: This is currently experimental and untested code (it will get tested soon, though :-)).
This commit is contained in:
parent
a8b07aa4e9
commit
c79223040d
@ -67,6 +67,7 @@
|
||||
static ERR_STRING_DATA CRYPTO_str_functs[]=
|
||||
{
|
||||
{ERR_PACK(0,CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,0), "CRYPTO_get_ex_new_index"},
|
||||
{ERR_PACK(0,CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,0), "CRYPTO_get_new_dynlockid"},
|
||||
{ERR_PACK(0,CRYPTO_F_CRYPTO_GET_NEW_LOCKID,0), "CRYPTO_get_new_lockid"},
|
||||
{ERR_PACK(0,CRYPTO_F_CRYPTO_SET_EX_DATA,0), "CRYPTO_set_ex_data"},
|
||||
{0,NULL}
|
||||
@ -74,6 +75,7 @@ static ERR_STRING_DATA CRYPTO_str_functs[]=
|
||||
|
||||
static ERR_STRING_DATA CRYPTO_str_reasons[]=
|
||||
{
|
||||
{CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK ,"no dynlock create callback"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
@ -60,11 +60,15 @@
|
||||
#include <string.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/safestack.h>
|
||||
|
||||
#if defined(WIN32) || defined(WIN16)
|
||||
static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
|
||||
#endif
|
||||
|
||||
DECLARE_STACK_OF(CRYPTO_dynlock);
|
||||
IMPLEMENT_STACK_OF(CRYPTO_dynlock);
|
||||
|
||||
/* real #defines in crypto.h, keep these upto date */
|
||||
static const char* lock_names[CRYPTO_NUM_LOCKS] =
|
||||
{
|
||||
@ -100,13 +104,30 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] =
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This is for applications to allocate new type names in the non-dynamic
|
||||
array of lock names. These are numbered with positive numbers. */
|
||||
static STACK *app_locks=NULL;
|
||||
|
||||
/* For applications that want a more dynamic way of handling threads, the
|
||||
following stack is used. These are externally numbered with negative
|
||||
numbers. */
|
||||
static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL;
|
||||
|
||||
|
||||
static void (MS_FAR *locking_callback)(int mode,int type,
|
||||
const char *file,int line)=NULL;
|
||||
static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
|
||||
int type,const char *file,int line)=NULL;
|
||||
static unsigned long (MS_FAR *id_callback)(void)=NULL;
|
||||
static CRYPTO_dynlock *(MS_FAR *dynlock_create_callback)(const char *file,
|
||||
int line)=NULL;
|
||||
static void (MS_FAR *dynlock_locking_callback)(int mode, CRYPTO_dynlock *l,
|
||||
const char *file,int line)=NULL;
|
||||
static void (MS_FAR *dynlock_destroy_callback)(CRYPTO_dynlock *l,
|
||||
const char *file,int line)=NULL;
|
||||
static int (MS_FAR *add_dynlock_callback)(int *pointer,int amount,
|
||||
CRYPTO_dynlock *l,const char *file,int line)=NULL;
|
||||
|
||||
int CRYPTO_get_new_lockid(char *name)
|
||||
{
|
||||
char *str;
|
||||
@ -126,7 +147,10 @@ int CRYPTO_get_new_lockid(char *name)
|
||||
return(0);
|
||||
}
|
||||
if ((str=BUF_strdup(name)) == NULL)
|
||||
{
|
||||
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
i=sk_push(app_locks,str);
|
||||
if (!i)
|
||||
OPENSSL_free(str);
|
||||
@ -140,30 +164,112 @@ int CRYPTO_num_locks(void)
|
||||
return CRYPTO_NUM_LOCKS;
|
||||
}
|
||||
|
||||
int CRYPTO_get_new_dynlockid(void)
|
||||
{
|
||||
int i = 0;
|
||||
CRYPTO_dynlock *pointer = NULL;
|
||||
|
||||
if (dynlock_create_callback == NULL)
|
||||
{
|
||||
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
|
||||
return(0);
|
||||
}
|
||||
if ((dyn_locks == NULL)
|
||||
&& ((dyn_locks=sk_new_null()) == NULL))
|
||||
{
|
||||
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
pointer = dynlock_create_callback(__FILE__,__LINE__);
|
||||
if (pointer == NULL)
|
||||
{
|
||||
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
i=sk_CRYPTO_dynlock_push(dyn_locks,pointer);
|
||||
if (!i)
|
||||
dynlock_destroy_callback(pointer,__FILE__,__LINE__);
|
||||
else
|
||||
i += 1; /* to avoid 0 */
|
||||
return -i;
|
||||
}
|
||||
|
||||
void CRYPTO_destroy_dynlockid(int i)
|
||||
{
|
||||
if (i)
|
||||
i = -i-1;
|
||||
if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks))
|
||||
return;
|
||||
if (dynlock_destroy_callback == NULL)
|
||||
return;
|
||||
dynlock_destroy_callback(sk_CRYPTO_dynlock_value(dyn_locks, i),
|
||||
__FILE__,__LINE__);
|
||||
sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
|
||||
}
|
||||
|
||||
CRYPTO_dynlock *CRYPTO_get_dynlock_value(int i)
|
||||
{
|
||||
if (i)
|
||||
i = -i-1;
|
||||
if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks))
|
||||
return NULL;
|
||||
return sk_CRYPTO_dynlock_value(dyn_locks, i);
|
||||
}
|
||||
|
||||
void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
|
||||
int line)
|
||||
{
|
||||
return(locking_callback);
|
||||
}
|
||||
|
||||
void (*CRYPTO_get_dynlock_lock_callback(void))(int mode,CRYPTO_dynlock *l,
|
||||
const char *file,int line)
|
||||
{
|
||||
return(dynlock_locking_callback);
|
||||
}
|
||||
|
||||
int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
|
||||
const char *file,int line)
|
||||
{
|
||||
return(add_lock_callback);
|
||||
}
|
||||
|
||||
int (*CRYPTO_get_add_dynlock_callback(void))(int *num,int mount,
|
||||
CRYPTO_dynlock *l,
|
||||
const char *file,int line)
|
||||
{
|
||||
return(add_dynlock_callback);
|
||||
}
|
||||
|
||||
void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
|
||||
const char *file,int line))
|
||||
{
|
||||
locking_callback=func;
|
||||
}
|
||||
|
||||
void CRYPTO_set_dynlock_locking_callback(void (*func)(int mode,
|
||||
CRYPTO_dynlock *l,
|
||||
const char *file,
|
||||
int line))
|
||||
{
|
||||
dynlock_locking_callback=func;
|
||||
}
|
||||
|
||||
void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
|
||||
const char *file,int line))
|
||||
{
|
||||
add_lock_callback=func;
|
||||
}
|
||||
|
||||
void CRYPTO_set_add_dynlock_lock_callback(int (*func)(int *num,int mount,
|
||||
CRYPTO_dynlock *l,
|
||||
const char *file,
|
||||
int line))
|
||||
{
|
||||
add_dynlock_callback=func;
|
||||
}
|
||||
|
||||
unsigned long (*CRYPTO_get_id_callback(void))(void)
|
||||
{
|
||||
return(id_callback);
|
||||
@ -220,14 +326,23 @@ void CRYPTO_lock(int mode, int type, const char *file, int line)
|
||||
CRYPTO_get_lock_name(type), file, line);
|
||||
}
|
||||
#endif
|
||||
if (locking_callback != NULL)
|
||||
locking_callback(mode,type,file,line);
|
||||
if (type < 0)
|
||||
{
|
||||
int i = -type-1;
|
||||
if (i < sk_CRYPTO_dynlock_num(dyn_locks))
|
||||
dynlock_locking_callback(mode,
|
||||
sk_CRYPTO_dynlock_value(dyn_locks,i),
|
||||
file,line);
|
||||
}
|
||||
else
|
||||
if (locking_callback != NULL)
|
||||
locking_callback(mode,type,file,line);
|
||||
}
|
||||
|
||||
int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
|
||||
int line)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (add_lock_callback != NULL)
|
||||
{
|
||||
@ -235,7 +350,21 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
|
||||
int before= *pointer;
|
||||
#endif
|
||||
|
||||
ret=add_lock_callback(pointer,amount,type,file,line);
|
||||
if (type < 0)
|
||||
{
|
||||
int i = -type-1;
|
||||
if (i >= sk_CRYPTO_dynlock_num(dyn_locks))
|
||||
/* FIXME: This is superbly dangerous if there
|
||||
are threads competing on this value, but
|
||||
hey, if the user used an invalid lock... */
|
||||
ret=(*pointer + amount);
|
||||
else
|
||||
ret=add_dynlock_callback(pointer,amount,
|
||||
sk_CRYPTO_dynlock_value(dyn_locks,i),
|
||||
file,line);
|
||||
}
|
||||
else
|
||||
ret=add_lock_callback(pointer,amount,type,file,line);
|
||||
#ifdef LOCK_DEBUG
|
||||
fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
|
||||
CRYPTO_thread_id(),
|
||||
@ -266,7 +395,7 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
|
||||
const char *CRYPTO_get_lock_name(int type)
|
||||
{
|
||||
if (type < 0)
|
||||
return("ERROR");
|
||||
return("dynamic");
|
||||
else if (type < CRYPTO_NUM_LOCKS)
|
||||
return(lock_names[type]);
|
||||
else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks))
|
||||
|
@ -150,6 +150,12 @@ extern "C" {
|
||||
#define CRYPTO_add(a,b,c) ((*(a))+=(b))
|
||||
#endif
|
||||
|
||||
/* Some applications as well as some parts of OpenSSL need to allocate
|
||||
and deallocate locks in a dynamic fashion. The following typedef
|
||||
makes this possible in a type-safe manner. */
|
||||
typedef struct CRYPTO_dynlock_value CRYPTO_dynlock;
|
||||
|
||||
|
||||
/* The following can be used to detect memory leaks in the SSLeay library.
|
||||
* It used, it turns on malloc checking */
|
||||
|
||||
@ -299,6 +305,16 @@ unsigned long CRYPTO_thread_id(void);
|
||||
const char *CRYPTO_get_lock_name(int type);
|
||||
int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
|
||||
int line);
|
||||
void CRYPTO_set_dynlock_create_callback(CRYPTO_dynlock *(*dyn_create_function)
|
||||
(char *file, int line));
|
||||
void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)
|
||||
(int mode, CRYPTO_dynlock *l, const char *file, int line));
|
||||
void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)
|
||||
(CRYPTO_dynlock *l, const char *file, int line));
|
||||
void CRYPTO_set_dynlock_size(int dynlock_size);
|
||||
int CRYPTO_get_new_dynlockid(void);
|
||||
void CRYPTO_destroy_dynlockid(int i);
|
||||
CRYPTO_dynlock *CRYPTO_get_dynlock_value(int i);
|
||||
|
||||
/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions --
|
||||
* call the latter last if you need different functions */
|
||||
@ -371,12 +387,15 @@ void ERR_load_CRYPTO_strings(void);
|
||||
|
||||
/* Function codes. */
|
||||
#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100
|
||||
#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103
|
||||
#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101
|
||||
#define CRYPTO_F_CRYPTO_SET_EX_DATA 102
|
||||
|
||||
/* Reason codes. */
|
||||
#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -164,6 +164,26 @@ STACK_OF(type) \
|
||||
#endif
|
||||
|
||||
/* This block of defines is updated by util/mkstack.pl, please do not touch! */
|
||||
#define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock)
|
||||
#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i))
|
||||
#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val))
|
||||
#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val))
|
||||
#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val))
|
||||
#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val))
|
||||
#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i))
|
||||
#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr))
|
||||
#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i))
|
||||
#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp))
|
||||
#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st)
|
||||
#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func))
|
||||
#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st))
|
||||
#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st))
|
||||
|
||||
#define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st))
|
||||
#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
|
||||
#define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st))
|
||||
|
@ -15,10 +15,27 @@ CRYPTO_set_locking_callback, CRYPTO_set_id_callback - OpenSSL thread support
|
||||
|
||||
int CRYPTO_num_locks(void);
|
||||
|
||||
|
||||
/* struct CRYPTO_dynlock_value needs to be defined by the user */
|
||||
typedef struct CRYPTO_dynlock_value CRYPTO_dynlock;
|
||||
|
||||
void CRYPTO_set_dynlock_create_callback(CRYPTO_dynlock *(*dyn_create_function)
|
||||
(char *file, int line));
|
||||
void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)
|
||||
(int mode, CRYPTO_dynlock *l, const char *file, int line));
|
||||
void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)
|
||||
(CRYPTO_dynlock *l, const char *file, int line));
|
||||
|
||||
int CRYPTO_get_new_dynlockid(void);
|
||||
|
||||
void CRYPTO_destroy_dynlockid(int i);
|
||||
|
||||
void CRYPTO_lock(int mode, int n, const char *file, int line);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
OpenSSL can safely be used in multi-threaded applications provided
|
||||
that two callback functions are set.
|
||||
that at least two callback functions are set.
|
||||
|
||||
locking_function(int mode, int n, const char *file, int line) is
|
||||
needed to perform locking on shared data stuctures. Multi-threaded
|
||||
@ -35,9 +52,55 @@ id_function(void) is a function that returns a thread ID. It is not
|
||||
needed on Windows nor on platforms where getpid() returns a different
|
||||
ID for each thread (most notably Linux).
|
||||
|
||||
Additionally, OpenSSL supports dynamic locks, and sometimes, some parts
|
||||
of OpenSSL need it for better performance. To enable this, the following
|
||||
is required:
|
||||
|
||||
=item *
|
||||
Three additional callback function, dyn_create_function, dyn_lock_function
|
||||
and dyn_destroy_function.
|
||||
|
||||
=item *
|
||||
A structure defined with the data that each lock needs to handle.
|
||||
|
||||
struct CRYPTO_dynlock_value has to be defined to contain whatever structure
|
||||
is needed to handle locks.
|
||||
|
||||
dyn_create_function(const char *file, int line) is needed to create a
|
||||
lock. Multi-threaded applications might crash at random if it is not set.
|
||||
|
||||
dyn_lock_function(int mode, CRYPTO_dynlock *l, const char *file, int line)
|
||||
is needed to perform locking off dynamic lock nunmbered n. Multi-threaded
|
||||
applications might crash at random if it is not set.
|
||||
|
||||
dyn_destroy_function(CRYPTO_dynlock *l, const char *file, int line) is
|
||||
needed to destroy the lock l. Multi-threaded applications might crash at
|
||||
random if it is not set.
|
||||
|
||||
CRYPTO_get_new_dynlockid() is used to create locks. It will call
|
||||
dyn_create_function for the actual creation.
|
||||
|
||||
CRYPTO_destroy_dynlockid() is used to destroy locks. It will call
|
||||
dyn_destroy_function for the actual destruction.
|
||||
|
||||
CRYPTO_lock() is used to lock and unlock the locks. mode is a bitfield
|
||||
describing what should be done with the lock. n is the number of the
|
||||
lock as returned from CRYPTO_get_new_dynlockid(). mode can be combined
|
||||
from the following values. These values are pairwise exclusive, with
|
||||
undefined behavior if misused (for example, CRYPTO_READ and CRYPTO_WRITE
|
||||
should not be used together):
|
||||
|
||||
CRYPTO_LOCK 0x01
|
||||
CRYPTO_UNLOCK 0x02
|
||||
CRYPTO_READ 0x04
|
||||
CRYPTO_WRITE 0x08
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
CRYPTO_num_locks() returns the required number of locks.
|
||||
|
||||
CRYPTO_get_new_dynlockid() returns the index to the newly created lock.
|
||||
|
||||
The other functions return no values.
|
||||
|
||||
=head1 NOTE
|
||||
@ -62,6 +125,7 @@ Solaris, Irix and Win32.
|
||||
CRYPTO_set_locking_callback() and CRYPTO_set_id_callback() are
|
||||
available in all versions of SSLeay and OpenSSL.
|
||||
CRYPTO_num_locks() was added in OpenSSL 0.9.4.
|
||||
All functions dealing with dynamic locks were added in OpenSSL 0.9.5b-dev.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
@ -1810,3 +1810,10 @@ i2d_RSA_NET 2406
|
||||
d2i_RSA_NET_2 2407
|
||||
d2i_RSA_NET 2408
|
||||
DSO_bind_func 2409
|
||||
CRYPTO_get_new_dynlockid 2410
|
||||
sk_new_null 2411
|
||||
CRYPTO_set_dynlock_destroy_callback 2412
|
||||
CRYPTO_destroy_dynlockid 2413
|
||||
CRYPTO_set_dynlock_size 2414
|
||||
CRYPTO_set_dynlock_create_callback 2415
|
||||
CRYPTO_set_dynlock_lock_callback 2416
|
||||
|
Loading…
x
Reference in New Issue
Block a user