| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <errno.h> |
| #include <fbl/array.h> |
| #include <fbl/unique_fd.h> |
| #include <fcntl.h> |
| #include <getopt.h> |
| #include <lib/counter-vmo-abi.h> |
| #include <lib/fdio/io.h> |
| #include <lib/fzl/owned-vmo-mapper.h> |
| #include <lib/zx/vmo.h> |
| #include <unistd.h> |
| #include <zxtest/zxtest.h> |
| |
| #include <algorithm> |
| #include <cinttypes> |
| #include <cstdio> |
| #include <cstdlib> |
| #include <cstring> |
| #include <utility> |
| |
| namespace { |
| |
| constexpr char kVmoFilePrefix[] = "/boot/kernel/"; |
| |
| TEST(Counters, Basic) { |
| fzl::OwnedVmoMapper desc_mapper; |
| const counters::DescriptorVmo* desc; |
| { |
| char desc_file_name[sizeof(kVmoFilePrefix) + sizeof(counters::DescriptorVmo::kVmoName)]; |
| strcpy(desc_file_name, kVmoFilePrefix); |
| strcat(desc_file_name, counters::DescriptorVmo::kVmoName); |
| fbl::unique_fd desc_fd(open(desc_file_name, O_RDONLY)); |
| ASSERT_TRUE(desc_fd, "cannot open descriptor VMO file"); |
| zx::vmo vmo; |
| ASSERT_OK(fdio_get_vmo_exact(desc_fd.get(), vmo.reset_and_get_address())); |
| uint64_t size; |
| ASSERT_OK(vmo.get_size(&size)); |
| ASSERT_OK(desc_mapper.Map(std::move(vmo), size, ZX_VM_PERM_READ)); |
| desc = reinterpret_cast<counters::DescriptorVmo*>(desc_mapper.start()); |
| EXPECT_EQ(desc->magic, counters::DescriptorVmo::kMagic, "descriptor VMO magic number"); |
| EXPECT_GE(size, sizeof(*desc) + desc->descriptor_table_size, "descriptor table size"); |
| } |
| |
| fzl::OwnedVmoMapper arena_mapper; |
| const volatile int64_t* arena; |
| { |
| char arena_file_name[sizeof(kVmoFilePrefix) + sizeof(counters::kArenaVmoName)]; |
| strcpy(arena_file_name, kVmoFilePrefix); |
| strcat(arena_file_name, counters::kArenaVmoName); |
| fbl::unique_fd arena_fd(open(arena_file_name, O_RDONLY)); |
| ASSERT_TRUE(arena_fd, "cannot open arena VMO file"); |
| zx::vmo vmo; |
| ASSERT_OK(fdio_get_vmo_exact(arena_fd.get(), vmo.reset_and_get_address())); |
| uint64_t size; |
| ASSERT_OK(vmo.get_size(&size)); |
| EXPECT_GE(size, desc->max_cpus * desc->num_counters() * sizeof(int64_t), "arena VMO size"); |
| ASSERT_OK(arena_mapper.Map(std::move(vmo), size, ZX_VM_PERM_READ)); |
| arena = reinterpret_cast<int64_t*>(arena_mapper.start()); |
| } |
| |
| auto find = [desc](const counters::Descriptor& ref) -> const counters::Descriptor* { |
| auto result = |
| std::equal_range(desc->begin(), desc->end(), ref, |
| [](const counters::Descriptor& a, const counters::Descriptor& b) { |
| return strcmp(a.name, b.name) < 0; |
| }); |
| return (result.first == result.second) ? nullptr |
| : &desc->descriptor_table[result.first - desc->begin()]; |
| }; |
| |
| constexpr counters::Descriptor kExpected[] = { |
| {"init.target.time.msec", counters::Type::kSum}, |
| {"handles.duped", counters::Type::kSum}, |
| {"handles.live", counters::Type::kSum}, |
| {"handles.made", counters::Type::kSum}, |
| }; |
| for (const auto& ref : kExpected) { |
| auto found = find(ref); |
| EXPECT_NOT_NULL(found, "expected counter name not found"); |
| if (found) { |
| EXPECT_EQ(found->type, ref.type, "counter has wrong type"); |
| size_t idx = found - desc->begin(); |
| int64_t value = 0; |
| for (uint64_t cpu = 0; cpu < desc->max_cpus; ++cpu) { |
| int64_t cpu_value = arena[(cpu * desc->num_counters()) + idx]; |
| switch (ref.type) { |
| default: |
| abort(); |
| break; |
| case counters::Type::kSum: |
| value += cpu_value; |
| break; |
| case counters::Type::kMax: // Not used, see ZX-3337. |
| value = std::max(value, cpu_value); |
| break; |
| } |
| } |
| EXPECT_GT(value, 0); |
| } |
| } |
| } |
| |
| } // anonymous namespace |