// Copyright 2022 Google LLC // // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. #include #include #include #include #include #if XNN_PLATFORM_WINDOWS #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS #include #else #include #endif enum xnn_status xnn_mutex_init(struct xnn_mutex* mutex) { #if XNN_PLATFORM_WINDOWS mutex->handle = CreateMutexW( /* security attributes */ NULL, /* initially owned */ FALSE, /* name */ NULL); if (mutex->handle == NULL) { xnn_log_error("failed to initialize mutex, error code: %" PRIu32, (uint32_t) GetLastError()); return xnn_status_out_of_memory; } #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS mutex->semaphore = dispatch_semaphore_create(1); if (mutex->semaphore == NULL) { xnn_log_error("failed to initialize mutex"); return xnn_status_out_of_memory; } #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) const int ret = pthread_mutex_init(&mutex->mutex, NULL); if (ret != 0) { xnn_log_error("failed to initialize mutex, error code: %d", ret); return xnn_status_out_of_memory; } #endif return xnn_status_success; } enum xnn_status xnn_mutex_lock(struct xnn_mutex* mutex) { #if XNN_PLATFORM_WINDOWS const DWORD wait_result = WaitForSingleObject(mutex->handle, INFINITE); if (WAIT_OBJECT_0 != wait_result) { xnn_log_error("failed to lock mutex, error code: %" PRIu32, (uint32_t) wait_result); return xnn_status_invalid_state; } #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS const int wait_result = dispatch_semaphore_wait(mutex->semaphore, DISPATCH_TIME_FOREVER); if (0 != wait_result) { xnn_log_error("failed to lock mutex, error code: %d", wait_result); return xnn_status_invalid_state; } #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) const int ret = pthread_mutex_lock(&mutex->mutex); if (ret != 0) { xnn_log_error("failed to lock mutex, error code: %d", ret); return xnn_status_invalid_state; } #endif return xnn_status_success; } enum xnn_status xnn_mutex_unlock(struct xnn_mutex* mutex) { #if XNN_PLATFORM_WINDOWS if (ReleaseMutex(mutex->handle) == 0) { xnn_log_error("failed to unlock mutex, error code: %" PRIu32, (uint32_t) GetLastError()); return xnn_status_invalid_state; } #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS dispatch_semaphore_signal(mutex->semaphore); #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) const int ret = pthread_mutex_unlock(&mutex->mutex); if (ret != 0) { xnn_log_error("failed to unlock mutex, error code: %d", ret); return xnn_status_invalid_state; } #endif return xnn_status_success; } enum xnn_status xnn_mutex_destroy(struct xnn_mutex* mutex) { #if XNN_PLATFORM_WINDOWS if (CloseHandle(mutex->handle) == 0) { xnn_log_error("failed to destroy mutex, error code: %" PRIu32, (uint32_t) GetLastError()); return xnn_status_invalid_state; } #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS dispatch_release(mutex->semaphore); #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) const int ret = pthread_mutex_destroy(&mutex->mutex); if (ret != 0) { xnn_log_error("failed to destroy mutex, error code: %d", ret); return xnn_status_invalid_state; } #endif memset(mutex, 0, sizeof(struct xnn_mutex)); return xnn_status_success; }