Coverage Report

Created: 2025-06-11 06:41

/src/boringssl/crypto/thread_pthread.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
// Ensure we can't call OPENSSL_malloc circularly.
16
#define _BORINGSSL_PROHIBIT_OPENSSL_MALLOC
17
#include "internal.h"
18
19
#if defined(OPENSSL_PTHREADS)
20
21
#include <assert.h>
22
#include <pthread.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
153k
void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
27
153k
  if (pthread_rwlock_init(lock, NULL) != 0) {
28
0
    abort();
29
0
  }
30
153k
}
31
32
37.4k
void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {
33
37.4k
  if (pthread_rwlock_rdlock(lock) != 0) {
34
0
    abort();
35
0
  }
36
37.4k
}
37
38
75.0k
void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
39
75.0k
  if (pthread_rwlock_wrlock(lock) != 0) {
40
0
    abort();
41
0
  }
42
75.0k
}
43
44
37.4k
void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
45
37.4k
  if (pthread_rwlock_unlock(lock) != 0) {
46
0
    abort();
47
0
  }
48
37.4k
}
49
50
75.0k
void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
51
75.0k
  if (pthread_rwlock_unlock(lock) != 0) {
52
0
    abort();
53
0
  }
54
75.0k
}
55
56
153k
void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { pthread_rwlock_destroy(lock); }
57
58
26.8M
void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
59
26.8M
  if (pthread_once(once, init) != 0) {
60
0
    abort();
61
0
  }
62
26.8M
}
63
64
static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER;
65
static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS];
66
67
// thread_local_destructor is called when a thread exits. It releases thread
68
// local data for that thread only.
69
0
static void thread_local_destructor(void *arg) {
70
0
  if (arg == NULL) {
71
0
    return;
72
0
  }
73
74
0
  thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS];
75
0
  if (pthread_mutex_lock(&g_destructors_lock) != 0) {
76
0
    return;
77
0
  }
78
0
  OPENSSL_memcpy(destructors, g_destructors, sizeof(destructors));
79
0
  pthread_mutex_unlock(&g_destructors_lock);
80
81
0
  unsigned i;
82
0
  void **pointers = reinterpret_cast<void **>(arg);
83
0
  for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) {
84
0
    if (destructors[i] != NULL) {
85
0
      destructors[i](pointers[i]);
86
0
    }
87
0
  }
88
89
0
  free(pointers);
90
0
}
91
92
static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT;
93
static pthread_key_t g_thread_local_key;
94
static int g_thread_local_key_created = 0;
95
96
2
static void thread_local_init(void) {
97
2
  g_thread_local_key_created =
98
2
      pthread_key_create(&g_thread_local_key, thread_local_destructor) == 0;
99
2
}
100
101
785k
void *CRYPTO_get_thread_local(thread_local_data_t index) {
102
785k
  CRYPTO_once(&g_thread_local_init_once, thread_local_init);
103
785k
  if (!g_thread_local_key_created) {
104
0
    return NULL;
105
0
  }
106
107
785k
  void **pointers =
108
785k
      reinterpret_cast<void **>(pthread_getspecific(g_thread_local_key));
109
785k
  if (pointers == NULL) {
110
2
    return NULL;
111
2
  }
112
785k
  return pointers[index];
113
785k
}
114
115
int CRYPTO_set_thread_local(thread_local_data_t index, void *value,
116
3
                            thread_local_destructor_t destructor) {
117
3
  CRYPTO_once(&g_thread_local_init_once, thread_local_init);
118
3
  if (!g_thread_local_key_created) {
119
0
    destructor(value);
120
0
    return 0;
121
0
  }
122
123
3
  void **pointers =
124
3
      reinterpret_cast<void **>(pthread_getspecific(g_thread_local_key));
125
3
  if (pointers == NULL) {
126
2
    pointers = reinterpret_cast<void **>(
127
2
        malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS));
128
2
    if (pointers == NULL) {
129
0
      destructor(value);
130
0
      return 0;
131
0
    }
132
2
    OPENSSL_memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
133
2
    if (pthread_setspecific(g_thread_local_key, pointers) != 0) {
134
0
      free(pointers);
135
0
      destructor(value);
136
0
      return 0;
137
0
    }
138
2
  }
139
140
3
  if (pthread_mutex_lock(&g_destructors_lock) != 0) {
141
0
    destructor(value);
142
0
    return 0;
143
0
  }
144
3
  g_destructors[index] = destructor;
145
3
  pthread_mutex_unlock(&g_destructors_lock);
146
147
3
  pointers[index] = value;
148
3
  return 1;
149
3
}
150
151
#endif  // OPENSSL_PTHREADS