blob: 891488b899e3a09984bba1659c45c42179402dc0 [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
Elliott Hughes95646e62023-09-21 14:11:19 -070025#include "utils.h"
26
Orion Hodson6ba66942018-08-30 11:10:23 +010027class ScopedErrnoCleaner {
28 public:
29 ScopedErrnoCleaner() { errno = 0; }
30 ~ScopedErrnoCleaner() { errno = 0; }
31};
32
Christopher Ferris795034c2018-09-07 14:10:12 -070033bool HasMembarrier(int membarrier_cmd) {
Orion Hodson6ba66942018-08-30 11:10:23 +010034 ScopedErrnoCleaner errno_cleaner;
Orion Hodson0c938552018-09-10 10:21:40 +010035 int supported_cmds = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
36 return (supported_cmds > 0) && ((supported_cmds & membarrier_cmd) != 0);
Orion Hodson6ba66942018-08-30 11:10:23 +010037}
38
39TEST(membarrier, query) {
40 ScopedErrnoCleaner errno_cleaner;
41 int supported = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
42 if (errno == 0) {
43 ASSERT_TRUE(supported >= 0);
44 } else {
45 ASSERT_TRUE(errno == ENOSYS && supported == -1);
46 }
47}
48
49TEST(membarrier, global_barrier) {
Christopher Ferris795034c2018-09-07 14:10:12 -070050 if (!HasMembarrier(MEMBARRIER_CMD_GLOBAL)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080051 GTEST_SKIP() << "MEMBARRIER_CMD_GLOBAL not supported";
Orion Hodson6ba66942018-08-30 11:10:23 +010052 }
Orion Hodson0c938552018-09-10 10:21:40 +010053 ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0));
Orion Hodson6ba66942018-08-30 11:10:23 +010054}
55
Christopher Ferris795034c2018-09-07 14:10:12 -070056static const char* MembarrierCommandToName(int membarrier_cmd) {
57 switch (membarrier_cmd) {
58 case MEMBARRIER_CMD_QUERY:
59 return "MEMBARRIER_CMD_QUERY";
60 case MEMBARRIER_CMD_GLOBAL:
61 return "MEMBARRIER_CMD_GLOBAL";
62 case MEMBARRIER_CMD_GLOBAL_EXPEDITED:
63 return "MEMBARRIER_CMD_GLOBAL_EXPEDITED";
64 case MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
65 return "MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED";
66 case MEMBARRIER_CMD_PRIVATE_EXPEDITED:
67 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED";
68 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
69 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED";
70 case MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE:
71 return "MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE";
72 case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE:
73 return "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE";
74 default:
75 return "MEMBARRIER_UNKNOWN";
76 }
77}
78
Orion Hodson6ba66942018-08-30 11:10:23 +010079static void TestRegisterAndBarrierCommands(int membarrier_cmd_register,
80 int membarrier_cmd_barrier) {
Christopher Ferris795034c2018-09-07 14:10:12 -070081 if (!HasMembarrier(membarrier_cmd_register)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080082 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_register) << " not supported";
Christopher Ferris795034c2018-09-07 14:10:12 -070083 }
84 if (!HasMembarrier(membarrier_cmd_barrier)) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080085 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_barrier) << " not supported";
Orion Hodson6ba66942018-08-30 11:10:23 +010086 }
87
88 ScopedErrnoCleaner errno_cleaner;
89
90 // Check barrier use without prior registration.
91 if (membarrier_cmd_register == MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED) {
92 // Global barrier use is always okay.
93 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
94 } else {
95 // Private barrier should fail.
96 ASSERT_EQ(-1, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
Elliott Hughes95646e62023-09-21 14:11:19 -070097 ASSERT_ERRNO(EPERM);
Orion Hodson6ba66942018-08-30 11:10:23 +010098 errno = 0;
99 }
100
101 // Check registration for barrier succeeds.
102 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_register, 0));
103
104 // Check barrier use after registration succeeds.
105 ASSERT_EQ(0, syscall(__NR_membarrier, membarrier_cmd_barrier, 0));
106}
107
108TEST(membarrier, global_expedited) {
109 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
110 MEMBARRIER_CMD_GLOBAL_EXPEDITED);
111}
112
113TEST(membarrier, private_expedited) {
114 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
115 MEMBARRIER_CMD_PRIVATE_EXPEDITED);
116}
117
118TEST(membarrier, private_expedited_sync_core) {
119 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
120 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE);
121}
122
123#endif // __BIONIC__