aboutsummaryrefslogtreecommitdiff
path: root/src/mutex.c
blob: a937d830d29ab4679fa2fb27e50c30e91200dd04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// 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;
}