/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>
#include <limits.h>
#include <audio_utils/fifo_index.h>
#include <audio_utils/futex.h>

// These are not implemented within <audio_utils/fifo_index.h>
// so that we don't expose futex.

// FIXME should inline these, so that writer_T can also inline it

uint32_t audio_utils_fifo_index::loadSingleThreaded()
{
    // TODO Should be a read from simple non-atomic variable
    return atomic_load_explicit(&mIndex, std::memory_order_relaxed);
}

uint32_t audio_utils_fifo_index::loadAcquire()
{
    return atomic_load_explicit(&mIndex, std::memory_order_acquire);
}

void audio_utils_fifo_index::storeSingleThreaded(uint32_t value)
{
    // TODO Should be a write to simple non-atomic variable
    atomic_store_explicit(&mIndex, value, std::memory_order_relaxed);
}

void audio_utils_fifo_index::storeRelease(uint32_t value)
{
    atomic_store_explicit(&mIndex, value, std::memory_order_release);
}

int audio_utils_fifo_index::wait(int op, uint32_t expected, const struct timespec *timeout)
{
    return sys_futex(&mIndex, op, expected, timeout, NULL, 0);
}

int audio_utils_fifo_index::wake(int op, int waiters)
{
    return sys_futex(&mIndex, op, waiters, NULL, NULL, 0);
}

// ----------------------------------------------------------------------------

#if 0   // TODO not currently used, review this code later: bug 150627616

RefIndexDeferredStoreReleaseDeferredWake::RefIndexDeferredStoreReleaseDeferredWake(
        audio_utils_fifo_index& index)
    : mIndex(index), mValue(0), mWriteback(false), mWaiters(0), mWakeOp(FUTEX_WAIT_PRIVATE)
{
}

RefIndexDeferredStoreReleaseDeferredWake::~RefIndexDeferredStoreReleaseDeferredWake()
{
    writeback();
    wakeNowIfNeeded();
}

void RefIndexDeferredStoreReleaseDeferredWake::set(uint32_t value) {
    mValue = value;
    mWriteback = true;
}

void RefIndexDeferredStoreReleaseDeferredWake::writeback()
{
    if (mWriteback) {
        // TODO When part of a collection, should use relaxed for all but the last writeback
        mIndex.storeRelease(mValue);
        mWriteback = false;
    }
}

void RefIndexDeferredStoreReleaseDeferredWake::writethrough(uint32_t value) {
    set(value);
    writeback();
}

void RefIndexDeferredStoreReleaseDeferredWake::wakeDeferred(int op, int waiters)
{
    if (waiters <= 0) {
        return;
    }
    // default is FUTEX_WAKE_PRIVATE
    if (op == FUTEX_WAKE) {
        mWakeOp = FUTEX_WAKE;
    }
    if (waiters < INT_MAX - mWaiters) {
        mWaiters += waiters;
    } else {
        mWaiters = INT_MAX;
    }
}

void RefIndexDeferredStoreReleaseDeferredWake::wakeNowIfNeeded()
{
    if (mWaiters > 0) {
        mIndex.wake(mWakeOp, mWaiters);
        mWaiters = 0;
        mWakeOp = FUTEX_WAKE_PRIVATE;
    }
}

void RefIndexDeferredStoreReleaseDeferredWake::wakeNow(int op, int waiters)
{
    wakeDeferred(op, waiters);
    wakeNowIfNeeded();
}

////

RefIndexCachedLoadAcquireDeferredWait::RefIndexCachedLoadAcquireDeferredWait(
        audio_utils_fifo_index& index)
    : mIndex(index), mValue(0), mLoaded(false)
{
}

RefIndexCachedLoadAcquireDeferredWait::~RefIndexCachedLoadAcquireDeferredWait()
{
}

uint32_t RefIndexCachedLoadAcquireDeferredWait::get()
{
    prefetch();
    return mValue;
}

void RefIndexCachedLoadAcquireDeferredWait::prefetch()
{
    if (!mLoaded) {
        // TODO When part of a collection, should use relaxed for all but the last load
        mValue = mIndex.loadAcquire();
        mLoaded = true;
    }
}

void RefIndexCachedLoadAcquireDeferredWait::invalidate()
{
    mLoaded = false;
}

#if 0
uint32_t RefIndexCachedLoadAcquireDeferredWait::readthrough()
{
    invalidate();
    return get();
}
#endif

int RefIndexCachedLoadAcquireDeferredWait::wait(int op, const struct timespec *timeout)
{
    if (!mLoaded) {
        return -EINVAL;
    }
    int err = mIndex.wait(op, mValue /*expected*/, timeout);
    invalidate();
    return err;
}

#endif  // 0
