blob: 25f625d550e9cb3f3d2dd2cdaf5a95e2acbb6a60 [file] [log] [blame]
// Copyright 2019 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.
#ifndef ZIRCON_SYSTEM_DEV_BLOCK_CORE_MESSAGE_H_
#define ZIRCON_SYSTEM_DEV_BLOCK_CORE_MESSAGE_H_
#include <zircon/device/block.h>
#include <memory>
#include <ddk/protocol/block.h>
#include <fbl/intrusive_double_list.h>
class IoBuffer;
class Server;
// A single unit of work transmitted to the underlying block layer.
// Message contains a block_op_t, which is dynamically sized. Therefore, it implements its
// own allocator that takes block_op_size.
class Message final : public fbl::DoublyLinkedListable<Message*> {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(Message);
Message() = default;
// Overloaded new operator allows variable-sized allocation to match block op size.
void* operator new(size_t size) = delete;
void* operator new(size_t size, size_t block_op_size) {
return calloc(1, size + block_op_size - sizeof(block_op_t));
}
void operator delete(void* msg) { free(msg); }
// Allocate a new, uninitialized Message whose block_op begins in a memory region that
// is block_op_size bytes long.
static zx_status_t Create(size_t block_op_size, std::unique_ptr<Message>* out);
// Initialize the contents of this from the supplied args. block_op op_ is cleared.
void Init(fbl::RefPtr<IoBuffer> iobuf, Server* server, block_fifo_request_t* req);
// End the transaction specified by reqid and group, and release iobuf.
// Message can be reused with another call to Init().
void Complete(zx_status_t status);
block_op_t* Op() { return &op_; }
private:
fbl::RefPtr<IoBuffer> iobuf_;
Server* server_;
reqid_t reqid_;
groupid_t group_;
size_t op_size_;
// Must be at the end of structure.
union {
block_op_t op_;
uint8_t _op_raw_[1]; // Extra space for underlying block_op.
};
};
using MessageQueue = fbl::DoublyLinkedList<Message*>;
#endif // ZIRCON_SYSTEM_DEV_BLOCK_CORE_MESSAGE_H_