blob: a937d830d29ab4679fa2fb27e50c30e91200dd04 [file] [log] [blame] [edit]
// 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 <string.h>
#include <xnnpack.h>
#include <xnnpack/common.h>
#include <xnnpack/log.h>
#include <xnnpack/mutex.h>
#if XNN_PLATFORM_WINDOWS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS
#include <dispatch/dispatch.h>
#else
#include <pthread.h>
#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;
}