Home | History | Annotate | Download | only in tests
      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