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 <thread>
7 #include <random>
8
9 #include <xnnpack.h>
10 #include <xnnpack/common.h>
11 #include <xnnpack/mutex.h>
12
13 #include <gtest/gtest.h>
14
TEST(MUTEX,init_lock_unlock_destroy)15 TEST(MUTEX, init_lock_unlock_destroy) {
16
17 xnn_mutex m;
18 ASSERT_EQ(xnn_status_success, xnn_mutex_init(&m));
19 ASSERT_EQ(xnn_status_success, xnn_mutex_lock(&m));
20 ASSERT_EQ(xnn_status_success, xnn_mutex_unlock(&m));
21 ASSERT_EQ(xnn_status_success, xnn_mutex_destroy(&m));
22 }
23
TEST(MUTEX,counter)24 TEST(MUTEX, counter) {
25 // Skip if we are not targeting pthread.
26 #if XNN_PLATFORM_WEB && !defined(__EMSCRIPTEN_PTHREADS__)
27 GTEST_SKIP();
28 #endif
29
30 xnn_mutex m;
31 constexpr size_t num_threads = 50;
32 std::vector<std::thread> threads;
33 threads.reserve(num_threads);
34 volatile size_t counter = 0;
35
36 std::random_device random_device;
37 auto rng = std::mt19937(random_device());
38 auto dist = std::uniform_int_distribution<int>(100, 200);
39
40 ASSERT_EQ(xnn_status_success, xnn_mutex_init(&m));
41
42 for (size_t i = 0; i < num_threads; i++) {
43 threads.emplace_back(([&] () {
44 ASSERT_EQ(xnn_status_success, xnn_mutex_lock(&m));
45 std::this_thread::sleep_for(std::chrono::milliseconds(dist(rng)));
46 counter += 1;
47 ASSERT_EQ(xnn_status_success, xnn_mutex_unlock(&m));
48 }));
49 }
50
51 for (int i = num_threads - 1; i >= 0; i--) {
52 threads[i].join();
53 }
54
55 ASSERT_EQ(counter, num_threads);
56 ASSERT_EQ(xnn_status_success, xnn_mutex_destroy(&m));
57 }
58