// Copyright 2017 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

#include <object/fifo_dispatcher.h>

#include <string.h>

#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <lib/counters.h>
#include <object/handle.h>
#include <zircon/rights.h>

KCOUNTER(dispatcher_fifo_create_count, "dispatcher.fifo.create")
KCOUNTER(dispatcher_fifo_destroy_count, "dispatcher.fifo.destroy")

// static
zx_status_t FifoDispatcher::Create(size_t count, size_t elemsize, uint32_t options,
                                   KernelHandle<FifoDispatcher>* handle0,
                                   KernelHandle<FifoDispatcher>* handle1,
                                   zx_rights_t* rights) {
    // count and elemsize must be nonzero
    // count must be a power of two
    // total size must be <= kMaxSizeBytes
    if (!count || !elemsize || (count & (count - 1)) ||
        (count > kMaxSizeBytes) || (elemsize > kMaxSizeBytes) ||
        ((count * elemsize) > kMaxSizeBytes)) {
        return ZX_ERR_OUT_OF_RANGE;
    }

    fbl::AllocChecker ac;
    auto holder0 = fbl::AdoptRef(new (&ac) PeerHolder<FifoDispatcher>());
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;
    auto holder1 = holder0;

    auto data0 = ktl::unique_ptr<uint8_t[]>(new (&ac) uint8_t[count * elemsize]);
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    KernelHandle fifo0(fbl::AdoptRef(new (&ac) FifoDispatcher(ktl::move(holder0), options,
                                                              static_cast<uint32_t>(count),
                                                              static_cast<uint32_t>(elemsize),
                                                              ktl::move(data0))));
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    auto data1 = ktl::unique_ptr<uint8_t[]>(new (&ac) uint8_t[count * elemsize]);
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    KernelHandle fifo1(fbl::AdoptRef(new (&ac) FifoDispatcher(ktl::move(holder1), options,
                                                              static_cast<uint32_t>(count),
                                                              static_cast<uint32_t>(elemsize),
                                                              ktl::move(data1))));
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    fifo0.dispatcher()->Init(fifo1.dispatcher());
    fifo1.dispatcher()->Init(fifo0.dispatcher());

    *rights = default_rights();
    *handle0 = ktl::move(fifo0);
    *handle1 = ktl::move(fifo1);
    return ZX_OK;
}

FifoDispatcher::FifoDispatcher(fbl::RefPtr<PeerHolder<FifoDispatcher>> holder,
                               uint32_t /*options*/, uint32_t count, uint32_t elem_size,
                               ktl::unique_ptr<uint8_t[]> data)
    : PeeredDispatcher(ktl::move(holder), ZX_FIFO_WRITABLE),
      elem_count_(count), elem_size_(elem_size), mask_(count - 1),
      head_(0u), tail_(0u), data_(ktl::move(data)) {
    kcounter_add(dispatcher_fifo_create_count, 1);
}

FifoDispatcher::~FifoDispatcher() {
    kcounter_add(dispatcher_fifo_destroy_count, 1);
}

// Thread safety analysis disabled as this happens during creation only,
// when no other thread could be accessing the object.
void FifoDispatcher::Init(fbl::RefPtr<FifoDispatcher> other) TA_NO_THREAD_SAFETY_ANALYSIS {
    peer_ = ktl::move(other);
    peer_koid_ = peer_->get_koid();
}

zx_status_t FifoDispatcher::UserSignalSelfLocked(uint32_t clear_mask, uint32_t set_mask) {
    canary_.Assert();
    UpdateStateLocked(clear_mask, set_mask);
    return ZX_OK;
}

void FifoDispatcher::on_zero_handles_locked() {
    canary_.Assert();
}

void FifoDispatcher::OnPeerZeroHandlesLocked() {
    canary_.Assert();

    UpdateStateLocked(ZX_FIFO_WRITABLE, ZX_FIFO_PEER_CLOSED);
}

zx_status_t FifoDispatcher::WriteFromUser(size_t elem_size, user_in_ptr<const uint8_t> ptr,
                                          size_t count, size_t* actual)
    TA_NO_THREAD_SAFETY_ANALYSIS {
    canary_.Assert();

    Guard<fbl::Mutex> guard{get_lock()};
    if (!peer_)
        return ZX_ERR_PEER_CLOSED;
    return peer_->WriteSelfLocked(elem_size, ptr, count, actual);
}

zx_status_t FifoDispatcher::WriteSelfLocked(size_t elem_size, user_in_ptr<const uint8_t> ptr,
                                            size_t count, size_t* actual)
    TA_NO_THREAD_SAFETY_ANALYSIS {
    canary_.Assert();

    if (elem_size != elem_size_)
        return ZX_ERR_OUT_OF_RANGE;
    if (count == 0)
        return ZX_ERR_OUT_OF_RANGE;

    uint32_t old_head = head_;

    // total number of available empty slots in the fifo
    size_t avail = elem_count_ - (head_ - tail_);

    if (avail == 0)
        return ZX_ERR_SHOULD_WAIT;

    bool was_empty = (avail == elem_count_);

    if (count > avail)
        count = avail;

    while (count > 0) {
        uint32_t offset = (head_ & mask_);

        // number of slots from target to end, inclusive
        uint32_t n = elem_count_ - offset;

        // number of slots we can actually copy
        size_t to_copy = (count > n) ? n : count;

        zx_status_t status = ptr.copy_array_from_user(&data_[offset * elem_size_],
                                                      to_copy * elem_size_);
        if (status != ZX_OK) {
            // roll back, in case this is the second copy
            head_ = old_head;
            return ZX_ERR_INVALID_ARGS;
        }

        // adjust head and count
        // due to size limitations on fifo, to_copy will always fit in a u32
        head_ += static_cast<uint32_t>(to_copy);
        count -= to_copy;
        ptr = ptr.byte_offset(to_copy * elem_size_);
    }

    // if was empty, we've become readable
    if (was_empty)
        UpdateStateLocked(0u, ZX_FIFO_READABLE);

    // if now full, we're no longer writable
    if (elem_count_ == (head_ - tail_))
        peer_->UpdateStateLocked(ZX_FIFO_WRITABLE, 0u);

    *actual = (head_ - old_head);
    return ZX_OK;
}

zx_status_t FifoDispatcher::ReadToUser(size_t elem_size, user_out_ptr<uint8_t> ptr, size_t count,
                                       size_t* actual)
    TA_NO_THREAD_SAFETY_ANALYSIS {
    canary_.Assert();

    if (elem_size != elem_size_)
        return ZX_ERR_OUT_OF_RANGE;
    if (count == 0)
        return ZX_ERR_OUT_OF_RANGE;

    Guard<fbl::Mutex> guard{get_lock()};

    uint32_t old_tail = tail_;

    // total number of available entries to read from the fifo
    size_t avail = (head_ - tail_);

    if (avail == 0)
        return peer_ ? ZX_ERR_SHOULD_WAIT : ZX_ERR_PEER_CLOSED;

    bool was_full = (avail == elem_count_);

    if (count > avail)
        count = avail;

    while (count > 0) {
        uint32_t offset = (tail_ & mask_);

        // number of slots from target to end, inclusive
        uint32_t n = elem_count_ - offset;

        // number of slots we can actually copy
        size_t to_copy = (count > n) ? n : count;

        zx_status_t status = ptr.copy_array_to_user(&data_[offset * elem_size_],
                                                    to_copy * elem_size_);
        if (status != ZX_OK) {
            // roll back, in case this is the second copy
            tail_ = old_tail;
            return ZX_ERR_INVALID_ARGS;
        }

        // adjust tail and count
        // due to size limitations on fifo, to_copy will always fit in a u32
        tail_ += static_cast<uint32_t>(to_copy);
        count -= to_copy;
        ptr = ptr.byte_offset(to_copy * elem_size_);
    }

    // if we were full, we have become writable
    if (was_full && peer_)
        peer_->UpdateStateLocked(0u, ZX_FIFO_WRITABLE);

    // if we've become empty, we're no longer readable
    if ((head_ - tail_) == 0)
        UpdateStateLocked(ZX_FIFO_READABLE, 0u);

    *actual = (tail_ - old_tail);
    return ZX_OK;
}
