| // Copyright 2024 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 <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/zx/clock.h> |
| #include <lib/zx/vmar.h> |
| #include <lib/zx/vmo.h> |
| |
| #include <gtest/gtest.h> |
| |
| namespace { |
| |
| __attribute__((noinline)) uint64_t count(int n) { |
| if (n == 0) { |
| return 1; |
| } |
| return 1 + count(n - 1); |
| } |
| __attribute__((noinline)) void add(uint64_t* addr) { *addr = *addr + 1; } |
| __attribute__((noinline)) void sub(uint64_t* addr) { *addr = *addr - 1; } |
| __attribute__((noinline)) void collatz(uint64_t* addr) { |
| switch (*addr % 2) { |
| case 0: |
| *addr /= 2; |
| break; |
| case 1: |
| *addr *= 3; |
| *addr += 1; |
| break; |
| } |
| } |
| |
| void MakeWork(uint64_t* ptr, async_dispatcher_t* dispatcher, zx::time until) { |
| if (zx::clock::get_monotonic() > until) { |
| return; |
| } |
| for (unsigned i = 0; i < 1000000; i++) { |
| switch (rand() % 4) { |
| case 0: |
| add(ptr); |
| break; |
| case 1: |
| sub(ptr); |
| break; |
| case 2: |
| collatz(ptr); |
| break; |
| case 3: |
| *ptr = count(20); |
| break; |
| } |
| } |
| EXPECT_EQ(1, 1); |
| async::PostTask(dispatcher, [ptr, dispatcher, until]() { MakeWork(ptr, dispatcher, until); }); |
| } |
| |
| // A simple test case that spins for a few seconds so we can profile it. |
| // |
| // This isn't intended as a standalone test to verify correctness, but as a simple target to point |
| // the profiler at to ensure it is able to profile a test. |
| TEST(GtestTest, MakeWorkTest) { |
| async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread); |
| async_dispatcher_t* dispatcher = loop.dispatcher(); |
| |
| // Map a vmo and write random data to it |
| zx::vmo vmo; |
| zx_status_t result = zx::vmo::create(zx_system_get_page_size(), 0, &vmo); |
| if (result != ZX_OK) { |
| return; |
| } |
| zx_vaddr_t out; |
| result = zx::vmar::root_self()->map(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, vmo, 0, |
| zx_system_get_page_size(), &out); |
| if (result != ZX_OK) { |
| return; |
| } |
| uint64_t* ptr = reinterpret_cast<uint64_t*>(out); |
| *ptr = 0; |
| |
| zx::time until = zx::deadline_after(zx::sec(5)); |
| async::PostTask(dispatcher, [ptr, dispatcher, until]() { MakeWork(ptr, dispatcher, until); }); |
| loop.RunUntilIdle(); |
| } |
| |
| } // namespace |