// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#pragma once

#include <fbl/canary.h>
#include <fbl/ref_ptr.h>
#include <object/dispatcher.h>
#include <object/port_dispatcher.h>
#include <zircon/types.h>
#include <vm/page_source.h>

// Page source implementation that talks to a userspace pager service.
//
// The lifecycle of this class is a little complicated because the pager source's port potentially
// has an unmanaged reference to the pager source through packet_. Because of this, we need to
// ensure that the last RefPtr to the pager source isn't released too early when the pager source
// gets closed. Normally, the dispatcher can retain its reference to the pager source until the
// port frees its reference to packet_ (through the PortAllocator). However, if the dispatcher is
// destroyed, if we can't revoke the port's reference to packet_, then we end up making the pager
// source keep a reference to itself until the packet is freed.
class PagerSource : public PageSource , public PortAllocator,
                    public fbl::DoublyLinkedListable<fbl::RefPtr<PagerSource>> {
private:
    PagerSource(uint64_t page_source_id,
                PagerDispatcher* dispatcher, fbl::RefPtr<PortDispatcher> port, uint64_t key);
    virtual ~PagerSource();
    friend fbl::RefPtr<PagerSource>;

    PortPacket* Alloc() final {
        DEBUG_ASSERT(false);
        return nullptr;
    }
    void Free(PortPacket* port_packet) final ;

    virtual bool GetPage(uint64_t offset,
                         vm_page_t** const page_out, paddr_t* const pa_out) final {
        // Pagers cannot synchronusly fulfill requests.
        return false;
    }

    void GetPageAsync(page_request_t* request) final;
    void ClearAsyncRequest(page_request_t* request) final;
    void SwapRequest(page_request_t* old, page_request_t* new_req) final;
    void OnClose() final;
    void OnDetach() final;
    zx_status_t WaitOnEvent(event_t* event) final;

    PagerDispatcher* const pager_;
    const fbl::RefPtr<PortDispatcher> port_;
    const uint64_t key_;

    mutable DECLARE_MUTEX(PagerSource) mtx_;
    bool closed_ TA_GUARDED(mtx_) = false;
    // Flag set when there is a pending ZX_PAGER_VMO_COMPLETE message. This serves as a proxy
    // for whether or not the port has a reference to packet_ (as the complete message is the
    // last message sent). This flag is used to delay cleanup if PagerSource::Close is called
    // while the port still has a reference to packet_.
    bool complete_pending_ TA_GUARDED(mtx_) = false;
    // Ref to keep the object alive in certain circumstances - see PagerDispatcher::on_zero_handles.
    fbl::RefPtr<PagerSource> self_ref_ TA_GUARDED(mtx_);

    // PortPacket used for sending all page requests to the pager service. The pager
    // dispatcher serves as packet_'s allocator. This informs the dispatcher when
    // packet_ is freed by the port, which lets the single packet be continuously reused
    // for all of the source's page requests.
    PortPacket packet_ = PortPacket(nullptr, this);
    // Bool indicating whether or not packet_ is currently queued in the port.
    bool packet_busy_ TA_GUARDED(mtx_) = false;
    // The page_request_t which corresponds to the current packet_.
    page_request_t* active_request_ TA_GUARDED(mtx_) = nullptr;
    // Queue of page_request_t's that have come in while packet_ is busy. The
    // head of this queue is sent to the port when packet_ is freed.
    list_node_t pending_requests_ TA_GUARDED(mtx_) = LIST_INITIAL_VALUE(pending_requests_);

    // page_request_t struct used for the complete message.
    page_request_t complete_request_ TA_GUARDED(mtx_) = {
        .node = LIST_INITIAL_CLEARED_VALUE, .offset = 0, .length = 0,
    };

    // Queues the page request, either sending it to the port or putting it in pending_requests_.
    void QueueMessageLocked(page_request_t* request) TA_REQ(mtx_);

    // Called when the packet becomes free. If pending_requests_ is non-empty, queues the
    // next request.
    void OnPacketFreedLocked() TA_REQ(mtx_);

    // Called by the dispatcher when it is about to go away. Handles cleaning up port's
    // reference to this object.
    void OnDispatcherClosed();

    friend PagerDispatcher;
};

class PagerDispatcher final : public SoloDispatcher<PagerDispatcher, ZX_DEFAULT_PAGER_RIGHTS> {
public:
    static zx_status_t Create(fbl::RefPtr<Dispatcher>* dispatcher, zx_rights_t* rights);
    ~PagerDispatcher() final;

    zx_status_t CreateSource(fbl::RefPtr<PortDispatcher> port,
                             uint64_t key, fbl::RefPtr<PageSource>* src);
    // Drop and return this object's reference to |src|. Must be called under
    // |src|'s lock to prevent races with dispatcher teardown.
    fbl::RefPtr<PagerSource> ReleaseSource(PagerSource* src) TA_REQ(src->mtx_);

    zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_PAGER; }

    void on_zero_handles() final;

private:
    explicit PagerDispatcher();

    fbl::Canary<fbl::magic("PGRD")> canary_;

    mutable DECLARE_MUTEX(PagerDispatcher) list_mtx_;
    fbl::DoublyLinkedList<fbl::RefPtr<PagerSource>> srcs_ TA_GUARDED(list_mtx_);
};
