/*
 * 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.
 */

#define LOG_TAG "FMQ_EventFlags"

#include <fmq/EventFlag.h>
#include <linux/futex.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <new>

namespace android {
namespace hardware {

status_t EventFlag::createEventFlag(int fd, off_t offset, EventFlag** flag) {
    if (flag == nullptr) {
        return BAD_VALUE;
    }

    status_t status = NO_MEMORY;
    *flag = nullptr;

    EventFlag* evFlag = new (std::nothrow) EventFlag(fd, offset, &status);
    if (evFlag != nullptr) {
        if (status == NO_ERROR) {
            *flag = evFlag;
        } else {
            delete evFlag;
        }
    }

    return status;
}

status_t EventFlag::createEventFlag(std::atomic<uint32_t>* fwAddr,
                                    EventFlag** flag) {
    if (flag == nullptr) {
        return BAD_VALUE;
    }

    status_t status = NO_MEMORY;
    *flag  = nullptr;

    EventFlag* evFlag = new (std::nothrow) EventFlag(fwAddr, &status);
    if (evFlag != nullptr) {
        if (status == NO_ERROR) {
            *flag = evFlag;
        } else {
            delete evFlag;
        }
    }

    return status;
}

/*
 * mmap memory for the futex word
 */
EventFlag::EventFlag(int fd, off_t offset, status_t* status) {
    mEfWordPtr = static_cast<std::atomic<uint32_t>*>(mmap(NULL,
                                                          sizeof(std::atomic<uint32_t>),
                                                          PROT_READ | PROT_WRITE,
                                                          MAP_SHARED, fd, offset));
    mEfWordNeedsUnmapping = true;
    if (mEfWordPtr != MAP_FAILED) {
        *status = NO_ERROR;
    } else {
        *status = -errno;
        ALOGE("Attempt to mmap event flag word failed: %s\n", strerror(errno));
    }
}

/*
 * Use this constructor if we already know where the futex word for
 * the EventFlag group lives.
 */
EventFlag::EventFlag(std::atomic<uint32_t>* fwAddr, status_t* status) {
    *status = NO_ERROR;
    if (fwAddr == nullptr) {
        *status = BAD_VALUE;
    } else {
        mEfWordPtr = fwAddr;
    }
}

/*
 * Set the specified bits of the futex word here and wake up any
 * thread waiting on any of the bits.
 */
status_t EventFlag::wake(uint32_t bitmask) {
    /*
     * Return early if there are no set bits in bitmask.
     */
    if (bitmask == 0) {
        return NO_ERROR;
    }

    status_t status = NO_ERROR;
    uint32_t old = std::atomic_fetch_or(mEfWordPtr, bitmask);
    /*
     * No need to call FUTEX_WAKE_BITSET if there were deferred wakes
     * already available for all set bits from bitmask.
     */
    if ((~old & bitmask) != 0) {
        int ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAKE_BITSET,
                          INT_MAX, NULL, NULL, bitmask);
        if (ret == -1) {
            status = -errno;
            ALOGE("Error in event flag wake attempt: %s\n", strerror(errno));
        }
    }
    return status;
}

/*
 * Wait for any of the bits in the bitmask to be set
 * and return which bits caused the return.
 */
status_t EventFlag::waitHelper(uint32_t bitmask, uint32_t* efState, int64_t timeoutNanoSeconds) {
    /*
     * Return early if there are no set bits in bitmask.
     */
    if (bitmask == 0 || efState == nullptr) {
        return BAD_VALUE;
    }

    status_t status = NO_ERROR;
    uint32_t old = std::atomic_fetch_and(mEfWordPtr, ~bitmask);
    uint32_t setBits = old & bitmask;
    /*
     * If there was a deferred wake available, no need to call FUTEX_WAIT_BITSET.
     */
    if (setBits != 0) {
        *efState = setBits;
        return status;
    }

    uint32_t efWord = old & ~bitmask;
    /*
     * The syscall will put the thread to sleep only
     * if the futex word still contains the expected
     * value i.e. efWord. If the futex word contents have
     * changed, it fails with the error EAGAIN; If a timeout
     * is specified and exceeded the syscall fails with ETIMEDOUT.
     */
    int ret = 0;
    if (timeoutNanoSeconds) {
        struct timespec waitTimeAbsolute;
        addNanosecondsToCurrentTime(timeoutNanoSeconds, &waitTimeAbsolute);

        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET,
                      efWord, &waitTimeAbsolute, NULL, bitmask);
    } else {
        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET, efWord, NULL, NULL, bitmask);
    }
    if (ret == -1) {
        status = -errno;
        if (status != -EAGAIN && status != -ETIMEDOUT) {
            ALOGE("Event flag wait was unsuccessful: %s\n", strerror(errno));
        }
        *efState = 0;
    } else {
        old = std::atomic_fetch_and(mEfWordPtr, ~bitmask);
        *efState = old & bitmask;

        if (*efState == 0) {
            /* Return -EINTR for a spurious wakeup */
            status = -EINTR;
        }
    }
    return status;
}

/*
 * Wait for any of the bits in the bitmask to be set
 * and return which bits caused the return. If 'retry'
 * is true, wait again on a spurious wake-up.
 */
status_t EventFlag::wait(uint32_t bitmask,
                         uint32_t* efState,
                         int64_t timeoutNanoSeconds,
                         bool retry) {
    if (!retry) {
        return waitHelper(bitmask, efState, timeoutNanoSeconds);
    }

    bool shouldTimeOut = timeoutNanoSeconds != 0;
    int64_t prevTimeNs = shouldTimeOut ? android::elapsedRealtimeNano() : 0;
    status_t status;
    while (true) {
        if (shouldTimeOut) {
            int64_t currentTimeNs = android::elapsedRealtimeNano();
            /*
             * Decrement TimeOutNanos to account for the time taken to complete the last
             * iteration of the while loop.
             */
            timeoutNanoSeconds -= currentTimeNs - prevTimeNs;
            prevTimeNs = currentTimeNs;
            if (timeoutNanoSeconds <= 0) {
                status = -ETIMEDOUT;
                *efState = 0;
                break;
            }
        }

        status = waitHelper(bitmask, efState, timeoutNanoSeconds);
        if ((status != -EAGAIN) && (status != -EINTR)) {
            break;
        }
    }
    return status;
}

status_t EventFlag::unmapEventFlagWord(std::atomic<uint32_t>* efWordPtr,
                                       bool* efWordNeedsUnmapping) {
    status_t status = NO_ERROR;
    if (*efWordNeedsUnmapping) {
        int ret = munmap(efWordPtr, sizeof(std::atomic<uint32_t>));
        if (ret != 0) {
            status = -errno;
            ALOGE("Error in deleting event flag group: %s\n", strerror(errno));
        }
        *efWordNeedsUnmapping = false;
    }
    return status;
}

status_t EventFlag::deleteEventFlag(EventFlag** evFlag) {
    if (evFlag == nullptr || *evFlag == nullptr) {
        return BAD_VALUE;
    }

    status_t status = unmapEventFlagWord((*evFlag)->mEfWordPtr,
                                         &(*evFlag)->mEfWordNeedsUnmapping);
    delete *evFlag;
    *evFlag = nullptr;

    return status;
}

void EventFlag::addNanosecondsToCurrentTime(int64_t nanoSeconds, struct timespec* waitTime) {
    static constexpr int64_t kNanosPerSecond = 1000000000;

    clock_gettime(CLOCK_MONOTONIC, waitTime);
    waitTime->tv_sec += nanoSeconds / kNanosPerSecond;
    waitTime->tv_nsec += nanoSeconds % kNanosPerSecond;

    if (waitTime->tv_nsec >= kNanosPerSecond) {
        waitTime->tv_sec++;
        waitTime->tv_nsec -= kNanosPerSecond;
    }
}

EventFlag::~EventFlag() {
    unmapEventFlagWord(mEfWordPtr, &mEfWordNeedsUnmapping);
}

}  // namespace hardware
}  // namespace android
