Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/threads_pthread.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <openssl/crypto.h>
11
#include "internal/cryptlib.h"
12
13
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
14
15
# ifdef PTHREAD_RWLOCK_INITIALIZER
16
#  define USE_RWLOCK
17
# endif
18
19
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
20
1.60M
{
21
1.60M
# ifdef USE_RWLOCK
22
1.60M
    CRYPTO_RWLOCK *lock;
23
1.60M
24
1.60M
    if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) {
25
0
        /* Don't set error, to avoid recursion blowup. */
26
0
        return NULL;
27
0
    }
28
1.60M
29
1.60M
    if (pthread_rwlock_init(lock, NULL) != 0) {
30
0
        OPENSSL_free(lock);
31
0
        return NULL;
32
0
    }
33
# else
34
    pthread_mutexattr_t attr;
35
    CRYPTO_RWLOCK *lock;
36
37
    if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) {
38
        /* Don't set error, to avoid recursion blowup. */
39
        return NULL;
40
    }
41
42
    pthread_mutexattr_init(&attr);
43
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
44
45
    if (pthread_mutex_init(lock, &attr) != 0) {
46
        pthread_mutexattr_destroy(&attr);
47
        OPENSSL_free(lock);
48
        return NULL;
49
    }
50
51
    pthread_mutexattr_destroy(&attr);
52
# endif
53
54
1.60M
    return lock;
55
1.60M
}
56
57
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
58
1.90M
{
59
1.90M
# ifdef USE_RWLOCK
60
1.90M
    if (pthread_rwlock_rdlock(lock) != 0)
61
0
        return 0;
62
# else
63
    if (pthread_mutex_lock(lock) != 0)
64
        return 0;
65
# endif
66
67
1.90M
    return 1;
68
1.90M
}
69
70
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
71
2.81M
{
72
2.81M
# ifdef USE_RWLOCK
73
2.81M
    if (pthread_rwlock_wrlock(lock) != 0)
74
0
        return 0;
75
# else
76
    if (pthread_mutex_lock(lock) != 0)
77
        return 0;
78
# endif
79
80
2.81M
    return 1;
81
2.81M
}
82
83
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
84
4.71M
{
85
4.71M
# ifdef USE_RWLOCK
86
4.71M
    if (pthread_rwlock_unlock(lock) != 0)
87
0
        return 0;
88
# else
89
    if (pthread_mutex_unlock(lock) != 0)
90
        return 0;
91
# endif
92
93
4.71M
    return 1;
94
4.71M
}
95
96
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
97
1.60M
{
98
1.60M
    if (lock == NULL)
99
1.60M
        return;
100
1.60M
101
1.60M
# ifdef USE_RWLOCK
102
1.60M
    pthread_rwlock_destroy(lock);
103
# else
104
    pthread_mutex_destroy(lock);
105
# endif
106
1.60M
    OPENSSL_free(lock);
107
1.60M
108
1.60M
    return;
109
1.60M
}
110
111
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
112
7.06M
{
113
7.06M
    if (pthread_once(once, init) != 0)
114
0
        return 0;
115
7.06M
116
7.06M
    return 1;
117
7.06M
}
118
119
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
120
16
{
121
16
    if (pthread_key_create(key, cleanup) != 0)
122
0
        return 0;
123
16
124
16
    return 1;
125
16
}
126
127
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
128
1.33M
{
129
1.33M
    return pthread_getspecific(*key);
130
1.33M
}
131
132
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
133
40
{
134
40
    if (pthread_setspecific(*key, val) != 0)
135
0
        return 0;
136
40
137
40
    return 1;
138
40
}
139
140
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
141
16
{
142
16
    if (pthread_key_delete(*key) != 0)
143
0
        return 0;
144
16
145
16
    return 1;
146
16
}
147
148
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
149
0
{
150
0
    return pthread_self();
151
0
}
152
153
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
154
0
{
155
0
    return pthread_equal(a, b);
156
0
}
157
158
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
159
0
{
160
0
# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
161
0
    if (__atomic_is_lock_free(sizeof(*val), val)) {
162
0
        *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
163
0
        return 1;
164
0
    }
165
0
# endif
166
0
    if (!CRYPTO_THREAD_write_lock(lock))
167
0
        return 0;
168
0
169
0
    *val += amount;
170
0
    *ret  = *val;
171
0
172
0
    if (!CRYPTO_THREAD_unlock(lock))
173
0
        return 0;
174
0
175
0
    return 1;
176
0
}
177
178
# ifdef OPENSSL_SYS_UNIX
179
static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
180
181
static void fork_once_func(void)
182
0
{
183
0
    pthread_atfork(OPENSSL_fork_prepare,
184
0
                   OPENSSL_fork_parent, OPENSSL_fork_child);
185
0
}
186
# endif
187
188
int openssl_init_fork_handlers(void)
189
0
{
190
0
# ifdef OPENSSL_SYS_UNIX
191
0
    if (pthread_once(&fork_once_control, fork_once_func) == 0)
192
0
        return 1;
193
0
# endif
194
0
    return 0;
195
0
}
196
#endif