blob: 6f650e712b262348d8dcaecba43ed6f96d141970 [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;
Orion Hodson0c938552018-09-10 10:21:40 +010033 int supported_cmds = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
34 return (supported_cmds > 0) && ((supported_cmds & membarrier_cmd) != 0);
Orion Hodson6ba66942018-08-30 11:10:23 +010035}
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)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080049 GTEST_SKIP() << "MEMBARRIER_CMD_GLOBAL not supported";
Orion Hodson6ba66942018-08-30 11:10:23 +010050 }
Orion Hodson0c938552018-09-10 10:21:40 +010051 ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0));
Orion Hodson6ba66942018-08-30 11:10:23 +010052}
53
Christopher Ferris795034c2018-09-07 14:10:12 -070054static const char* MembarrierCommandToName(int membarrier_cmd) {
55 switch (membarrier_cmd) {
56 case MEMBARRIER_CMD_QUERY:
57 return "MEMBARRIER_CMD_QUERY";
58 case MEMBARRIER_CMD_GLOBAL:
59 return "MEMBARRIER_CMD_GLOBAL";
60 case MEMBARRIER_CMD_GLOBAL_EXPEDITED:
61 return "MEMBARRIER_CMD_GLOBAL_EXPEDITED";
62 case MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
63 return "MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED";
64 case MEMBARRIER_CMD_PRIVATE_EXPEDITED:
65 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED";
66 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
67 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED";
68 case MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE:
69 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE";
70 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE:
71 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE";
72 default:
73 return "MEMBARRIER_UNKNOWN";
74 }
75}
76
Orion Hodson6ba66942018-08-30 11:10:23 +010077static void TestRegisterAndBarrierCommands(int membarrier_cmd_register,
78 int membarrier_cmd_barrier) {
Christopher Ferris795034c2018-09-07 14:10:12 -070079 if (!HasMembarrier(membarrier_cmd_register)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080080 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_register) << " not supported";
Christopher Ferris795034c2018-09-07 14:10:12 -070081 }
82 if (!HasMembarrier(membarrier_cmd_barrier)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080083 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_barrier) << " not supported";
Orion Hodson6ba66942018-08-30 11:10:23 +010084 }
85
86 ScopedErrnoCleaner errno_cleaner;
87
88 // Check barrier use without prior registration.
89 if (membarrier_cmd_register == MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED) {
90 // Global barrier use is always okay.
91 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
92 } else {
93 // Private barrier should fail.
94 ASSERT_EQ(-1, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
95 ASSERT_EQ(EPERM, errno);
96 errno = 0;
97 }
98
99 // Check registration for barrier succeeds.
100 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_register, 0));
101
102 // Check barrier use after registration succeeds.
103 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
104}
105
106TEST(membarrier, global_expedited) {
107 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
108 MEMBARRIER_CMD_GLOBAL_EXPEDITED);
109}
110
111TEST(membarrier, private_expedited) {
112 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
113 MEMBARRIER_CMD_PRIVATE_EXPEDITED);
114}
115
116TEST(membarrier, private_expedited_sync_core) {
117 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
118 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE);
119}
120
121#endif // __BIONIC__