summaryrefslogtreecommitdiff
path: root/src/libcamera/event_dispatcher_poll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/event_dispatcher_poll.cpp')
-rw-r--r--src/libcamera/event_dispatcher_poll.cpp308
1 files changed, 0 insertions, 308 deletions
diff --git a/src/libcamera/event_dispatcher_poll.cpp b/src/libcamera/event_dispatcher_poll.cpp
deleted file mode 100644
index 0b6aee18..00000000
--- a/src/libcamera/event_dispatcher_poll.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Google Inc.
- *
- * event_dispatcher_poll.cpp - Poll-based event dispatcher
- */
-
-#include "libcamera/internal/event_dispatcher_poll.h"
-
-#include <algorithm>
-#include <chrono>
-#include <iomanip>
-#include <poll.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include <libcamera/base/utils.h>
-
-#include "libcamera/internal/event_notifier.h"
-#include "libcamera/internal/log.h"
-#include "libcamera/internal/thread.h"
-#include "libcamera/internal/timer.h"
-
-/**
- * \file event_dispatcher_poll.h
- */
-
-namespace libcamera {
-
-LOG_DECLARE_CATEGORY(Event)
-
-static const char *notifierType(EventNotifier::Type type)
-{
- if (type == EventNotifier::Read)
- return "read";
- if (type == EventNotifier::Write)
- return "write";
- if (type == EventNotifier::Exception)
- return "exception";
-
- return "";
-}
-
-/**
- * \class EventDispatcherPoll
- * \brief A poll-based event dispatcher
- */
-
-EventDispatcherPoll::EventDispatcherPoll()
- : processingEvents_(false)
-{
- /*
- * Create the event fd. Failures are fatal as we can't implement an
- * interruptible dispatcher without the fd.
- */
- eventfd_ = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (eventfd_ < 0)
- LOG(Event, Fatal) << "Unable to create eventfd";
-}
-
-EventDispatcherPoll::~EventDispatcherPoll()
-{
- close(eventfd_);
-}
-
-void EventDispatcherPoll::registerEventNotifier(EventNotifier *notifier)
-{
- EventNotifierSetPoll &set = notifiers_[notifier->fd()];
- EventNotifier::Type type = notifier->type();
-
- if (set.notifiers[type] && set.notifiers[type] != notifier) {
- LOG(Event, Warning)
- << "Ignoring duplicate " << notifierType(type)
- << " notifier for fd " << notifier->fd();
- return;
- }
-
- set.notifiers[type] = notifier;
-}
-
-void EventDispatcherPoll::unregisterEventNotifier(EventNotifier *notifier)
-{
- auto iter = notifiers_.find(notifier->fd());
- if (iter == notifiers_.end())
- return;
-
- EventNotifierSetPoll &set = iter->second;
- EventNotifier::Type type = notifier->type();
-
- if (!set.notifiers[type])
- return;
-
- if (set.notifiers[type] != notifier) {
- LOG(Event, Warning)
- << notifierType(type) << " notifier for fd "
- << notifier->fd() << " is not registered";
- return;
- }
-
- set.notifiers[type] = nullptr;
-
- /*
- * Don't race with event processing if this method is called from an
- * event notifier. The notifiers_ entry will be erased by
- * processEvents().
- */
- if (processingEvents_)
- return;
-
- if (!set.notifiers[0] && !set.notifiers[1] && !set.notifiers[2])
- notifiers_.erase(iter);
-}
-
-void EventDispatcherPoll::registerTimer(Timer *timer)
-{
- for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) {
- if ((*iter)->deadline() > timer->deadline()) {
- timers_.insert(iter, timer);
- return;
- }
- }
-
- timers_.push_back(timer);
-}
-
-void EventDispatcherPoll::unregisterTimer(Timer *timer)
-{
- for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) {
- if (*iter == timer) {
- timers_.erase(iter);
- return;
- }
-
- /*
- * As the timers list is ordered, we can stop as soon as we go
- * past the deadline.
- */
- if ((*iter)->deadline() > timer->deadline())
- break;
- }
-}
-
-void EventDispatcherPoll::processEvents()
-{
- int ret;
-
- Thread::current()->dispatchMessages();
-
- /* Create the pollfd array. */
- std::vector<struct pollfd> pollfds;
- pollfds.reserve(notifiers_.size() + 1);
-
- for (auto notifier : notifiers_)
- pollfds.push_back({ notifier.first, notifier.second.events(), 0 });
-
- pollfds.push_back({ eventfd_, POLLIN, 0 });
-
- /* Wait for events and process notifiers and timers. */
- do {
- ret = poll(&pollfds);
- } while (ret == -1 && errno == EINTR);
-
- if (ret < 0) {
- ret = -errno;
- LOG(Event, Warning) << "poll() failed with " << strerror(-ret);
- } else if (ret > 0) {
- processInterrupt(pollfds.back());
- pollfds.pop_back();
- processNotifiers(pollfds);
- }
-
- processTimers();
-}
-
-void EventDispatcherPoll::interrupt()
-{
- uint64_t value = 1;
- ssize_t ret = write(eventfd_, &value, sizeof(value));
- if (ret != sizeof(value)) {
- if (ret < 0)
- ret = -errno;
- LOG(Event, Error)
- << "Failed to interrupt event dispatcher ("
- << ret << ")";
- }
-}
-
-short EventDispatcherPoll::EventNotifierSetPoll::events() const
-{
- short events = 0;
-
- if (notifiers[EventNotifier::Read])
- events |= POLLIN;
- if (notifiers[EventNotifier::Write])
- events |= POLLOUT;
- if (notifiers[EventNotifier::Exception])
- events |= POLLPRI;
-
- return events;
-}
-
-int EventDispatcherPoll::poll(std::vector<struct pollfd> *pollfds)
-{
- /* Compute the timeout. */
- Timer *nextTimer = !timers_.empty() ? timers_.front() : nullptr;
- struct timespec timeout;
-
- if (nextTimer) {
- utils::time_point now = utils::clock::now();
-
- if (nextTimer->deadline() > now)
- timeout = utils::duration_to_timespec(nextTimer->deadline() - now);
- else
- timeout = { 0, 0 };
-
- LOG(Event, Debug)
- << "timeout " << timeout.tv_sec << "."
- << std::setfill('0') << std::setw(9)
- << timeout.tv_nsec;
- }
-
- return ppoll(pollfds->data(), pollfds->size(),
- nextTimer ? &timeout : nullptr, nullptr);
-}
-
-void EventDispatcherPoll::processInterrupt(const struct pollfd &pfd)
-{
- if (!(pfd.revents & POLLIN))
- return;
-
- uint64_t value;
- ssize_t ret = read(eventfd_, &value, sizeof(value));
- if (ret != sizeof(value)) {
- if (ret < 0)
- ret = -errno;
- LOG(Event, Error)
- << "Failed to process interrupt (" << ret << ")";
- }
-}
-
-void EventDispatcherPoll::processNotifiers(const std::vector<struct pollfd> &pollfds)
-{
- static const struct {
- EventNotifier::Type type;
- short events;
- } events[] = {
- { EventNotifier::Read, POLLIN },
- { EventNotifier::Write, POLLOUT },
- { EventNotifier::Exception, POLLPRI },
- };
-
- processingEvents_ = true;
-
- for (const pollfd &pfd : pollfds) {
- auto iter = notifiers_.find(pfd.fd);
- ASSERT(iter != notifiers_.end());
-
- EventNotifierSetPoll &set = iter->second;
-
- for (const auto &event : events) {
- EventNotifier *notifier = set.notifiers[event.type];
-
- if (!notifier)
- continue;
-
- /*
- * If the file descriptor is invalid, disable the
- * notifier immediately.
- */
- if (pfd.revents & POLLNVAL) {
- LOG(Event, Warning)
- << "Disabling " << notifierType(event.type)
- << " due to invalid file descriptor "
- << pfd.fd;
- unregisterEventNotifier(notifier);
- continue;
- }
-
- if (pfd.revents & event.events)
- notifier->activated.emit(notifier);
- }
-
- /* Erase the notifiers_ entry if it is now empty. */
- if (!set.notifiers[0] && !set.notifiers[1] && !set.notifiers[2])
- notifiers_.erase(iter);
- }
-
- processingEvents_ = false;
-}
-
-void EventDispatcherPoll::processTimers()
-{
- utils::time_point now = utils::clock::now();
-
- while (!timers_.empty()) {
- Timer *timer = timers_.front();
- if (timer->deadline() > now)
- break;
-
- timers_.pop_front();
- timer->stop();
- timer->timeout.emit(timer);
- }
-}
-
-} /* namespace libcamera */