aboutsummaryrefslogtreecommitdiffstats
path: root/doc/threads.doc
blob: 251061e8965cf9e3be65b25b4e26a51f65db4ac0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
How to compile SSLeay for multi-threading.

Well basically it is quite simple, set the compiler flags and build.
I have only really done much testing under Solaris and Windows NT.
If you library supports localtime_r() and gmtime_r() add,
-DTHREADS to the makefile parameters.  You can probably survive with out
this define unless you are going to have multiple threads generating
certificates at once.  It will not affect the SSL side of things.

The approach I have taken to doing locking is to make the application provide
callbacks to perform locking and so that the SSLeay library can distinguish
between threads (for the error state).

To have a look at an example program, 'cd mt; vi mttest.c'.
To build under solaris, sh solaris.sh, for Windows NT or Windows 95,
win32.bat

This will build mttest which will fire up 10 threads that talk SSL
to each other 10 times.
To enable everything to work, the application needs to call

CRYPTO_set_id_callback(id_function);
CRYPTO_set_locking_callback(locking_function);

before any multithreading is started.
id_function does not need to be defined under Windows NT or 95, the
correct function will be called if it is not.  Under unix, getpid()
is call if the id_callback is not defined, for solaris this is wrong
(since threads id's are not pid's) but under IRIX it is correct
(threads are just processes sharing the data segement).

The locking_callback is used to perform locking by the SSLeay library.
eg.

void solaris_locking_callback(mode,type,file,line)
int mode;
int type;
char *file;
int line;
	{
	if (mode & CRYPTO_LOCK)
		mutex_lock(&(lock_cs[type]));
	else
		mutex_unlock(&(lock_cs[type]));
	}

Now in this case I have used mutexes instead of read/write locks, since they
are faster and there are not many read locks in SSLeay, you may as well
always use write locks.  file and line are __FILE__ and __LINE__ from
the compile and can be usefull when debugging.

Now as you can see, 'type' can be one of a range of values, these values are
defined in crypto/crypto.h
CRYPTO_get_lock_name(type) will return a text version of what the lock is.
There are CRYPTO_NUM_LOCKS locks required, so under solaris, the setup
for multi-threading can be

static mutex_t lock_cs[CRYPTO_NUM_LOCKS];

void thread_setup()
	{
	int i;

	for (i=0; i<CRYPTO_NUM_LOCKS; i++)
		mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL);
	CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
	CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
	}

As a final note, under Windows NT or Windows 95, you have to be careful
not to mix the various threaded, unthreaded and debug libraries.
Normally if they are mixed incorrectly, mttest will crash just after printing
out some usage statistics at the end.  This is because the
different system libraries use different malloc routines and if
data is malloc()ed inside crypt32.dll or ssl32.dll and then free()ed by a
different library malloc, things get very confused.

The default SSLeay DLL builds use /MD, so if you use this on your
application, things will work as expected.  If you use /MDd,
you will probably have to rebuild SSLeay using this flag.
I should modify util/mk1mf.pl so it does all this correctly, but 
this has not been done yet.

One last warning.  Because locking overheads are actually quite large, the
statistics collected against the SSL_CTX for successfull connections etc
are not locked when updated.  This does make it possible for these
values to be slightly lower than they should be, if you are
running multithreaded on a multi-processor box, but this does not really
matter much.