1 /* 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 25 class ScopedErrnoCleaner { 26 public: 27 ScopedErrnoCleaner() { errno = 0; } 28 ~ScopedErrnoCleaner() { errno = 0; } 29 }; 30 31 bool HasMembarrier(int membarrier_cmd) { 32 ScopedErrnoCleaner errno_cleaner; 33 int supported_cmds = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); 34 return (supported_cmds > 0) && ((supported_cmds & membarrier_cmd) != 0); 35 } 36 37 TEST(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 47 TEST(membarrier, global_barrier) { 48 if (!HasMembarrier(MEMBARRIER_CMD_GLOBAL)) { 49 GTEST_SKIP() << "MEMBARRIER_CMD_GLOBAL not supported"; 50 } 51 ASSERT_EQ(0, syscall(__NR_membarrier, MEMBARRIER_CMD_GLOBAL, 0)); 52 } 53 54 static 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 77 static void TestRegisterAndBarrierCommands(int membarrier_cmd_register, 78 int membarrier_cmd_barrier) { 79 if (!HasMembarrier(membarrier_cmd_register)) { 80 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_register) << " not supported"; 81 } 82 if (!HasMembarrier(membarrier_cmd_barrier)) { 83 GTEST_SKIP() << MembarrierCommandToName(membarrier_cmd_barrier) << " not supported"; 84 } 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 106 TEST(membarrier, global_expedited) { 107 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED, 108 MEMBARRIER_CMD_GLOBAL_EXPEDITED); 109 } 110 111 TEST(membarrier, private_expedited) { 112 TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 113 MEMBARRIER_CMD_PRIVATE_EXPEDITED); 114 } 115 116 TEST(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__ 122