1a8e1175bSopenharmony_ci/** Mutex usage verification framework. */ 2a8e1175bSopenharmony_ci 3a8e1175bSopenharmony_ci/* 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci#include <test/helpers.h> 9a8e1175bSopenharmony_ci#include <test/threading_helpers.h> 10a8e1175bSopenharmony_ci#include <test/macros.h> 11a8e1175bSopenharmony_ci 12a8e1175bSopenharmony_ci#include "mbedtls/threading.h" 13a8e1175bSopenharmony_ci 14a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C) 15a8e1175bSopenharmony_ci 16a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_PTHREAD) 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_cistatic int threading_thread_create_pthread(mbedtls_test_thread_t *thread, void *(*thread_func)( 19a8e1175bSopenharmony_ci void *), void *thread_data) 20a8e1175bSopenharmony_ci{ 21a8e1175bSopenharmony_ci if (thread == NULL || thread_func == NULL) { 22a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; 23a8e1175bSopenharmony_ci } 24a8e1175bSopenharmony_ci 25a8e1175bSopenharmony_ci if (pthread_create(&thread->thread, NULL, thread_func, thread_data)) { 26a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_THREAD_ERROR; 27a8e1175bSopenharmony_ci } 28a8e1175bSopenharmony_ci 29a8e1175bSopenharmony_ci return 0; 30a8e1175bSopenharmony_ci} 31a8e1175bSopenharmony_ci 32a8e1175bSopenharmony_cistatic int threading_thread_join_pthread(mbedtls_test_thread_t *thread) 33a8e1175bSopenharmony_ci{ 34a8e1175bSopenharmony_ci if (thread == NULL) { 35a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; 36a8e1175bSopenharmony_ci } 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ci if (pthread_join(thread->thread, NULL) != 0) { 39a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_THREAD_ERROR; 40a8e1175bSopenharmony_ci } 41a8e1175bSopenharmony_ci 42a8e1175bSopenharmony_ci return 0; 43a8e1175bSopenharmony_ci} 44a8e1175bSopenharmony_ci 45a8e1175bSopenharmony_ciint (*mbedtls_test_thread_create)(mbedtls_test_thread_t *thread, void *(*thread_func)(void *), 46a8e1175bSopenharmony_ci void *thread_data) = threading_thread_create_pthread; 47a8e1175bSopenharmony_ciint (*mbedtls_test_thread_join)(mbedtls_test_thread_t *thread) = threading_thread_join_pthread; 48a8e1175bSopenharmony_ci 49a8e1175bSopenharmony_ci#endif /* MBEDTLS_THREADING_PTHREAD */ 50a8e1175bSopenharmony_ci 51a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_ALT) 52a8e1175bSopenharmony_ci 53a8e1175bSopenharmony_cistatic int threading_thread_create_fail(mbedtls_test_thread_t *thread, 54a8e1175bSopenharmony_ci void *(*thread_func)(void *), 55a8e1175bSopenharmony_ci void *thread_data) 56a8e1175bSopenharmony_ci{ 57a8e1175bSopenharmony_ci (void) thread; 58a8e1175bSopenharmony_ci (void) thread_func; 59a8e1175bSopenharmony_ci (void) thread_data; 60a8e1175bSopenharmony_ci 61a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; 62a8e1175bSopenharmony_ci} 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_cistatic int threading_thread_join_fail(mbedtls_test_thread_t *thread) 65a8e1175bSopenharmony_ci{ 66a8e1175bSopenharmony_ci (void) thread; 67a8e1175bSopenharmony_ci 68a8e1175bSopenharmony_ci return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; 69a8e1175bSopenharmony_ci} 70a8e1175bSopenharmony_ci 71a8e1175bSopenharmony_ciint (*mbedtls_test_thread_create)(mbedtls_test_thread_t *thread, void *(*thread_func)(void *), 72a8e1175bSopenharmony_ci void *thread_data) = threading_thread_create_fail; 73a8e1175bSopenharmony_ciint (*mbedtls_test_thread_join)(mbedtls_test_thread_t *thread) = threading_thread_join_fail; 74a8e1175bSopenharmony_ci 75a8e1175bSopenharmony_ci#endif /* MBEDTLS_THREADING_ALT */ 76a8e1175bSopenharmony_ci 77a8e1175bSopenharmony_ci#if defined(MBEDTLS_TEST_MUTEX_USAGE) 78a8e1175bSopenharmony_ci 79a8e1175bSopenharmony_ci#include "mbedtls/threading.h" 80a8e1175bSopenharmony_ci 81a8e1175bSopenharmony_ci/** Mutex usage verification framework. 82a8e1175bSopenharmony_ci * 83a8e1175bSopenharmony_ci * The mutex usage verification code below aims to detect bad usage of 84a8e1175bSopenharmony_ci * Mbed TLS's mutex abstraction layer at runtime. Note that this is solely 85a8e1175bSopenharmony_ci * about the use of the mutex itself, not about checking whether the mutex 86a8e1175bSopenharmony_ci * correctly protects whatever it is supposed to protect. 87a8e1175bSopenharmony_ci * 88a8e1175bSopenharmony_ci * The normal usage of a mutex is: 89a8e1175bSopenharmony_ci * ``` 90a8e1175bSopenharmony_ci * digraph mutex_states { 91a8e1175bSopenharmony_ci * "UNINITIALIZED"; // the initial state 92a8e1175bSopenharmony_ci * "IDLE"; 93a8e1175bSopenharmony_ci * "FREED"; 94a8e1175bSopenharmony_ci * "LOCKED"; 95a8e1175bSopenharmony_ci * "UNINITIALIZED" -> "IDLE" [label="init"]; 96a8e1175bSopenharmony_ci * "FREED" -> "IDLE" [label="init"]; 97a8e1175bSopenharmony_ci * "IDLE" -> "LOCKED" [label="lock"]; 98a8e1175bSopenharmony_ci * "LOCKED" -> "IDLE" [label="unlock"]; 99a8e1175bSopenharmony_ci * "IDLE" -> "FREED" [label="free"]; 100a8e1175bSopenharmony_ci * } 101a8e1175bSopenharmony_ci * ``` 102a8e1175bSopenharmony_ci * 103a8e1175bSopenharmony_ci * All bad transitions that can be unambiguously detected are reported. 104a8e1175bSopenharmony_ci * An attempt to use an uninitialized mutex cannot be detected in general 105a8e1175bSopenharmony_ci * since the memory content may happen to denote a valid state. For the same 106a8e1175bSopenharmony_ci * reason, a double init cannot be detected. 107a8e1175bSopenharmony_ci * All-bits-zero is the state of a freed mutex, which is distinct from an 108a8e1175bSopenharmony_ci * initialized mutex, so attempting to use zero-initialized memory as a mutex 109a8e1175bSopenharmony_ci * without calling the init function is detected. 110a8e1175bSopenharmony_ci * 111a8e1175bSopenharmony_ci * The framework attempts to detect missing calls to init and free by counting 112a8e1175bSopenharmony_ci * calls to init and free. If there are more calls to init than free, this 113a8e1175bSopenharmony_ci * means that a mutex is not being freed somewhere, which is a memory leak 114a8e1175bSopenharmony_ci * on platforms where a mutex consumes resources other than the 115a8e1175bSopenharmony_ci * mbedtls_threading_mutex_t object itself. If there are more calls to free 116a8e1175bSopenharmony_ci * than init, this indicates a missing init, which is likely to be detected 117a8e1175bSopenharmony_ci * by an attempt to lock the mutex as well. A limitation of this framework is 118a8e1175bSopenharmony_ci * that it cannot detect scenarios where there is exactly the same number of 119a8e1175bSopenharmony_ci * calls to init and free but the calls don't match. A bug like this is 120a8e1175bSopenharmony_ci * unlikely to happen uniformly throughout the whole test suite though. 121a8e1175bSopenharmony_ci * 122a8e1175bSopenharmony_ci * If an error is detected, this framework will report what happened and the 123a8e1175bSopenharmony_ci * test case will be marked as failed. Unfortunately, the error report cannot 124a8e1175bSopenharmony_ci * indicate the exact location of the problematic call. To locate the error, 125a8e1175bSopenharmony_ci * use a debugger and set a breakpoint on mbedtls_test_mutex_usage_error(). 126a8e1175bSopenharmony_ci */ 127a8e1175bSopenharmony_cienum value_of_mutex_state_field { 128a8e1175bSopenharmony_ci /* Potential values for the state field of mbedtls_threading_mutex_t. 129a8e1175bSopenharmony_ci * Note that MUTEX_FREED must be 0 and MUTEX_IDLE must be 1 for 130a8e1175bSopenharmony_ci * compatibility with threading_mutex_init_pthread() and 131a8e1175bSopenharmony_ci * threading_mutex_free_pthread(). MUTEX_LOCKED could be any nonzero 132a8e1175bSopenharmony_ci * value. */ 133a8e1175bSopenharmony_ci MUTEX_FREED = 0, //! < Set by mbedtls_test_wrap_mutex_free 134a8e1175bSopenharmony_ci MUTEX_IDLE = 1, //! < Set by mbedtls_test_wrap_mutex_init and by mbedtls_test_wrap_mutex_unlock 135a8e1175bSopenharmony_ci MUTEX_LOCKED = 2, //! < Set by mbedtls_test_wrap_mutex_lock 136a8e1175bSopenharmony_ci}; 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_citypedef struct { 139a8e1175bSopenharmony_ci void (*init)(mbedtls_threading_mutex_t *); 140a8e1175bSopenharmony_ci void (*free)(mbedtls_threading_mutex_t *); 141a8e1175bSopenharmony_ci int (*lock)(mbedtls_threading_mutex_t *); 142a8e1175bSopenharmony_ci int (*unlock)(mbedtls_threading_mutex_t *); 143a8e1175bSopenharmony_ci} mutex_functions_t; 144a8e1175bSopenharmony_cistatic mutex_functions_t mutex_functions; 145a8e1175bSopenharmony_ci 146a8e1175bSopenharmony_ci/** 147a8e1175bSopenharmony_ci * The mutex used to guard live_mutexes below and access to the status variable 148a8e1175bSopenharmony_ci * in every mbedtls_threading_mutex_t. 149a8e1175bSopenharmony_ci * Note that we are not reporting any errors when locking and unlocking this 150a8e1175bSopenharmony_ci * mutex. This is for a couple of reasons: 151a8e1175bSopenharmony_ci * 152a8e1175bSopenharmony_ci * 1. We have no real way of reporting any errors with this mutex - we cannot 153a8e1175bSopenharmony_ci * report it back to the caller, as the failure was not that of the mutex 154a8e1175bSopenharmony_ci * passed in. We could fail the test, but again this would indicate a problem 155a8e1175bSopenharmony_ci * with the test code that did not exist. 156a8e1175bSopenharmony_ci * 157a8e1175bSopenharmony_ci * 2. Any failure to lock is unlikely to be intermittent, and will thus not 158a8e1175bSopenharmony_ci * give false test results - the overall result would be to turn off the 159a8e1175bSopenharmony_ci * testing. This is not a situation that is likely to happen with normal 160a8e1175bSopenharmony_ci * testing and we still have TSan to fall back on should this happen. 161a8e1175bSopenharmony_ci */ 162a8e1175bSopenharmony_cimbedtls_threading_mutex_t mbedtls_test_mutex_mutex; 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci/** 165a8e1175bSopenharmony_ci * The total number of calls to mbedtls_mutex_init(), minus the total number 166a8e1175bSopenharmony_ci * of calls to mbedtls_mutex_free(). 167a8e1175bSopenharmony_ci * 168a8e1175bSopenharmony_ci * Do not read or write without holding mbedtls_test_mutex_mutex (above). Reset 169a8e1175bSopenharmony_ci * to 0 after each test case. 170a8e1175bSopenharmony_ci */ 171a8e1175bSopenharmony_cistatic int live_mutexes; 172a8e1175bSopenharmony_ci 173a8e1175bSopenharmony_cistatic void mbedtls_test_mutex_usage_error(mbedtls_threading_mutex_t *mutex, 174a8e1175bSopenharmony_ci const char *msg) 175a8e1175bSopenharmony_ci{ 176a8e1175bSopenharmony_ci (void) mutex; 177a8e1175bSopenharmony_ci 178a8e1175bSopenharmony_ci mbedtls_test_set_mutex_usage_error(msg); 179a8e1175bSopenharmony_ci mbedtls_fprintf(stdout, "[mutex: %s] ", msg); 180a8e1175bSopenharmony_ci /* Don't mark the test as failed yet. This way, if the test fails later 181a8e1175bSopenharmony_ci * for a functional reason, the test framework will report the message 182a8e1175bSopenharmony_ci * and location for this functional reason. If the test passes, 183a8e1175bSopenharmony_ci * mbedtls_test_mutex_usage_check() will mark it as failed. */ 184a8e1175bSopenharmony_ci} 185a8e1175bSopenharmony_ci 186a8e1175bSopenharmony_cistatic int mbedtls_test_mutex_can_test(mbedtls_threading_mutex_t *mutex) 187a8e1175bSopenharmony_ci{ 188a8e1175bSopenharmony_ci /* If we attempt to run tests on this mutex then we are going to run into a 189a8e1175bSopenharmony_ci * couple of problems: 190a8e1175bSopenharmony_ci * 1. If any test on this mutex fails, we are going to deadlock when 191a8e1175bSopenharmony_ci * reporting that failure, as we already hold the mutex at that point. 192a8e1175bSopenharmony_ci * 2. Given the 'global' position of the initialization and free of this 193a8e1175bSopenharmony_ci * mutex, it will be shown as leaked on the first test run. */ 194a8e1175bSopenharmony_ci if (mutex == mbedtls_test_get_info_mutex()) { 195a8e1175bSopenharmony_ci return 0; 196a8e1175bSopenharmony_ci } 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci return 1; 199a8e1175bSopenharmony_ci} 200a8e1175bSopenharmony_ci 201a8e1175bSopenharmony_cistatic void mbedtls_test_wrap_mutex_init(mbedtls_threading_mutex_t *mutex) 202a8e1175bSopenharmony_ci{ 203a8e1175bSopenharmony_ci mutex_functions.init(mutex); 204a8e1175bSopenharmony_ci 205a8e1175bSopenharmony_ci if (mbedtls_test_mutex_can_test(mutex)) { 206a8e1175bSopenharmony_ci if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { 207a8e1175bSopenharmony_ci mutex->state = MUTEX_IDLE; 208a8e1175bSopenharmony_ci ++live_mutexes; 209a8e1175bSopenharmony_ci 210a8e1175bSopenharmony_ci mutex_functions.unlock(&mbedtls_test_mutex_mutex); 211a8e1175bSopenharmony_ci } 212a8e1175bSopenharmony_ci } 213a8e1175bSopenharmony_ci} 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_cistatic void mbedtls_test_wrap_mutex_free(mbedtls_threading_mutex_t *mutex) 216a8e1175bSopenharmony_ci{ 217a8e1175bSopenharmony_ci if (mbedtls_test_mutex_can_test(mutex)) { 218a8e1175bSopenharmony_ci if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { 219a8e1175bSopenharmony_ci 220a8e1175bSopenharmony_ci switch (mutex->state) { 221a8e1175bSopenharmony_ci case MUTEX_FREED: 222a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "free without init or double free"); 223a8e1175bSopenharmony_ci break; 224a8e1175bSopenharmony_ci case MUTEX_IDLE: 225a8e1175bSopenharmony_ci mutex->state = MUTEX_FREED; 226a8e1175bSopenharmony_ci --live_mutexes; 227a8e1175bSopenharmony_ci break; 228a8e1175bSopenharmony_ci case MUTEX_LOCKED: 229a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "free without unlock"); 230a8e1175bSopenharmony_ci break; 231a8e1175bSopenharmony_ci default: 232a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "corrupted state"); 233a8e1175bSopenharmony_ci break; 234a8e1175bSopenharmony_ci } 235a8e1175bSopenharmony_ci 236a8e1175bSopenharmony_ci mutex_functions.unlock(&mbedtls_test_mutex_mutex); 237a8e1175bSopenharmony_ci } 238a8e1175bSopenharmony_ci } 239a8e1175bSopenharmony_ci 240a8e1175bSopenharmony_ci mutex_functions.free(mutex); 241a8e1175bSopenharmony_ci} 242a8e1175bSopenharmony_ci 243a8e1175bSopenharmony_cistatic int mbedtls_test_wrap_mutex_lock(mbedtls_threading_mutex_t *mutex) 244a8e1175bSopenharmony_ci{ 245a8e1175bSopenharmony_ci /* Lock the passed in mutex first, so that the only way to change the state 246a8e1175bSopenharmony_ci * is to hold the passed in and internal mutex - otherwise we create a race 247a8e1175bSopenharmony_ci * condition. */ 248a8e1175bSopenharmony_ci int ret = mutex_functions.lock(mutex); 249a8e1175bSopenharmony_ci 250a8e1175bSopenharmony_ci if (mbedtls_test_mutex_can_test(mutex)) { 251a8e1175bSopenharmony_ci if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { 252a8e1175bSopenharmony_ci switch (mutex->state) { 253a8e1175bSopenharmony_ci case MUTEX_FREED: 254a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "lock without init"); 255a8e1175bSopenharmony_ci break; 256a8e1175bSopenharmony_ci case MUTEX_IDLE: 257a8e1175bSopenharmony_ci if (ret == 0) { 258a8e1175bSopenharmony_ci mutex->state = MUTEX_LOCKED; 259a8e1175bSopenharmony_ci } 260a8e1175bSopenharmony_ci break; 261a8e1175bSopenharmony_ci case MUTEX_LOCKED: 262a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "double lock"); 263a8e1175bSopenharmony_ci break; 264a8e1175bSopenharmony_ci default: 265a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "corrupted state"); 266a8e1175bSopenharmony_ci break; 267a8e1175bSopenharmony_ci } 268a8e1175bSopenharmony_ci 269a8e1175bSopenharmony_ci mutex_functions.unlock(&mbedtls_test_mutex_mutex); 270a8e1175bSopenharmony_ci } 271a8e1175bSopenharmony_ci } 272a8e1175bSopenharmony_ci 273a8e1175bSopenharmony_ci return ret; 274a8e1175bSopenharmony_ci} 275a8e1175bSopenharmony_ci 276a8e1175bSopenharmony_cistatic int mbedtls_test_wrap_mutex_unlock(mbedtls_threading_mutex_t *mutex) 277a8e1175bSopenharmony_ci{ 278a8e1175bSopenharmony_ci /* Lock the internal mutex first and change state, so that the only way to 279a8e1175bSopenharmony_ci * change the state is to hold the passed in and internal mutex - otherwise 280a8e1175bSopenharmony_ci * we create a race condition. */ 281a8e1175bSopenharmony_ci if (mbedtls_test_mutex_can_test(mutex)) { 282a8e1175bSopenharmony_ci if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { 283a8e1175bSopenharmony_ci switch (mutex->state) { 284a8e1175bSopenharmony_ci case MUTEX_FREED: 285a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "unlock without init"); 286a8e1175bSopenharmony_ci break; 287a8e1175bSopenharmony_ci case MUTEX_IDLE: 288a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "unlock without lock"); 289a8e1175bSopenharmony_ci break; 290a8e1175bSopenharmony_ci case MUTEX_LOCKED: 291a8e1175bSopenharmony_ci mutex->state = MUTEX_IDLE; 292a8e1175bSopenharmony_ci break; 293a8e1175bSopenharmony_ci default: 294a8e1175bSopenharmony_ci mbedtls_test_mutex_usage_error(mutex, "corrupted state"); 295a8e1175bSopenharmony_ci break; 296a8e1175bSopenharmony_ci } 297a8e1175bSopenharmony_ci mutex_functions.unlock(&mbedtls_test_mutex_mutex); 298a8e1175bSopenharmony_ci } 299a8e1175bSopenharmony_ci } 300a8e1175bSopenharmony_ci 301a8e1175bSopenharmony_ci return mutex_functions.unlock(mutex); 302a8e1175bSopenharmony_ci} 303a8e1175bSopenharmony_ci 304a8e1175bSopenharmony_civoid mbedtls_test_mutex_usage_init(void) 305a8e1175bSopenharmony_ci{ 306a8e1175bSopenharmony_ci mutex_functions.init = mbedtls_mutex_init; 307a8e1175bSopenharmony_ci mutex_functions.free = mbedtls_mutex_free; 308a8e1175bSopenharmony_ci mutex_functions.lock = mbedtls_mutex_lock; 309a8e1175bSopenharmony_ci mutex_functions.unlock = mbedtls_mutex_unlock; 310a8e1175bSopenharmony_ci mbedtls_mutex_init = &mbedtls_test_wrap_mutex_init; 311a8e1175bSopenharmony_ci mbedtls_mutex_free = &mbedtls_test_wrap_mutex_free; 312a8e1175bSopenharmony_ci mbedtls_mutex_lock = &mbedtls_test_wrap_mutex_lock; 313a8e1175bSopenharmony_ci mbedtls_mutex_unlock = &mbedtls_test_wrap_mutex_unlock; 314a8e1175bSopenharmony_ci 315a8e1175bSopenharmony_ci mutex_functions.init(&mbedtls_test_mutex_mutex); 316a8e1175bSopenharmony_ci} 317a8e1175bSopenharmony_ci 318a8e1175bSopenharmony_civoid mbedtls_test_mutex_usage_check(void) 319a8e1175bSopenharmony_ci{ 320a8e1175bSopenharmony_ci if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { 321a8e1175bSopenharmony_ci if (live_mutexes != 0) { 322a8e1175bSopenharmony_ci /* A positive number (more init than free) means that a mutex resource 323a8e1175bSopenharmony_ci * is leaking (on platforms where a mutex consumes more than the 324a8e1175bSopenharmony_ci * mbedtls_threading_mutex_t object itself). The (hopefully) rare 325a8e1175bSopenharmony_ci * case of a negative number means a missing init somewhere. */ 326a8e1175bSopenharmony_ci mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes); 327a8e1175bSopenharmony_ci live_mutexes = 0; 328a8e1175bSopenharmony_ci mbedtls_test_set_mutex_usage_error("missing free"); 329a8e1175bSopenharmony_ci } 330a8e1175bSopenharmony_ci if (mbedtls_test_get_mutex_usage_error() != NULL && 331a8e1175bSopenharmony_ci mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) { 332a8e1175bSopenharmony_ci /* Functionally, the test passed. But there was a mutex usage error, 333a8e1175bSopenharmony_ci * so mark the test as failed after all. */ 334a8e1175bSopenharmony_ci mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__); 335a8e1175bSopenharmony_ci } 336a8e1175bSopenharmony_ci mbedtls_test_set_mutex_usage_error(NULL); 337a8e1175bSopenharmony_ci 338a8e1175bSopenharmony_ci mutex_functions.unlock(&mbedtls_test_mutex_mutex); 339a8e1175bSopenharmony_ci } 340a8e1175bSopenharmony_ci} 341a8e1175bSopenharmony_ci 342a8e1175bSopenharmony_civoid mbedtls_test_mutex_usage_end(void) 343a8e1175bSopenharmony_ci{ 344a8e1175bSopenharmony_ci mbedtls_mutex_init = mutex_functions.init; 345a8e1175bSopenharmony_ci mbedtls_mutex_free = mutex_functions.free; 346a8e1175bSopenharmony_ci mbedtls_mutex_lock = mutex_functions.lock; 347a8e1175bSopenharmony_ci mbedtls_mutex_unlock = mutex_functions.unlock; 348a8e1175bSopenharmony_ci 349a8e1175bSopenharmony_ci mutex_functions.free(&mbedtls_test_mutex_mutex); 350a8e1175bSopenharmony_ci} 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci#endif /* MBEDTLS_TEST_MUTEX_USAGE */ 353a8e1175bSopenharmony_ci 354a8e1175bSopenharmony_ci#endif /* MBEDTLS_THREADING_C */ 355