// 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/intrusive_double_list.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <kernel/event.h>
#include <kernel/lockdep.h>
#include <kernel/mutex.h>
#include <vm/page.h>
#include <vm/vm.h>
#include <zircon/types.h>

// A page source has two parts - the PageSource and the PageSourceCallback. The
// PageSource is responsible for generic functionality, mostly around managing
// the lifecycle of page requests. The PageSourceCallback is responsible for
// actually providing the pages.
//
// The synchronous fulfillment of requests is fairly straightforward, with
// direct calls from the vm object to the PageSource to the PageSourceCallback.
//
// For asynchronous requests, the lifecycle is as follows:
//   1) A vm object requests a page with PageSource::GetPage
//   2) PageSource starts tracking the request's PageRequest and then
//      forwards the request to PageSourceCallback::GetPageAsync.
//   3) The caller waits for the request with PageRequest::Wait
//   4) At some point, whatever is backing the callback provides pages
//      to the vm object (e.g. with VmObjectPaged::SupplyPages).
//   5) The vm object calls PageSource::OnPagesSupplied, which signals
//      any PageRequests that have been fulfilled.
//   6) The caller wakes up and queries the vm object again, by which
//      point the request page will be present.

class PageRequest;

// A simple page_request struct for use by the PageSourceCallback implementation.
typedef struct page_request {
    list_node_t node;
    uint64_t offset;
    uint64_t length;
} page_request_t;

// Object which provides pages to a vm_object.
class PageSource : public fbl::RefCounted<PageSource> {
public:
    PageSource();
    virtual ~PageSource();

    // Sends a request to the backing source to provide the requested page.
    //
    // Returns ZX_OK if the request was synchronously fulfilled.
    // Returns ZX_ERR_SHOULD_WAIT if the request will be asynchronously
    // fulfilled. The caller should wait on |req|.
    // Returns ZX_ERR_NOT_FOUND if the request cannot be fulfilled.
    zx_status_t GetPage(uint64_t offset, PageRequest* req,
                        vm_page_t** const page_out, paddr_t* const pa_out);

    // Updates the request tracking metadata to account for pages [offset, len) having
    // been supplied to the owning vmo.
    void OnPagesSupplied(uint64_t offset, uint64_t len);

    // Detaches the source. All future calls into the page source will fail. All
    // pending read transactions are aborted. Pending flush transactions will still
    // be serviced.
    void Detach();

    // Closes the source. All pending transactions will be aborted and all future
    // calls will fail.
    void Close();

protected:
    // Synchronously gets a page from the backing source.
    virtual bool GetPage(uint64_t offset,
                         vm_page_t** const page_out, paddr_t* const pa_out) = 0;
    // Informs the backing source of a page request. The callback has ownership
    // of |request| until the async request is cancelled.
    virtual void GetPageAsync(page_request_t* request) = 0;
    // Informs the backing source that a page request has been fulfilled. This
    // must be called for all requests that are raised.
    virtual void ClearAsyncRequest(page_request_t* request) = 0;
    // Swaps the backing memory for a request. Assumes that |old|
    // and |new_request| have the same type, offset, and length.
    virtual void SwapRequest(page_request_t* old, page_request_t* new_req) = 0;

    // OnDetach is called once no more calls to GetPage/GetPageAsync will be made. It
    // will be called before OnClose and will only be called once.
    virtual void OnDetach() = 0;
    // After OnClose is called, no more calls will be made except for ::WaitOnEvent.
    virtual void OnClose() = 0;

    virtual zx_status_t WaitOnEvent(event_t* event) = 0;

private:
    fbl::Canary<fbl::magic("VMPS")> canary_;

    mutable DECLARE_MUTEX(PageSource) page_source_mtx_;
    bool detached_ TA_GUARDED(page_source_mtx_) = false;
    bool closed_ TA_GUARDED(page_source_mtx_) = false;

    // Tree of pending_request structs which have been sent to the callback.
    fbl::WAVLTree<uint64_t, PageRequest*> outstanding_requests_ TA_GUARDED(page_source_mtx_);

    // Wakes up the given PageRequest and all overlapping requests.
    void CompleteRequestLocked(PageRequest* head) TA_REQ(page_source_mtx_);

    // Removes |request| from any internal tracking. Called by a PageRequest if
    // it needs to abort itself.
    void CancelRequest(PageRequest* request) TA_EXCL(page_source_mtx_);

    friend PageRequest;
};

// Object which is used to make delayed page requests to a PageSource
class PageRequest : public fbl::WAVLTreeContainable<PageRequest*>,
                    public fbl::DoublyLinkedListable<PageRequest*> {
public:
    explicit PageRequest() {}
    ~PageRequest();

    // Returns ZX_OK on success or ZX_ERR_INTERNAL_INTR_KILLED if the thread was killed.
    zx_status_t Wait();

    uint64_t GetKey() const { return offset_; }

    DISALLOW_COPY_ASSIGN_AND_MOVE(PageRequest);

private:
    void Init(fbl::RefPtr<PageSource> src, uint64_t offset);

    // The page source this request is currently associated with.
    fbl::RefPtr<PageSource> src_;
    // Event signaled when the request is fulfilled.
    event_t event_;
    // PageRequests are active if offset_ is not UINT64_MAX.
    uint64_t offset_ = UINT64_MAX;

    // List node for overlapping requests.
    fbl::DoublyLinkedList<PageRequest*> overlap_;

    // Request struct for the PageSourceCallback
    page_request_t read_request_;

    friend PageSource;
};
