Coverage Report

Created: 2024-08-17 06:47

/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 Apache License 2.0 (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(__sun)
14
# include <atomic.h>
15
#endif
16
17
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
18
19
# if defined(OPENSSL_SYS_UNIX)
20
#  include <sys/types.h>
21
#  include <unistd.h>
22
#endif
23
24
# ifdef PTHREAD_RWLOCK_INITIALIZER
25
#  define USE_RWLOCK
26
# endif
27
28
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
29
30.7k
{
30
30.7k
# ifdef USE_RWLOCK
31
30.7k
    CRYPTO_RWLOCK *lock;
32
33
30.7k
    if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) {
34
        /* Don't set error, to avoid recursion blowup. */
35
0
        return NULL;
36
0
    }
37
38
30.7k
    if (pthread_rwlock_init(lock, NULL) != 0) {
39
0
        OPENSSL_free(lock);
40
0
        return NULL;
41
0
    }
42
# else
43
    pthread_mutexattr_t attr;
44
    CRYPTO_RWLOCK *lock;
45
46
    if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) {
47
        /* Don't set error, to avoid recursion blowup. */
48
        return NULL;
49
    }
50
51
    pthread_mutexattr_init(&attr);
52
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
53
54
    if (pthread_mutex_init(lock, &attr) != 0) {
55
        pthread_mutexattr_destroy(&attr);
56
        OPENSSL_free(lock);
57
        return NULL;
58
    }
59
60
    pthread_mutexattr_destroy(&attr);
61
# endif
62
63
30.7k
    return lock;
64
30.7k
}
65
66
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
67
30.8k
{
68
30.8k
# ifdef USE_RWLOCK
69
30.8k
    if (pthread_rwlock_rdlock(lock) != 0)
70
0
        return 0;
71
# else
72
    if (pthread_mutex_lock(lock) != 0)
73
        return 0;
74
# endif
75
76
30.8k
    return 1;
77
30.8k
}
78
79
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
80
466k
{
81
466k
# ifdef USE_RWLOCK
82
466k
    if (pthread_rwlock_wrlock(lock) != 0)
83
0
        return 0;
84
# else
85
    if (pthread_mutex_lock(lock) != 0)
86
        return 0;
87
# endif
88
89
466k
    return 1;
90
466k
}
91
92
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
93
497k
{
94
497k
# ifdef USE_RWLOCK
95
497k
    if (pthread_rwlock_unlock(lock) != 0)
96
0
        return 0;
97
# else
98
    if (pthread_mutex_unlock(lock) != 0)
99
        return 0;
100
# endif
101
102
497k
    return 1;
103
497k
}
104
105
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
106
30.6k
{
107
30.6k
    if (lock == NULL)
108
30
        return;
109
110
30.6k
# ifdef USE_RWLOCK
111
30.6k
    pthread_rwlock_destroy(lock);
112
# else
113
    pthread_mutex_destroy(lock);
114
# endif
115
30.6k
    OPENSSL_free(lock);
116
117
30.6k
    return;
118
30.6k
}
119
120
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
121
3.61M
{
122
3.61M
    if (pthread_once(once, init) != 0)
123
0
        return 0;
124
125
3.61M
    return 1;
126
3.61M
}
127
128
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
129
24
{
130
24
    if (pthread_key_create(key, cleanup) != 0)
131
0
        return 0;
132
133
24
    return 1;
134
24
}
135
136
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
137
924k
{
138
924k
    return pthread_getspecific(*key);
139
924k
}
140
141
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
142
48
{
143
48
    if (pthread_setspecific(*key, val) != 0)
144
0
        return 0;
145
146
48
    return 1;
147
48
}
148
149
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
150
12
{
151
12
    if (pthread_key_delete(*key) != 0)
152
0
        return 0;
153
154
12
    return 1;
155
12
}
156
157
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
158
4.06k
{
159
4.06k
    return pthread_self();
160
4.06k
}
161
162
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
163
0
{
164
0
    return pthread_equal(a, b);
165
0
}
166
167
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
168
0
{
169
0
# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
170
0
    if (__atomic_is_lock_free(sizeof(*val), val)) {
171
0
        *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
172
0
        return 1;
173
0
    }
174
# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11))
175
    /* This will work for all future Solaris versions. */
176
    if (ret != NULL) {
177
        *ret = atomic_add_int_nv((volatile unsigned int *)val, amount);
178
        return 1;
179
    }
180
# endif
181
0
    if (!CRYPTO_THREAD_write_lock(lock))
182
0
        return 0;
183
184
0
    *val += amount;
185
0
    *ret  = *val;
186
187
0
    if (!CRYPTO_THREAD_unlock(lock))
188
0
        return 0;
189
190
0
    return 1;
191
0
}
192
193
# ifndef FIPS_MODE
194
/* TODO(3.0): No fork protection in FIPS module yet! */
195
196
#  ifdef OPENSSL_SYS_UNIX
197
static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
198
199
static void fork_once_func(void)
200
0
{
201
0
    pthread_atfork(OPENSSL_fork_prepare,
202
0
                   OPENSSL_fork_parent, OPENSSL_fork_child);
203
0
}
204
#  endif
205
206
int openssl_init_fork_handlers(void)
207
0
{
208
0
#  ifdef OPENSSL_SYS_UNIX
209
0
    if (pthread_once(&fork_once_control, fork_once_func) == 0)
210
0
        return 1;
211
0
#  endif
212
0
    return 0;
213
0
}
214
# endif /* FIPS_MODE */
215
216
int openssl_get_fork_id(void)
217
0
{
218
0
    return getpid();
219
0
}
220
#endif