summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/affinity.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/syscalls/linux/affinity.cc')
-rw-r--r--test/syscalls/linux/affinity.cc242
1 files changed, 0 insertions, 242 deletions
diff --git a/test/syscalls/linux/affinity.cc b/test/syscalls/linux/affinity.cc
deleted file mode 100644
index 128364c34..000000000
--- a/test/syscalls/linux/affinity.cc
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <sched.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "gtest/gtest.h"
-#include "absl/strings/str_split.h"
-#include "test/util/cleanup.h"
-#include "test/util/fs_util.h"
-#include "test/util/posix_error.h"
-#include "test/util/test_util.h"
-#include "test/util/thread_util.h"
-
-namespace gvisor {
-namespace testing {
-namespace {
-
-// These tests are for both the sched_getaffinity(2) and sched_setaffinity(2)
-// syscalls.
-class AffinityTest : public ::testing::Test {
- protected:
- void SetUp() override {
- EXPECT_THAT(
- // Needs use the raw syscall to get the actual size.
- cpuset_size_ = syscall(SYS_sched_getaffinity, /*pid=*/0,
- sizeof(cpu_set_t), &mask_),
- SyscallSucceeds());
- // Lots of tests rely on having more than 1 logical processor available.
- EXPECT_GT(CPU_COUNT(&mask_), 1);
- }
-
- static PosixError ClearLowestBit(cpu_set_t* mask, size_t cpus) {
- const size_t mask_size = CPU_ALLOC_SIZE(cpus);
- for (size_t n = 0; n < cpus; ++n) {
- if (CPU_ISSET_S(n, mask_size, mask)) {
- CPU_CLR_S(n, mask_size, mask);
- return NoError();
- }
- }
- return PosixError(EINVAL, "No bit to clear, mask is empty");
- }
-
- PosixError ClearLowestBit() { return ClearLowestBit(&mask_, CPU_SETSIZE); }
-
- // Stores the initial cpu mask for this process.
- cpu_set_t mask_ = {};
- int cpuset_size_ = 0;
-};
-
-// sched_getaffinity(2) is implemented.
-TEST_F(AffinityTest, SchedGetAffinityImplemented) {
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, sizeof(cpu_set_t), &mask_),
- SyscallSucceeds());
-}
-
-// PID is not found.
-TEST_F(AffinityTest, SchedGetAffinityInvalidPID) {
- // Flaky, but it's tough to avoid a race condition when finding an unused pid
- EXPECT_THAT(sched_getaffinity(/*pid=*/INT_MAX - 1, sizeof(cpu_set_t), &mask_),
- SyscallFailsWithErrno(ESRCH));
-}
-
-// PID is not found.
-TEST_F(AffinityTest, SchedSetAffinityInvalidPID) {
- // Flaky, but it's tough to avoid a race condition when finding an unused pid
- EXPECT_THAT(sched_setaffinity(/*pid=*/INT_MAX - 1, sizeof(cpu_set_t), &mask_),
- SyscallFailsWithErrno(ESRCH));
-}
-
-TEST_F(AffinityTest, SchedSetAffinityZeroMask) {
- CPU_ZERO(&mask_);
- EXPECT_THAT(sched_setaffinity(/*pid=*/0, sizeof(cpu_set_t), &mask_),
- SyscallFailsWithErrno(EINVAL));
-}
-
-// N.B. This test case relies on cpuset_size_ larger than the actual number of
-// of all existing CPUs. Check your machine if the test fails.
-TEST_F(AffinityTest, SchedSetAffinityNonexistentCPUDropped) {
- cpu_set_t mask = mask_;
- // Add a nonexistent CPU.
- //
- // The number needs to be larger than the possible number of CPU available,
- // but smaller than the number of the CPU that the kernel claims to support --
- // it's implicitly returned by raw sched_getaffinity syscall.
- CPU_SET(cpuset_size_ * 8 - 1, &mask);
- EXPECT_THAT(
- // Use raw syscall because it will be rejected by the libc wrapper
- // otherwise.
- syscall(SYS_sched_setaffinity, /*pid=*/0, sizeof(cpu_set_t), &mask),
- SyscallSucceeds())
- << "failed with cpumask : " << CPUSetToString(mask)
- << ", cpuset_size_ : " << cpuset_size_;
- cpu_set_t newmask;
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, sizeof(cpu_set_t), &newmask),
- SyscallSucceeds());
- EXPECT_TRUE(CPU_EQUAL(&mask_, &newmask))
- << "got: " << CPUSetToString(newmask)
- << " != expected: " << CPUSetToString(mask_);
-}
-
-TEST_F(AffinityTest, SchedSetAffinityOnlyNonexistentCPUFails) {
- // Make an empty cpu set.
- CPU_ZERO(&mask_);
- // Add a nonexistent CPU.
- //
- // The number needs to be larger than the possible number of CPU available,
- // but smaller than the number of the CPU that the kernel claims to support --
- // it's implicitly returned by raw sched_getaffinity syscall.
- int cpu = cpuset_size_ * 8 - 1;
- if (cpu <= NumCPUs()) {
- GTEST_SKIP() << "Skipping test: cpu " << cpu << " exists";
- }
- CPU_SET(cpu, &mask_);
- EXPECT_THAT(
- // Use raw syscall because it will be rejected by the libc wrapper
- // otherwise.
- syscall(SYS_sched_setaffinity, /*pid=*/0, sizeof(cpu_set_t), &mask_),
- SyscallFailsWithErrno(EINVAL));
-}
-
-TEST_F(AffinityTest, SchedSetAffinityInvalidSize) {
- EXPECT_GT(cpuset_size_, 0);
- // Not big enough.
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, cpuset_size_ - 1, &mask_),
- SyscallFailsWithErrno(EINVAL));
- // Not a multiple of word size.
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, cpuset_size_ + 1, &mask_),
- SyscallFailsWithErrno(EINVAL));
-}
-
-TEST_F(AffinityTest, Sanity) {
- ASSERT_NO_ERRNO(ClearLowestBit());
- EXPECT_THAT(sched_setaffinity(/*pid=*/0, sizeof(cpu_set_t), &mask_),
- SyscallSucceeds());
- cpu_set_t newmask;
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, sizeof(cpu_set_t), &newmask),
- SyscallSucceeds());
- EXPECT_TRUE(CPU_EQUAL(&mask_, &newmask))
- << "got: " << CPUSetToString(newmask)
- << " != expected: " << CPUSetToString(mask_);
-}
-
-TEST_F(AffinityTest, NewThread) {
- SKIP_IF(CPU_COUNT(&mask_) < 3);
- ASSERT_NO_ERRNO(ClearLowestBit());
- ASSERT_NO_ERRNO(ClearLowestBit());
- EXPECT_THAT(sched_setaffinity(/*pid=*/0, sizeof(cpu_set_t), &mask_),
- SyscallSucceeds());
- ScopedThread([this]() {
- cpu_set_t child_mask;
- ASSERT_THAT(sched_getaffinity(/*pid=*/0, sizeof(cpu_set_t), &child_mask),
- SyscallSucceeds());
- ASSERT_TRUE(CPU_EQUAL(&child_mask, &mask_))
- << "child cpu mask: " << CPUSetToString(child_mask)
- << " != parent cpu mask: " << CPUSetToString(mask_);
- });
-}
-
-TEST_F(AffinityTest, ConsistentWithProcCpuInfo) {
- // Count how many cpus are shown in /proc/cpuinfo.
- std::string cpuinfo = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/cpuinfo"));
- int count = 0;
- for (auto const& line : absl::StrSplit(cpuinfo, '\n')) {
- if (absl::StartsWith(line, "processor")) {
- count++;
- }
- }
- EXPECT_GE(count, CPU_COUNT(&mask_));
-}
-
-TEST_F(AffinityTest, ConsistentWithProcStat) {
- // Count how many cpus are shown in /proc/stat.
- std::string stat = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/stat"));
- int count = 0;
- for (auto const& line : absl::StrSplit(stat, '\n')) {
- if (absl::StartsWith(line, "cpu") && !absl::StartsWith(line, "cpu ")) {
- count++;
- }
- }
- EXPECT_GE(count, CPU_COUNT(&mask_));
-}
-
-TEST_F(AffinityTest, SmallCpuMask) {
- const int num_cpus = NumCPUs();
- const size_t mask_size = CPU_ALLOC_SIZE(num_cpus);
- cpu_set_t* mask = CPU_ALLOC(num_cpus);
- ASSERT_NE(mask, nullptr);
- const auto free_mask = Cleanup([&] { CPU_FREE(mask); });
-
- CPU_ZERO_S(mask_size, mask);
- ASSERT_THAT(sched_getaffinity(0, mask_size, mask), SyscallSucceeds());
-}
-
-TEST_F(AffinityTest, LargeCpuMask) {
- // Allocate mask bigger than cpu_set_t normally allocates.
- const size_t cpus = CPU_SETSIZE * 8;
- const size_t mask_size = CPU_ALLOC_SIZE(cpus);
-
- cpu_set_t* large_mask = CPU_ALLOC(cpus);
- auto free_mask = Cleanup([large_mask] { CPU_FREE(large_mask); });
- CPU_ZERO_S(mask_size, large_mask);
-
- // Check that get affinity with large mask works as expected.
- ASSERT_THAT(sched_getaffinity(/*pid=*/0, mask_size, large_mask),
- SyscallSucceeds());
- EXPECT_TRUE(CPU_EQUAL(&mask_, large_mask))
- << "got: " << CPUSetToString(*large_mask, cpus)
- << " != expected: " << CPUSetToString(mask_);
-
- // Check that set affinity with large mask works as expected.
- ASSERT_NO_ERRNO(ClearLowestBit(large_mask, cpus));
- EXPECT_THAT(sched_setaffinity(/*pid=*/0, mask_size, large_mask),
- SyscallSucceeds());
-
- cpu_set_t* new_mask = CPU_ALLOC(cpus);
- auto free_new_mask = Cleanup([new_mask] { CPU_FREE(new_mask); });
- CPU_ZERO_S(mask_size, new_mask);
- EXPECT_THAT(sched_getaffinity(/*pid=*/0, mask_size, new_mask),
- SyscallSucceeds());
-
- EXPECT_TRUE(CPU_EQUAL_S(mask_size, large_mask, new_mask))
- << "got: " << CPUSetToString(*new_mask, cpus)
- << " != expected: " << CPUSetToString(*large_mask, cpus);
-}
-
-} // namespace
-} // namespace testing
-} // namespace gvisor