blob: 14989d0f26ca714896990249c8a20dfc3ebac9bb [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/message_packet.h"
#include <lib/fdf/channel.h>
#include "src/devices/bin/driver_runtime/arena.h"
#include "src/devices/bin/driver_runtime/handle.h"
namespace driver_runtime {
// static
MessagePacketOwner MessagePacket::Create(fbl::RefPtr<fdf_arena> arena, void* data,
uint32_t num_bytes, zx_handle_t* handles,
uint32_t num_handles) {
void* message_packet = nullptr;
if (arena) {
message_packet = arena->Allocate(sizeof(MessagePacket));
} else {
// The user wrote an empty message that did not provide an arena.
message_packet = calloc(1, sizeof(MessagePacket));
}
if (!message_packet) {
return nullptr;
}
return MessagePacketOwner(
new (message_packet) MessagePacket(std::move(arena), data, num_bytes, handles, num_handles));
}
// static
void MessagePacket::Delete(MessagePacket* message_packet) {
// Since the message packet may be allocated from the arena, keep it alive
// until we finish destruction.
fbl::RefPtr<fdf_arena_t> arena = std::move(message_packet->arena_);
message_packet->~MessagePacket();
if (!arena) {
// The user wrote an empty message that did not provide an arena.
// TODO(fxbug.dev/86856): we should consider recycling deleted packets.
free(message_packet);
}
}
MessagePacket::~MessagePacket() {
ZX_ASSERT(!InContainer());
if (handles_) {
for (size_t i = 0; i != num_handles_; i++) {
fdf_handle_close(handles_[i]);
}
}
}
void MessagePacket::CopyOut(fdf_arena_t** out_arena, void** out_data, uint32_t* out_num_bytes,
zx_handle_t** out_handles, uint32_t* out_num_handles) {
if (out_arena) {
fbl::RefPtr<fdf_arena> arena = this->arena();
// The reference is dropped when the user calls fbl_arena::Destroy.
*out_arena = fbl::ExportToRawPtr(&arena);
}
if (out_data) {
TakeData(out_data);
}
if (out_num_bytes) {
*out_num_bytes = num_bytes();
}
if (out_handles) {
TakeHandles(out_handles);
}
if (out_num_handles) {
*out_num_handles = num_handles();
}
}
} // namespace driver_runtime