1 /* Copyright (c) 2015, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 #include "internal.h" 16 17 #if defined(OPENSSL_PTHREADS) 18 19 #include <pthread.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include <openssl/mem.h> 24 #include <openssl/type_check.h> 25 26 27 OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(pthread_rwlock_t), 28 CRYPTO_MUTEX_too_small); 29 30 void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { 31 if (pthread_rwlock_init((pthread_rwlock_t *) lock, NULL) != 0) { 32 abort(); 33 } 34 } 35 36 void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) { 37 if (pthread_rwlock_rdlock((pthread_rwlock_t *) lock) != 0) { 38 abort(); 39 } 40 } 41 42 void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) { 43 if (pthread_rwlock_wrlock((pthread_rwlock_t *) lock) != 0) { 44 abort(); 45 } 46 } 47 48 void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) { 49 if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { 50 abort(); 51 } 52 } 53 54 void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) { 55 if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { 56 abort(); 57 } 58 } 59 60 void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { 61 pthread_rwlock_destroy((pthread_rwlock_t *) lock); 62 } 63 64 void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { 65 if (pthread_rwlock_rdlock(&lock->lock) != 0) { 66 abort(); 67 } 68 } 69 70 void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) { 71 if (pthread_rwlock_wrlock(&lock->lock) != 0) { 72 abort(); 73 } 74 } 75 76 void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) { 77 if (pthread_rwlock_unlock(&lock->lock) != 0) { 78 abort(); 79 } 80 } 81 82 void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) { 83 if (pthread_rwlock_unlock(&lock->lock) != 0) { 84 abort(); 85 } 86 } 87 88 void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { 89 if (pthread_once(once, init) != 0) { 90 abort(); 91 } 92 } 93 94 static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER; 95 static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; 96 97 static void thread_local_destructor(void *arg) { 98 if (arg == NULL) { 99 return; 100 } 101 102 thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; 103 if (pthread_mutex_lock(&g_destructors_lock) != 0) { 104 return; 105 } 106 OPENSSL_memcpy(destructors, g_destructors, sizeof(destructors)); 107 pthread_mutex_unlock(&g_destructors_lock); 108 109 unsigned i; 110 void **pointers = arg; 111 for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { 112 if (destructors[i] != NULL) { 113 destructors[i](pointers[i]); 114 } 115 } 116 117 OPENSSL_free(pointers); 118 } 119 120 static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT; 121 static pthread_key_t g_thread_local_key; 122 static int g_thread_local_failed = 0; 123 124 static void thread_local_init(void) { 125 g_thread_local_failed = 126 pthread_key_create(&g_thread_local_key, thread_local_destructor) != 0; 127 } 128 129 void *CRYPTO_get_thread_local(thread_local_data_t index) { 130 CRYPTO_once(&g_thread_local_init_once, thread_local_init); 131 if (g_thread_local_failed) { 132 return NULL; 133 } 134 135 void **pointers = pthread_getspecific(g_thread_local_key); 136 if (pointers == NULL) { 137 return NULL; 138 } 139 return pointers[index]; 140 } 141 142 int CRYPTO_set_thread_local(thread_local_data_t index, void *value, 143 thread_local_destructor_t destructor) { 144 CRYPTO_once(&g_thread_local_init_once, thread_local_init); 145 if (g_thread_local_failed) { 146 destructor(value); 147 return 0; 148 } 149 150 void **pointers = pthread_getspecific(g_thread_local_key); 151 if (pointers == NULL) { 152 pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); 153 if (pointers == NULL) { 154 destructor(value); 155 return 0; 156 } 157 OPENSSL_memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); 158 if (pthread_setspecific(g_thread_local_key, pointers) != 0) { 159 OPENSSL_free(pointers); 160 destructor(value); 161 return 0; 162 } 163 } 164 165 if (pthread_mutex_lock(&g_destructors_lock) != 0) { 166 destructor(value); 167 return 0; 168 } 169 g_destructors[index] = destructor; 170 pthread_mutex_unlock(&g_destructors_lock); 171 172 pointers[index] = value; 173 return 1; 174 } 175 176 #endif /* OPENSSL_PTHREADS */ 177