blob: 15c30e00396793d5b1c0b4d8728ccc28975ba6b0 [file] [log] [blame]
// Copyright 2020 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/graphics/drivers/misc/goldfish_control/heap.h"
#include <fuchsia/sysmem2/llcpp/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/async-loop/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fit/function.h>
#include <memory>
#include <ddk/debug.h>
#include <fbl/intrusive_double_list.h>
#include "src/graphics/drivers/misc/goldfish_control/control_device.h"
namespace goldfish {
Heap::Heap(Control* control, const char* tag)
: control_(control), loop_(&kAsyncLoopConfigNoAttachToCurrentThread), tag_(tag) {
ZX_DEBUG_ASSERT(control_);
// Start server thread. Heap server must be running on a seperate
// thread as sysmem might be making synchronous allocation requests
// from the main thread.
std::string thread_name = tag_ + "-thread";
loop_.StartThread(thread_name.c_str());
}
Heap::~Heap() { loop_.Shutdown(); }
void Heap::BindWithHeapProperties(zx::channel server_request,
llcpp::fuchsia::sysmem2::HeapProperties heap_properties) {
zx_handle_t server_handle = server_request.release();
async::PostTask(loop_.dispatcher(), [server_handle, heap_properties = std::move(heap_properties),
this]() mutable {
auto result = fidl::BindServer<HeapInterface>(
loop_.dispatcher(), zx::channel(server_handle), static_cast<HeapInterface*>(this),
[](HeapInterface* interface, fidl::UnbindInfo info, zx::channel channel) {
static_cast<Heap*>(interface)->OnClose(info, std::move(channel));
});
if (!result.is_ok()) {
zxlogf(ERROR, "[%s] Cannot bind to channel: status: %d", tag_.c_str(), result.error());
control_->RemoveHeap(this);
return;
}
result.value()->OnRegister(std::move(heap_properties));
});
}
void Heap::OnClose(fidl::UnbindInfo info, zx::channel channel) {
if (info.reason == fidl::UnbindInfo::kPeerClosed) {
zxlogf(INFO, "[%s] Client closed Heap connection: epitaph: %d", tag_.c_str(), info.status);
} else if (info.reason != fidl::UnbindInfo::kUnbind && info.reason != fidl::UnbindInfo::kClose) {
zxlogf(ERROR, "[%s] Channel internal error: status: %d", tag_.c_str(), info.status);
}
control_->RemoveHeap(this);
}
} // namespace goldfish