Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a845cb7 authored by Chris Manton's avatar Chris Manton Committed by Automerger Merge Worker
Browse files

Remove common::once_timer am: 77772eaf

parents 31a94d1d 77772eaf
Loading
Loading
Loading
Loading
+0 −28
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ cc_library_static {
        "address_obfuscator.cc",
        "message_loop_thread.cc",
        "metric_id_allocator.cc",
        "once_timer.cc",
        "os_utils.cc",
        "repeating_timer.cc",
        "stop_watch_legacy.cc",
@@ -66,7 +65,6 @@ cc_test {
        "lru_unittest.cc",
        "message_loop_thread_unittest.cc",
        "metric_id_allocator_unittest.cc",
        "once_timer_unittest.cc",
        "repeating_timer_unittest.cc",
        "state_machine_unittest.cc",
        "time_util_unittest.cc",
@@ -138,29 +136,3 @@ cc_benchmark {
        "libosi",
    ],
}

cc_benchmark {
    name: "bluetooth_benchmark_timer_performance",
    defaults: [
        "fluoride_defaults",
    ],
    host_supported: false,
    include_dirs: ["packages/modules/Bluetooth/system"],
    srcs: [
        "benchmark/timer_performance_benchmark.cc",
    ],
    shared_libs: [
        "libcrypto",
        "libcrypto",
        "libcutils",
        "liblog",
        "libprotobuf-cpp-lite",
    ],
    static_libs: [
        "libbt-common",
        "libbt-protos-lite",
        "libchrome",
        "libevent",
        "libosi",
    ],
}
+0 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ static_library("common") {
    "message_loop_thread.cc",
    "metric_id_allocator.cc",
    "metrics_linux.cc",
    "once_timer.cc",
    "os_utils.cc",
    "repeating_timer.cc",
    "stop_watch_legacy.cc",
+0 −288
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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 <base/functional/bind.h>
#include <base/run_loop.h>
#include <base/threading/thread.h>
#include <benchmark/benchmark.h>
#include <future>

#include "common/message_loop_thread.h"
#include "common/once_timer.h"
#include "common/repeating_timer.h"
#include "common/time_util.h"
#include "osi/include/alarm.h"

using ::benchmark::State;
using bluetooth::common::MessageLoopThread;
using bluetooth::common::OnceTimer;
using bluetooth::common::RepeatingTimer;
using bluetooth::common::time_get_os_boottime_us;

bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; }

namespace {
std::unordered_map<int, int> g_map;
std::shared_ptr<std::promise<void>> g_promise;
uint64_t g_start_time;
int g_scheduled_tasks;
int g_task_length;
int g_task_interval;
int g_task_counter;

void TimerFire(void*) { g_promise->set_value(); }

void AlarmSleepAndCountDelayedTime(void*) {
  auto end_time_us = time_get_os_boottime_us();
  auto time_after_start_ms = (end_time_us - g_start_time) / 1000;
  g_task_counter++;
  g_map[time_after_start_ms - g_task_counter * g_task_interval]++;
  std::this_thread::sleep_for(std::chrono::milliseconds(g_task_length));
  if (g_task_counter >= g_scheduled_tasks) {
    g_promise->set_value();
  }
}

}  // namespace

class BM_OsiAlarmTimer : public ::benchmark::Fixture {
 protected:
  void SetUp(State& st) override {
    ::benchmark::Fixture::SetUp(st);
    alarm_ = alarm_new("osi_alarm_timer_test");
    g_promise = std::make_shared<std::promise<void>>();
  }

  void TearDown(State& st) override {
    g_promise = nullptr;
    alarm_free(alarm_);
    ::benchmark::Fixture::TearDown(st);
  }

  alarm_t* alarm_ = nullptr;
};

BENCHMARK_DEFINE_F(BM_OsiAlarmTimer, timer_performance_ms)(State& state) {
  auto milliseconds = static_cast<int>(state.range(0));
  for (auto _ : state) {
    auto start_time_point = time_get_os_boottime_us();
    alarm_set(alarm_, milliseconds, &TimerFire, nullptr);
    g_promise->get_future().get();
    auto end_time_point = time_get_os_boottime_us();
    auto duration = end_time_point - start_time_point;
    state.SetIterationTime(duration * 1e-6);
  }
};

BENCHMARK_REGISTER_F(BM_OsiAlarmTimer, timer_performance_ms)
    ->Arg(1)
    ->Arg(5)
    ->Arg(10)
    ->Arg(20)
    ->Arg(100)
    ->Arg(1000)
    ->Arg(2000)
    ->Iterations(1)
    ->UseManualTime();

class BM_AlarmTaskTimer : public ::benchmark::Fixture {
 protected:
  void SetUp(State& st) override {
    ::benchmark::Fixture::SetUp(st);
    message_loop_thread_ = new MessageLoopThread("timer_benchmark");
    message_loop_thread_->StartUp();
    message_loop_thread_->EnableRealTimeScheduling();
    once_timer_ = new OnceTimer();
    repeating_timer_ = new RepeatingTimer();
    g_promise = std::make_shared<std::promise<void>>();
  }

  void TearDown(State& st) override {
    g_promise = nullptr;
    delete once_timer_;
    once_timer_ = nullptr;
    delete repeating_timer_;
    repeating_timer_ = nullptr;
    message_loop_thread_->ShutDown();
    delete message_loop_thread_;
    message_loop_thread_ = nullptr;
    ::benchmark::Fixture::TearDown(st);
  }

  MessageLoopThread* message_loop_thread_;
  OnceTimer* once_timer_;
  RepeatingTimer* repeating_timer_;
};

BENCHMARK_DEFINE_F(BM_AlarmTaskTimer, timer_performance_ms)(State& state) {
  auto milliseconds = static_cast<int>(state.range(0));
  for (auto _ : state) {
    auto start_time_point = time_get_os_boottime_us();
    once_timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE,
                          base::BindOnce(&TimerFire, nullptr),
#if BASE_VER < 931007
                          base::TimeDelta::FromMilliseconds(milliseconds));
#else
                          base::Milliseconds(milliseconds));
#endif
    g_promise->get_future().get();
    once_timer_->Cancel();
    auto end_time_point = time_get_os_boottime_us();
    auto duration = end_time_point - start_time_point;
    state.SetIterationTime(duration * 1e-6);
  }
};

BENCHMARK_REGISTER_F(BM_AlarmTaskTimer, timer_performance_ms)
    ->Arg(1)
    ->Arg(5)
    ->Arg(10)
    ->Arg(20)
    ->Arg(100)
    ->Arg(1000)
    ->Arg(2000)
    ->Iterations(1)
    ->UseManualTime();

class BM_OsiPeriodicAlarmTimer : public ::benchmark::Fixture {
 protected:
  void SetUp(State& st) override {
    ::benchmark::Fixture::SetUp(st);
    alarm_ = alarm_new_periodic("osi_alarm_timer_test");
    g_map.clear();
    g_promise = std::make_shared<std::promise<void>>();
    g_scheduled_tasks = 0;
    g_task_length = 0;
    g_task_interval = 0;
    g_task_counter = 0;
  }

  void TearDown(State& st) override {
    g_promise = nullptr;
    alarm_free(alarm_);
    ::benchmark::Fixture::TearDown(st);
  }

  alarm_t* alarm_ = nullptr;
};

BENCHMARK_DEFINE_F(BM_OsiPeriodicAlarmTimer, periodic_accuracy)(State& state) {
  for (auto _ : state) {
    g_scheduled_tasks = state.range(0);
    g_task_length = state.range(1);
    g_task_interval = state.range(2);
    g_start_time = time_get_os_boottime_us();
    alarm_set(alarm_, g_task_interval, &AlarmSleepAndCountDelayedTime, nullptr);
    g_promise->get_future().get();
    alarm_cancel(alarm_);
  }
  for (const auto& delay : g_map) {
    state.counters[std::to_string(delay.first)] = delay.second;
  }
};

BENCHMARK_REGISTER_F(BM_OsiPeriodicAlarmTimer, periodic_accuracy)
    ->Args({2000, 1, 5})
    ->Args({2000, 3, 5})
    ->Args({2000, 1, 7})
    ->Args({2000, 3, 7})
    ->Args({2000, 1, 20})
    ->Args({2000, 5, 20})
    ->Args({2000, 10, 20})
    ->Args({2000, 15, 20})
    ->Iterations(1)
    ->UseRealTime();

class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture {
 protected:
  void SetUp(State& st) override {
    ::benchmark::Fixture::SetUp(st);
    message_loop_thread_ = new MessageLoopThread("timer_benchmark");
    message_loop_thread_->StartUp();
    message_loop_thread_->EnableRealTimeScheduling();
    once_timer_ = new OnceTimer();
    repeating_timer_ = new RepeatingTimer();
    g_map.clear();
    g_promise = std::make_shared<std::promise<void>>();
    g_scheduled_tasks = 0;
    g_task_length = 0;
    g_task_interval = 0;
    g_task_counter = 0;
  }

  void TearDown(State& st) override {
    g_promise = nullptr;
    delete once_timer_;
    once_timer_ = nullptr;
    delete repeating_timer_;
    repeating_timer_ = nullptr;
    message_loop_thread_->ShutDown();
    delete message_loop_thread_;
    message_loop_thread_ = nullptr;
    ::benchmark::Fixture::TearDown(st);
  }

  MessageLoopThread* message_loop_thread_;
  OnceTimer* once_timer_;
  RepeatingTimer* repeating_timer_;
};

BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy)
(State& state) {
  for (auto _ : state) {
    g_scheduled_tasks = state.range(0);
    g_task_length = state.range(1);
    g_task_interval = state.range(2);
    g_start_time = time_get_os_boottime_us();
    repeating_timer_->SchedulePeriodic(
        message_loop_thread_->GetWeakPtr(), FROM_HERE,
        base::BindRepeating(&AlarmSleepAndCountDelayedTime, nullptr),
#if BASE_VER < 931007
        base::TimeDelta::FromMilliseconds(g_task_interval));
#else
        base::Milliseconds(g_task_interval));
#endif
    g_promise->get_future().get();
    repeating_timer_->Cancel();
  }
  for (const auto& delay : g_map) {
    state.counters[std::to_string(delay.first)] = delay.second;
  }
};

BENCHMARK_REGISTER_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy)
    ->Args({2000, 1, 5})
    ->Args({2000, 3, 5})
    ->Args({2000, 1, 7})
    ->Args({2000, 3, 7})
    ->Args({2000, 1, 20})
    ->Args({2000, 5, 20})
    ->Args({2000, 10, 20})
    ->Args({2000, 15, 20})
    ->Iterations(1)
    ->UseRealTime();

int main(int argc, char** argv) {
  // Disable LOG() output from libchrome
  logging::LoggingSettings log_settings;
  log_settings.logging_dest = logging::LoggingDestination::LOG_NONE;
  CHECK(logging::InitLogging(log_settings)) << "Failed to set up logging";
  ::benchmark::Initialize(&argc, argv);
  if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
    return 1;
  }
  ::benchmark::RunSpecifiedBenchmarks();
}

system/common/once_timer.cc

deleted100644 → 0
+0 −155
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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 "once_timer.h"

#include <base/logging.h>

#include <memory>
#include <mutex>

#include "message_loop_thread.h"
#include "time_util.h"

namespace bluetooth {

namespace common {

// This runs on user thread
OnceTimer::~OnceTimer() {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  if (message_loop_thread_ != nullptr && message_loop_thread_->IsRunning()) {
    CancelAndWait();
  }
}

// This runs on user thread
bool OnceTimer::Schedule(const base::WeakPtr<MessageLoopThread>& thread,
                         const base::Location& from_here,
                         base::OnceClosure task, base::TimeDelta delay) {
  uint64_t time_now_us = time_get_os_boottime_us();
  uint64_t time_next_task_us = time_now_us + delay.InMicroseconds();
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  if (thread == nullptr) {
    LOG(ERROR) << __func__ << ": thread must be non-null";
    return false;
  }
  CancelAndWait();
  task_ = std::move(task);
  task_wrapper_.Reset(
      base::BindOnce(&OnceTimer::RunTask, base::Unretained(this)));
  {
    std::unique_lock<decltype(message_loop_thread_write_mutex_)> lock(
        message_loop_thread_write_mutex_);
    message_loop_thread_ = thread;
  }

  delay_ = delay;
  uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us();
  if (!thread->DoInThreadDelayed(
          from_here, task_wrapper_.callback(),
#if BASE_VER < 931007
          base::TimeDelta::FromMicroseconds(time_until_next_us))) {
#else
          base::Microseconds(time_until_next_us))) {
#endif
    LOG(ERROR) << __func__
               << ": failed to post task to message loop for thread " << *thread
               << ", from " << from_here.ToString();
    task_wrapper_.Cancel();
    {
      std::unique_lock<decltype(message_loop_thread_write_mutex_)> lock(
          message_loop_thread_write_mutex_);
      message_loop_thread_ = nullptr;
    }
    delay_ = {};
    return false;
  }
  return true;
}

// This runs on user thread
void OnceTimer::Cancel() {
  std::promise<void> promise;
  CancelHelper(std::move(promise));
}

// This runs on user thread
void OnceTimer::CancelAndWait() {
  std::promise<void> promise;
  auto future = promise.get_future();
  CancelHelper(std::move(promise));
  future.wait();
}

// This runs on user thread
void OnceTimer::CancelHelper(std::promise<void> promise) {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  MessageLoopThread* scheduled_thread = message_loop_thread_.get();
  if (scheduled_thread == nullptr) {
    promise.set_value();
    return;
  }
  if (scheduled_thread->GetThreadId() == base::PlatformThread::CurrentId()) {
    CancelClosure(std::move(promise));
    return;
  }
  scheduled_thread->DoInThread(
      FROM_HERE, base::BindOnce(&OnceTimer::CancelClosure,
                                base::Unretained(this), std::move(promise)));
}

// This runs on message loop thread
void OnceTimer::CancelClosure(std::promise<void> promise) {
  task_wrapper_.Cancel();
  {
    std::unique_lock<decltype(message_loop_thread_write_mutex_)> lock(
        message_loop_thread_write_mutex_);
    message_loop_thread_ = nullptr;
  }
  delay_ = base::TimeDelta();
  promise.set_value();
}

// This runs on user thread
bool OnceTimer::IsScheduled() const {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return message_loop_thread_ != nullptr && message_loop_thread_->IsRunning();
}

// This runs on message loop thread
void OnceTimer::RunTask() {
  if (message_loop_thread_ == nullptr || !message_loop_thread_->IsRunning()) {
    LOG(ERROR) << __func__
               << ": message_loop_thread_ is null or is not running";
    return;
  }
  CHECK_EQ(message_loop_thread_->GetThreadId(),
           base::PlatformThread::CurrentId())
      << ": task must run on message loop thread";

  task_wrapper_.Cancel();
  std::move(task_).Run();
  {
    std::unique_lock<decltype(message_loop_thread_write_mutex_)> lock(
        message_loop_thread_write_mutex_);
    message_loop_thread_ = nullptr;
  }
}

}  // namespace common

}  // namespace bluetooth

system/common/once_timer.h

deleted100644 → 0
+0 −95
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * 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.
 */

#pragma once

#include <base/cancelable_callback.h>
#include <base/functional/bind.h>
#include <base/location.h>
#include <base/time/time.h>

#include <future>

namespace bluetooth {

namespace common {

class MessageLoopThread;

/**
 * An alarm clock that posts a delayed task to a specified MessageLoopThread
 * once.
 *
 * Warning: MessageLoopThread must be running when any task is scheduled or
 * being executed
 */
class OnceTimer final {
 public:
  OnceTimer() {}
  OnceTimer(const OnceTimer&) = delete;
  OnceTimer& operator=(const OnceTimer&) = delete;

  ~OnceTimer();

  /**
   * Schedule a delayed task to the MessageLoopThread. Only one task can be
   * scheduled at a time. If another task is scheduled, it will cancel the
   * previous task synchronously and schedule the new task; this blocks until
   * the previous task is cancelled.
   *
   * @param thread thread to run the task
   * @param from_here location where this task is originated
   * @param task task created through base::Bind()
   * @param delay delay for the task to be executed
   * @return true iff task is scheduled successfully
   */
  bool Schedule(const base::WeakPtr<MessageLoopThread>& thread,
                const base::Location& from_here, base::OnceClosure task,
                base::TimeDelta delay);

  /**
   * Post an event which cancels the current task asynchronously
   */
  void Cancel();

  /**
   * Post an event which cancels the current task and wait for the cancellation
   * to be completed
   */
  void CancelAndWait();

  /**
   * Returns true when there is a pending task scheduled on a running thread,
   * otherwise false.
   */
  bool IsScheduled() const;

 private:
  mutable std::mutex message_loop_thread_write_mutex_;
  base::WeakPtr<MessageLoopThread> message_loop_thread_;
  base::CancelableOnceClosure task_wrapper_;
  base::OnceClosure task_;
  base::TimeDelta delay_;
  mutable std::recursive_mutex api_mutex_;
  void CancelHelper(std::promise<void> promise);
  void CancelClosure(std::promise<void> promise);

  void RunTask();
};

}  // namespace common

}  // namespace bluetooth
Loading