blob: fbfcb1ce3fce63912608a9daa5e3d82bf07ba322 [file] [log] [blame]
// Copyright 2021 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 "src/devices/bin/driver_runtime/driver_context.h"
#include <zircon/assert.h>
#include <vector>
#include "src/devices/bin/driver_runtime/dispatcher.h"
#include "src/devices/lib/log/log.h"
namespace {
struct Entry {
const void* driver;
driver_runtime::Dispatcher* dispatcher;
};
static thread_local std::vector<Entry> g_driver_call_stack;
// The latest generation seen by this thread.
static thread_local uint32_t g_cached_irqs_generation = 0;
} // namespace
namespace driver_context {
void PushDriver(const void* driver, driver_runtime::Dispatcher* dispatcher) {
// TODO(fxbug.dev/88520): re-enable this once driver host v1 is deprecated.
// ZX_DEBUG_ASSERT(IsDriverInCallStack(driver) == false);
if (IsDriverInCallStack(driver)) {
LOGF(TRACE, "DriverContext: tried to push driver %p that was already in stack\n", driver);
}
g_driver_call_stack.push_back({driver, dispatcher});
}
void PopDriver() {
ZX_ASSERT(!g_driver_call_stack.empty());
g_driver_call_stack.pop_back();
}
const void* GetCurrentDriver() {
return g_driver_call_stack.empty() ? nullptr : g_driver_call_stack.back().driver;
}
driver_runtime::Dispatcher* GetCurrentDispatcher() {
return g_driver_call_stack.empty() ? nullptr : g_driver_call_stack.back().dispatcher;
}
bool IsDriverInCallStack(const void* driver) {
for (int64_t i = g_driver_call_stack.size() - 1; i >= 0; i--) {
if (g_driver_call_stack[i].driver == driver) {
return true;
}
}
return false;
}
bool IsCallStackEmpty() { return g_driver_call_stack.empty(); }
void OnThreadWakeup(driver_runtime::DispatcherCoordinator& coordinator) {
uint32_t new_irq_generation_id;
coordinator.OnThreadWakeup(g_cached_irqs_generation, &new_irq_generation_id);
g_cached_irqs_generation = new_irq_generation_id;
}
} // namespace driver_context