/*
 * 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 <linux/futex.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>

#include <new>

#include <fmq/EventFlag.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>

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
