• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ScopedErrnoCleaner()27   ScopedErrnoCleaner() { errno = 0; }
~ScopedErrnoCleaner()28   ~ScopedErrnoCleaner() { errno = 0; }
29 };
30 
HasMembarrier(int membarrier_cmd)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 
TEST(membarrier,query)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 
TEST(membarrier,global_barrier)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 
MembarrierCommandToName(int membarrier_cmd)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 
TestRegisterAndBarrierCommands(int membarrier_cmd_register,int membarrier_cmd_barrier)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 
TEST(membarrier,global_expedited)106 TEST(membarrier, global_expedited) {
107   TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
108                                  MEMBARRIER_CMD_GLOBAL_EXPEDITED);
109 }
110 
TEST(membarrier,private_expedited)111 TEST(membarrier, private_expedited) {
112   TestRegisterAndBarrierCommands(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
113                                  MEMBARRIER_CMD_PRIVATE_EXPEDITED);
114 }
115 
TEST(membarrier,private_expedited_sync_core)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