18b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju/*
28b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Copyright (C) 2016 The Android Open Source Project
38b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju *
48b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Licensed under the Apache License, Version 2.0 (the "License");
58b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * you may not use this file except in compliance with the License.
68b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * You may obtain a copy of the License at
78b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju *
88b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju *      http://www.apache.org/licenses/LICENSE-2.0
98b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju *
108b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Unless required by applicable law or agreed to in writing, software
118b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * distributed under the License is distributed on an "AS IS" BASIS,
128b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * See the License for the specific language governing permissions and
148b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * limitations under the License.
158b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju */
168b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
178b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#define LOG_TAG "FMQ_EventFlags"
188b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
198b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <fmq/EventFlag.h>
208b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <linux/futex.h>
218b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <sys/mman.h>
228b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <sys/syscall.h>
2326531e0ec6fa5b80be2be9ea0017b8ee1638f377Steven Moreland#include <unistd.h>
248b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <utils/Log.h>
25f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju#include <utils/SystemClock.h>
268b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju#include <new>
278b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
288b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajunamespace android {
298b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajunamespace hardware {
308b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
318b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajustatus_t EventFlag::createEventFlag(int fd, off_t offset, EventFlag** flag) {
328b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (flag == nullptr) {
338b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return BAD_VALUE;
348b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
358b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
368b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = NO_MEMORY;
378b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    *flag = nullptr;
388b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
398b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    EventFlag* evFlag = new (std::nothrow) EventFlag(fd, offset, &status);
408b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (evFlag != nullptr) {
418b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        if (status == NO_ERROR) {
428b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            *flag = evFlag;
438b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        } else {
448b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            delete evFlag;
458b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        }
468b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
478b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
488b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
498b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
508b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
518b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajustatus_t EventFlag::createEventFlag(std::atomic<uint32_t>* fwAddr,
528b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju                                    EventFlag** flag) {
538b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (flag == nullptr) {
548b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return BAD_VALUE;
558b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
568b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
578b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = NO_MEMORY;
588b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    *flag  = nullptr;
598b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
608b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    EventFlag* evFlag = new (std::nothrow) EventFlag(fwAddr, &status);
618b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (evFlag != nullptr) {
628b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        if (status == NO_ERROR) {
638b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            *flag = evFlag;
648b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        } else {
658b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            delete evFlag;
668b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        }
678b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
688b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
698b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
708b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
718b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
728b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju/*
738b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * mmap memory for the futex word
748b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju */
758b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya ValsarajuEventFlag::EventFlag(int fd, off_t offset, status_t* status) {
768b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    mEfWordPtr = static_cast<std::atomic<uint32_t>*>(mmap(NULL,
7710f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju                                                          sizeof(std::atomic<uint32_t>),
7810f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju                                                          PROT_READ | PROT_WRITE,
7910f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju                                                          MAP_SHARED, fd, offset));
808b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    mEfWordNeedsUnmapping = true;
818b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (mEfWordPtr != MAP_FAILED) {
828b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *status = NO_ERROR;
838b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    } else {
848b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *status = -errno;
858b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        ALOGE("Attempt to mmap event flag word failed: %s\n", strerror(errno));
868b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
878b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
888b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
898b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju/*
908b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Use this constructor if we already know where the futex word for
918b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * the EventFlag group lives.
928b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju */
938b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya ValsarajuEventFlag::EventFlag(std::atomic<uint32_t>* fwAddr, status_t* status) {
948b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    *status = NO_ERROR;
958b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (fwAddr == nullptr) {
968b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *status = BAD_VALUE;
978b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    } else {
988b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        mEfWordPtr = fwAddr;
998b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1008b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
1018b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
1028b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju/*
1038b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Set the specified bits of the futex word here and wake up any
1048b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * thread waiting on any of the bits.
1058b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju */
1068b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajustatus_t EventFlag::wake(uint32_t bitmask) {
1078b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    /*
1088b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * Return early if there are no set bits in bitmask.
1098b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     */
1108b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (bitmask == 0) {
1118b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return NO_ERROR;
1128b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1138b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
1148b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = NO_ERROR;
1158b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    uint32_t old = std::atomic_fetch_or(mEfWordPtr, bitmask);
1168b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    /*
117af605d4be8b9a0c190b44b85a582a4b9a5f99f3bHridya Valsaraju     * No need to call FUTEX_WAKE_BITSET if there were deferred wakes
118af605d4be8b9a0c190b44b85a582a4b9a5f99f3bHridya Valsaraju     * already available for all set bits from bitmask.
1198b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     */
1208b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if ((~old & bitmask) != 0) {
1218b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        int ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAKE_BITSET,
12210f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju                          INT_MAX, NULL, NULL, bitmask);
1238b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        if (ret == -1) {
1248b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            status = -errno;
1258b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            ALOGE("Error in event flag wake attempt: %s\n", strerror(errno));
1268b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        }
1278b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1288b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
1298b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
1308b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
1318b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju/*
1328b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * Wait for any of the bits in the bitmask to be set
1338b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju * and return which bits caused the return.
1348b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju */
135f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsarajustatus_t EventFlag::waitHelper(uint32_t bitmask, uint32_t* efState, int64_t timeoutNanoSeconds) {
1368b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    /*
1378b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * Return early if there are no set bits in bitmask.
1388b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     */
1398b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (bitmask == 0 || efState == nullptr) {
1408b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return BAD_VALUE;
1418b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1428b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
1438b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = NO_ERROR;
1448b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    uint32_t old = std::atomic_fetch_and(mEfWordPtr, ~bitmask);
1458b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    uint32_t setBits = old & bitmask;
1468b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    /*
1478b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * If there was a deferred wake available, no need to call FUTEX_WAIT_BITSET.
1488b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     */
1498b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (setBits != 0) {
1508b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *efState = setBits;
1518b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return status;
1528b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1538b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
1548b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    uint32_t efWord = old & ~bitmask;
1558b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    /*
1568b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * The syscall will put the thread to sleep only
1578b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * if the futex word still contains the expected
1588b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     * value i.e. efWord. If the futex word contents have
1593c2dcb1856d0725f402751e1334044ef8eb1df87Andreas Huber     * changed, it fails with the error EAGAIN; If a timeout
1603c2dcb1856d0725f402751e1334044ef8eb1df87Andreas Huber     * is specified and exceeded the syscall fails with ETIMEDOUT.
1618b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju     */
16210f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    int ret = 0;
16310f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    if (timeoutNanoSeconds) {
16410f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        struct timespec waitTimeAbsolute;
16510f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        addNanosecondsToCurrentTime(timeoutNanoSeconds, &waitTimeAbsolute);
16610f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju
16710f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET,
16810f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju                      efWord, &waitTimeAbsolute, NULL, bitmask);
16910f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    } else {
17010f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET, efWord, NULL, NULL, bitmask);
17110f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    }
1728b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (ret == -1) {
1738b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        status = -errno;
1743c2dcb1856d0725f402751e1334044ef8eb1df87Andreas Huber        if (status != -EAGAIN && status != -ETIMEDOUT) {
1758b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            ALOGE("Event flag wait was unsuccessful: %s\n", strerror(errno));
1768b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        }
1778b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *efState = 0;
1788b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    } else {
17992b79dc7938ad2b5e36aebef80d78b061db275b3Hridya Valsaraju        old = std::atomic_fetch_and(mEfWordPtr, ~bitmask);
18092b79dc7938ad2b5e36aebef80d78b061db275b3Hridya Valsaraju        *efState = old & bitmask;
18177c8aba447488b2507f9531fa17e80b06c5bb0dfHridya Valsaraju
18277c8aba447488b2507f9531fa17e80b06c5bb0dfHridya Valsaraju        if (*efState == 0) {
18377c8aba447488b2507f9531fa17e80b06c5bb0dfHridya Valsaraju            /* Return -EINTR for a spurious wakeup */
18477c8aba447488b2507f9531fa17e80b06c5bb0dfHridya Valsaraju            status = -EINTR;
18577c8aba447488b2507f9531fa17e80b06c5bb0dfHridya Valsaraju        }
1868b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
1878b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
1888b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
1898b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
190f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju/*
191f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju * Wait for any of the bits in the bitmask to be set
192f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju * and return which bits caused the return. If 'retry'
193f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju * is true, wait again on a spurious wake-up.
194f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju */
195f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsarajustatus_t EventFlag::wait(uint32_t bitmask,
196f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                         uint32_t* efState,
197f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                         int64_t timeoutNanoSeconds,
198f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                         bool retry) {
199f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    if (!retry) {
200f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        return waitHelper(bitmask, efState, timeoutNanoSeconds);
201f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    }
202f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju
203f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    bool shouldTimeOut = timeoutNanoSeconds != 0;
204f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    int64_t prevTimeNs = shouldTimeOut ? android::elapsedRealtimeNano() : 0;
205f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    status_t status;
206f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    while (true) {
207f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        if (shouldTimeOut) {
208f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            int64_t currentTimeNs = android::elapsedRealtimeNano();
209f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            /*
210f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju             * Decrement TimeOutNanos to account for the time taken to complete the last
211f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju             * iteration of the while loop.
212f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju             */
213f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            timeoutNanoSeconds -= currentTimeNs - prevTimeNs;
214f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            prevTimeNs = currentTimeNs;
215f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            if (timeoutNanoSeconds <= 0) {
216f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                status = -ETIMEDOUT;
217f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                *efState = 0;
218f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju                break;
219f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            }
220f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        }
221f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju
222f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        status = waitHelper(bitmask, efState, timeoutNanoSeconds);
223f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        if ((status != -EAGAIN) && (status != -EINTR)) {
224f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju            break;
225f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju        }
226f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    }
227f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju    return status;
228f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju}
229f542b5a8383ff3d03b1735f72a9524b5edf31071Hridya Valsaraju
2308b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajustatus_t EventFlag::unmapEventFlagWord(std::atomic<uint32_t>* efWordPtr,
2318b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju                                       bool* efWordNeedsUnmapping) {
2328b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = NO_ERROR;
2338b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (*efWordNeedsUnmapping) {
2348b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        int ret = munmap(efWordPtr, sizeof(std::atomic<uint32_t>));
2358b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        if (ret != 0) {
2368b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            status = -errno;
2378b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju            ALOGE("Error in deleting event flag group: %s\n", strerror(errno));
2388b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        }
2398b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        *efWordNeedsUnmapping = false;
2408b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
2418b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
2428b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
2438b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
2448b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsarajustatus_t EventFlag::deleteEventFlag(EventFlag** evFlag) {
2458b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    if (evFlag == nullptr || *evFlag == nullptr) {
2468b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju        return BAD_VALUE;
2478b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    }
2488b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
2498b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    status_t status = unmapEventFlagWord((*evFlag)->mEfWordPtr,
2508b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju                                         &(*evFlag)->mEfWordNeedsUnmapping);
2518b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    delete *evFlag;
2528b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    *evFlag = nullptr;
2538b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
2548b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    return status;
2558b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
2568b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
25710f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsarajuvoid EventFlag::addNanosecondsToCurrentTime(int64_t nanoSeconds, struct timespec* waitTime) {
25810f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    static constexpr int64_t kNanosPerSecond = 1000000000;
25910f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju
26010f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    clock_gettime(CLOCK_MONOTONIC, waitTime);
26110f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    waitTime->tv_sec += nanoSeconds / kNanosPerSecond;
26210f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    waitTime->tv_nsec += nanoSeconds % kNanosPerSecond;
26310f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju
26410f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    if (waitTime->tv_nsec >= kNanosPerSecond) {
26510f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        waitTime->tv_sec++;
26610f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju        waitTime->tv_nsec -= kNanosPerSecond;
26710f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju    }
26810f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju}
26910f59dc950f859119431f0e0c8368a882a7fa586Hridya Valsaraju
2708b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya ValsarajuEventFlag::~EventFlag() {
2718b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju    unmapEventFlagWord(mEfWordPtr, &mEfWordNeedsUnmapping);
2728b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}
2738b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju
2748b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}  // namespace hardware
2758b0d5a5c20cfc786f783e44442787c5ea53f0001Hridya Valsaraju}  // namespace android
276