blob: 4c58d308eef5417e11291ba73dcd801c44c8936c [file] [log] [blame]
Orion Hodson6ba66942018-08-30 11:10:23 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19// membarrier(2) is only supported for bionic builds (b/111199492).
20#if defined(__BIONIC__)
21
22#include <linux/membarrier.h>
23#include <sys/syscall.h>
24
25class ScopedErrnoCleaner {
26 public:
27 ScopedErrnoCleaner() { errno = 0; }
28 ~ScopedErrnoCleaner() { errno = 0; }
29};
30
31bool HasMembarrier() {
32 ScopedErrnoCleaner errno_cleaner;
33 bool present = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0) > 0;
34 return present;
35}
36
37TEST(membarrier, query) {
38 ScopedErrnoCleaner errno_cleaner;
39 int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
40 if (errno == 0) {
41 ASSERT_TRUE(supported >= 0);
42 } else {
43 ASSERT_TRUE(errno == ENOSYS && supported == -1);
44 }
45}
46
47TEST(membarrier, global_barrier) {
48 if (!HasMembarrier()) {
49 return;
50 }
51
52 ScopedErrnoCleaner errno_cleaner;
53 int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
54 ASSERT_LE(0, supported);
55
56 if ((supported & MEMBARRIER_CMD_GLOBAL) != 0) {
57 ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0));
58 }
59}
60
61static void TestRegisterAndBarrierCommands(int membarrier_cmd_register,
62 int membarrier_cmd_barrier) {
63 if (!HasMembarrier()) {
64 return;
65 }
66
67 ScopedErrnoCleaner errno_cleaner;
68
69 // Check barrier use without prior registration.
70 if (membarrier_cmd_register == MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED) {
71 // Global barrier use is always okay.
72 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
73 } else {
74 // Private barrier should fail.
75 ASSERT_EQ(-1, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
76 ASSERT_EQ(EPERM, errno);
77 errno = 0;
78 }
79
80 // Check registration for barrier succeeds.
81 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_register, 0));
82
83 // Check barrier use after registration succeeds.
84 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
85}
86
87TEST(membarrier, global_expedited) {
88 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
89 MEMBARRIER_CMD_GLOBAL_EXPEDITED);
90}
91
92TEST(membarrier, private_expedited) {
93 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
94 MEMBARRIER_CMD_PRIVATE_EXPEDITED);
95}
96
97TEST(membarrier, private_expedited_sync_core) {
98 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
99 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE);
100}
101
102#endif // __BIONIC__