blob: 74c8ed204c46ffda7ef5aa8a208697d101ef213d [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
Christopher Ferris795034c2018-09-07 14:10:12 -070031bool HasMembarrier(int membarrier_cmd) {
Orion Hodson6ba66942018-08-30 11:10:23 +010032 ScopedErrnoCleaner errno_cleaner;
Christopher Ferris795034c2018-09-07 14:10:12 -070033 bool present = syscall(__NR_membarrier, membarrier_cmd, 0) > 0;
Orion Hodson6ba66942018-08-30 11:10:23 +010034 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) {
Christopher Ferris795034c2018-09-07 14:10:12 -070048 if (!HasMembarrier(MEMBARRIER_CMD_GLOBAL)) {
49 GTEST_LOG_(INFO) << "MEMBARRIER_CMD_GLOBAL not supported, skipping test.";
Orion Hodson6ba66942018-08-30 11:10:23 +010050 return;
51 }
52
53 ScopedErrnoCleaner errno_cleaner;
54 int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
55 ASSERT_LE(0, supported);
56
57 if ((supported & MEMBARRIER_CMD_GLOBAL) != 0) {
58 ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0));
59 }
60}
61
Christopher Ferris795034c2018-09-07 14:10:12 -070062static const char* MembarrierCommandToName(int membarrier_cmd) {
63 switch (membarrier_cmd) {
64 case MEMBARRIER_CMD_QUERY:
65 return "MEMBARRIER_CMD_QUERY";
66 case MEMBARRIER_CMD_GLOBAL:
67 return "MEMBARRIER_CMD_GLOBAL";
68 case MEMBARRIER_CMD_GLOBAL_EXPEDITED:
69 return "MEMBARRIER_CMD_GLOBAL_EXPEDITED";
70 case MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
71 return "MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED";
72 case MEMBARRIER_CMD_PRIVATE_EXPEDITED:
73 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED";
74 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
75 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED";
76 case MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE:
77 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE";
78 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE:
79 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE";
80 default:
81 return "MEMBARRIER_UNKNOWN";
82 }
83}
84
Orion Hodson6ba66942018-08-30 11:10:23 +010085static void TestRegisterAndBarrierCommands(int membarrier_cmd_register,
86 int membarrier_cmd_barrier) {
Christopher Ferris795034c2018-09-07 14:10:12 -070087 if (!HasMembarrier(membarrier_cmd_register)) {
88 GTEST_LOG_(INFO) << MembarrierCommandToName(membarrier_cmd_register)
89 << " not supported, skipping test.";
90 return;
91 }
92 if (!HasMembarrier(membarrier_cmd_barrier)) {
93 GTEST_LOG_(INFO) << MembarrierCommandToName(membarrier_cmd_barrier)
94 << " not supported, skipping test.";
Orion Hodson6ba66942018-08-30 11:10:23 +010095 return;
96 }
97
98 ScopedErrnoCleaner errno_cleaner;
99
100 // Check barrier use without prior registration.
101 if (membarrier_cmd_register == MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED) {
102 // Global barrier use is always okay.
103 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
104 } else {
105 // Private barrier should fail.
106 ASSERT_EQ(-1, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
107 ASSERT_EQ(EPERM, errno);
108 errno = 0;
109 }
110
111 // Check registration for barrier succeeds.
112 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_register, 0));
113
114 // Check barrier use after registration succeeds.
115 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
116}
117
118TEST(membarrier, global_expedited) {
119 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
120 MEMBARRIER_CMD_GLOBAL_EXPEDITED);
121}
122
123TEST(membarrier, private_expedited) {
124 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
125 MEMBARRIER_CMD_PRIVATE_EXPEDITED);
126}
127
128TEST(membarrier, private_expedited_sync_core) {
129 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
130 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE);
131}
132
133#endif // __BIONIC__