/*
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sim/futex_map.hh>

namespace gem5
{

FutexKey::FutexKey(uint64_t addr_in, uint64_t tgid_in)
        : addr(addr_in), tgid(tgid_in) {}

bool
FutexKey::operator==(const FutexKey &in) const
{
    return addr == in.addr && tgid == in.tgid;
}

WaiterState::WaiterState(ThreadContext* _tc, int _bitmask)
      : tc(_tc), bitmask(_bitmask) { }

bool
WaiterState::checkMask(int wakeup_bitmask) const
{
    return bitmask & wakeup_bitmask;
}

void
FutexMap::suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
{
    suspend_bitset(addr, tgid, tc, 0xffffffff);
}

int
FutexMap::wakeup(Addr addr, uint64_t tgid, int count)
{
    FutexKey key(addr, tgid);
    auto it = find(key);

    if (it == end())
        return 0;

    int woken_up = 0;
    auto &waiterList = it->second;

    while (!waiterList.empty() && woken_up < count) {
        // Threads may be woken up by access to locked
        // memory addresses outside of syscalls, so we
        // must only count threads that were actually
        // woken up by this syscall.
        auto& tc = waiterList.front().tc;
        tc->activate();
        woken_up++;
        waiterList.pop_front();
        waitingTcs.erase(tc);
    }

    if (waiterList.empty())
        erase(it);

    return woken_up;
}

void
FutexMap::suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc,
               int bitmask)
{
    FutexKey key(addr, tgid);
    auto it = find(key);

    if (it == end()) {
        WaiterList waiterList {WaiterState(tc, bitmask)};
        insert({key, waiterList});
    } else {
        it->second.push_back(WaiterState(tc, bitmask));
    }
    waitingTcs.emplace(tc);

    /** Suspend the thread context */
    tc->suspend();
}

int
FutexMap::wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
{
    FutexKey key(addr, tgid);
    auto it = find(key);

    if (it == end())
        return 0;

    int woken_up = 0;

    auto &waiterList = it->second;
    auto iter = waiterList.begin();

    while (iter != waiterList.end()) {
        WaiterState& waiter = *iter;

        if (waiter.checkMask(bitmask)) {
            waiter.tc->activate();
            iter = waiterList.erase(iter);
            waitingTcs.erase(waiter.tc);
            woken_up++;
        } else {
            ++iter;
        }
    }

    if (waiterList.empty())
        erase(it);

    return woken_up;
}

int
FutexMap::requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
{
    FutexKey key1(addr1, tgid);
    auto it1 = find(key1);

    if (it1 == end())
        return 0;

    int woken_up = 0;
    auto &waiterList1 = it1->second;

    while (!waiterList1.empty() && woken_up < count) {
        waiterList1.front().tc->activate();
        waiterList1.pop_front();
        woken_up++;
    }

    WaiterList tmpList;
    int requeued = 0;

    while (!waiterList1.empty() && requeued < count2) {
      auto w = waiterList1.front();
      waiterList1.pop_front();
      tmpList.push_back(w);
      requeued++;
    }

    FutexKey key2(addr2, tgid);
    auto it2 = find(key2);

    if (it2 == end() && requeued > 0) {
        insert({key2, tmpList});
    } else {
        it2->second.insert(it2->second.end(),
                           tmpList.begin(), tmpList.end());
    }

    if (waiterList1.empty())
        erase(it1);

    return woken_up + requeued;
}

bool
FutexMap::is_waiting(ThreadContext *tc)
{
    return waitingTcs.find(tc) != waitingTcs.end();
}

} // namespace gem5
