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

Commit a89530f4 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Copy reactor classes to new directory

Test: compile and run unit test
Change-Id: Ie704bf6b80f24bcae86d557ca351a893dcf8bdfa
parent c0cbaa44
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ subdirs = [
    "audio_bluetooth_hw",
    "audio_hal_interface",
    "audio_hearing_aid_hw",
    "gd",
    "hci",
    "utils",
    "device",
+3 −0
Original line number Diff line number Diff line
{
  "postsubmit" : [
    {
      "name" : "bluetooth_gd_test_os"
    },
    {
      "name" : "bluetooth_test_common"
    },

system/gd/Android.bp

0 → 100644
+38 −0
Original line number Diff line number Diff line
cc_library_static {
    name: "libbt-gd-os",
    defaults: [
        "fluoride_defaults",
        "clang_file_coverage",
    ],
    host_supported: true,
    srcs: [
        "os/alarm.cc",
        "os/handler.cc",
        "os/reactor.cc",
        "os/repeating_alarm.cc",
        "os/thread.cc",
    ],
}

cc_test {
    name: "bluetooth_gd_test_os",
    test_suites: ["device-tests"],
    defaults: [
        "fluoride_defaults",
        "clang_coverage_bin",
    ],
    host_supported: true,
    srcs : [
        "os/alarm_unittest.cc",
        "os/handler_unittest.cc",
        "os/reactor_unittest.cc",
        "os/repeating_alarm_unittest.cc",
        "os/thread_unittest.cc",
    ],
    static_libs : [
        "libbt-gd-os",
    ],
    sanitize: {
        cfi: false,
    },
}

system/gd/os/alarm.cc

0 → 100644
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 "os/alarm.h"

#include <sys/timerfd.h>
#include <cstring>

#include "base/logging.h"
#include "os/utils.h"

namespace bluetooth {
namespace os {

Alarm::Alarm(Thread* thread)
  : thread_(thread),
    fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
  CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);

  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
}

Alarm::~Alarm() {
  thread_->GetReactor()->Unregister(token_);

  int close_status;
  RUN_NO_INTR(close_status = close(fd_));
  CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
}

void Alarm::Schedule(Closure task, std::chrono::milliseconds delay) {
  std::lock_guard<std::mutex> lock(mutex_);
  long delay_ms = delay.count();
  itimerspec timer_itimerspec{
    {/* interval for periodic timer */},
    {delay_ms / 1000, delay_ms % 1000 * 1000000}
  };
  int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);

  task_ = std::move(task);
}

void Alarm::Cancel() {
  std::lock_guard<std::mutex> lock(mutex_);
  itimerspec disarm_itimerspec{/* disarm timer */};
  int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
}

void Alarm::on_fire() {
  std::unique_lock<std::mutex> lock(mutex_);
  auto task = std::move(task_);
  uint64_t times_invoked;
  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
  lock.unlock();
  task();
  CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
  CHECK_EQ(times_invoked, static_cast<uint64_t>(1));
}

}  // namespace os
}  // namespace bluetooth

system/gd/os/alarm.h

0 → 100644
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 <functional>
#include <memory>
#include <mutex>

#include "os/thread.h"
#include "os/utils.h"

namespace bluetooth {
namespace os {

// A single-shot alarm for reactor-based thread, implemented by Linux timerfd.
// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
// itself from the thread.
class Alarm {
 public:
  // Create and register a single-shot alarm on given thread
  explicit Alarm(Thread* thread);

  // Unregister this alarm from the thread and release resource
  ~Alarm();

  DISALLOW_COPY_AND_ASSIGN(Alarm);

  // Schedule the alarm with given delay
  void Schedule(Closure task, std::chrono::milliseconds delay);

  // Cancel the alarm. No-op if it's not armed.
  void Cancel();

 private:
  Closure task_;
  Thread* thread_;
  int fd_ = 0;
  Reactor::Reactable* token_;
  mutable std::mutex mutex_;
  void on_fire();
};

}  // namespace os

}  // namespace bluetooth
Loading