1 | // Copyright 2022 Google LLC |
2 | // |
3 | // This source code is licensed under the BSD-style license found in the |
4 | // LICENSE file in the root directory of this source tree. |
5 | |
6 | #include <string.h> |
7 | |
8 | #include <xnnpack.h> |
9 | #include <xnnpack/common.h> |
10 | #include <xnnpack/log.h> |
11 | #include <xnnpack/mutex.h> |
12 | |
13 | #if XNN_PLATFORM_WINDOWS |
14 | #ifndef WIN32_LEAN_AND_MEAN |
15 | #define WIN32_LEAN_AND_MEAN |
16 | #endif |
17 | #include <windows.h> |
18 | #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS |
19 | #include <dispatch/dispatch.h> |
20 | #else |
21 | #include <pthread.h> |
22 | #endif |
23 | |
24 | enum xnn_status xnn_mutex_init(struct xnn_mutex* mutex) { |
25 | #if XNN_PLATFORM_WINDOWS |
26 | mutex->handle = CreateMutexW( |
27 | /* security attributes */ NULL, |
28 | /* initially owned */ FALSE, |
29 | /* name */ NULL); |
30 | if (mutex->handle == NULL) { |
31 | xnn_log_error("failed to initialize mutex, error code: %" PRIu32, (uint32_t) GetLastError()); |
32 | return xnn_status_out_of_memory; |
33 | } |
34 | #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS |
35 | mutex->semaphore = dispatch_semaphore_create(1); |
36 | if (mutex->semaphore == NULL) { |
37 | xnn_log_error("failed to initialize mutex" ); |
38 | return xnn_status_out_of_memory; |
39 | } |
40 | #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) |
41 | const int ret = pthread_mutex_init(&mutex->mutex, NULL); |
42 | if (ret != 0) { |
43 | xnn_log_error("failed to initialize mutex, error code: %d" , ret); |
44 | return xnn_status_out_of_memory; |
45 | } |
46 | #endif |
47 | return xnn_status_success; |
48 | } |
49 | |
50 | enum xnn_status xnn_mutex_lock(struct xnn_mutex* mutex) { |
51 | #if XNN_PLATFORM_WINDOWS |
52 | const DWORD wait_result = WaitForSingleObject(mutex->handle, INFINITE); |
53 | if (WAIT_OBJECT_0 != wait_result) { |
54 | xnn_log_error("failed to lock mutex, error code: %" PRIu32, (uint32_t) wait_result); |
55 | return xnn_status_invalid_state; |
56 | } |
57 | #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS |
58 | const int wait_result = dispatch_semaphore_wait(mutex->semaphore, DISPATCH_TIME_FOREVER); |
59 | if (0 != wait_result) { |
60 | xnn_log_error("failed to lock mutex, error code: %d" , wait_result); |
61 | return xnn_status_invalid_state; |
62 | } |
63 | #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) |
64 | const int ret = pthread_mutex_lock(&mutex->mutex); |
65 | if (ret != 0) { |
66 | xnn_log_error("failed to lock mutex, error code: %d" , ret); |
67 | return xnn_status_invalid_state; |
68 | } |
69 | #endif |
70 | return xnn_status_success; |
71 | } |
72 | |
73 | enum xnn_status xnn_mutex_unlock(struct xnn_mutex* mutex) { |
74 | #if XNN_PLATFORM_WINDOWS |
75 | if (ReleaseMutex(mutex->handle) == 0) { |
76 | xnn_log_error("failed to unlock mutex, error code: %" PRIu32, (uint32_t) GetLastError()); |
77 | return xnn_status_invalid_state; |
78 | } |
79 | #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS |
80 | dispatch_semaphore_signal(mutex->semaphore); |
81 | #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) |
82 | const int ret = pthread_mutex_unlock(&mutex->mutex); |
83 | if (ret != 0) { |
84 | xnn_log_error("failed to unlock mutex, error code: %d" , ret); |
85 | return xnn_status_invalid_state; |
86 | } |
87 | #endif |
88 | return xnn_status_success; |
89 | } |
90 | |
91 | enum xnn_status xnn_mutex_destroy(struct xnn_mutex* mutex) { |
92 | #if XNN_PLATFORM_WINDOWS |
93 | if (CloseHandle(mutex->handle) == 0) { |
94 | xnn_log_error("failed to destroy mutex, error code: %" PRIu32, (uint32_t) GetLastError()); |
95 | return xnn_status_invalid_state; |
96 | } |
97 | #elif XNN_PLATFORM_MACOS || XNN_PLATFORM_IOS |
98 | dispatch_release(mutex->semaphore); |
99 | #elif !XNN_PLATFORM_WEB || defined(__EMSCRIPTEN_PTHREADS__) |
100 | const int ret = pthread_mutex_destroy(&mutex->mutex); |
101 | if (ret != 0) { |
102 | xnn_log_error("failed to destroy mutex, error code: %d" , ret); |
103 | return xnn_status_invalid_state; |
104 | } |
105 | #endif |
106 | memset(mutex, 0, sizeof(struct xnn_mutex)); |
107 | return xnn_status_success; |
108 | } |
109 | |