blob: ce612e0601ae9c106d76171b96574b163dbefbc9 [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.
#pragma once
#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/macros.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <zircon/types.h>
#include <io-scheduler/stream-op.h>
namespace ioscheduler {
class Scheduler;
class Stream;
using StreamRef = fbl::RefPtr<Stream>;
// Stream - a logical sequence of ops.
// The Stream class is not thread safe, streams depend on the scheduler for synchronization.
// Certain calls must be performed with the Scheduler's stream_lock_ held.
class Stream : public fbl::RefCounted<Stream> {
public:
Stream(uint32_t id, uint32_t pri);
~Stream();
DISALLOW_COPY_ASSIGN_AND_MOVE(Stream);
uint32_t Id() { return id_; }
uint32_t Priority() { return priority_; }
void Close();
// Functions requiring the Scheduler stream lock be held.
// ---------------------------------------------------------
// Insert an op into the tail of the stream (subject to reordering).
// On error op's error status is set and it is moved to |*op_err|.
zx_status_t Push(UniqueOp op, UniqueOp* op_err);
// Fetch an op from the head of the stream.
UniqueOp Pop();
// Does the stream contain any ops that are not yet issued?
bool IsEmpty() { return (num_acquired_ == 0); }
// ---------------------------------------------------------
// End functions requiring stream lock.
// WAVL Tree support.
using WAVLTreeNodeState = fbl::WAVLTreeNodeState<StreamRef>;
struct WAVLTreeNodeTraitsSortById {
static WAVLTreeNodeState& node_state(Stream& s) { return s.map_node_; }
};
struct KeyTraitsSortById {
static const uint32_t& GetKey(const Stream& s) { return s.id_; }
static bool LessThan(const uint32_t s1, const uint32_t s2) { return (s1 < s2); }
static bool EqualTo(const uint32_t s1, const uint32_t s2) { return (s1 == s2); }
};
using WAVLTreeSortById = fbl::WAVLTree<uint32_t, StreamRef, KeyTraitsSortById,
WAVLTreeNodeTraitsSortById>;
// List support.
using ListNodeState = fbl::DoublyLinkedListNodeState<StreamRef>;
struct ListTraitsUnsorted {
static ListNodeState& node_state(Stream& s) { return s.list_node_; }
};
using ListUnsorted = fbl::DoublyLinkedList<StreamRef, ListTraitsUnsorted>;
private:
friend struct WAVLTreeNodeTraitsSortById;
friend struct KeyTraitsSortById;
WAVLTreeNodeState map_node_;
ListNodeState list_node_;
uint32_t id_;
uint32_t priority_;
bool open_ = true; // Stream is open, can accept more ops.
uint32_t num_acquired_ = 0; // Number of ops acquired and waiting for issue.
fbl::DoublyLinkedList<StreamOp*> acquired_list_;
};
} // namespace ioscheduler