Home | History | Annotate | Download | only in fmq
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef HIDL_EVENTFLAG_H
     18 #define HIDL_EVENTFLAG_H
     19 
     20 #include <time.h>
     21 #include <utils/Errors.h>
     22 #include <atomic>
     23 
     24 namespace android {
     25 namespace hardware {
     26 
     27 /**
     28  * EventFlag is an abstraction that application code utilizing FMQ can use to wait on
     29  * conditions like full, empty, data available etc. The same EventFlag object
     30  * can be used with multiple FMQs.
     31  */
     32 struct EventFlag {
     33     /**
     34      * Create an event flag object with mapping information.
     35      *
     36      * @param fd File descriptor to be mmapped to create the event flag word.
     37      * There is no transfer of ownership of the fd. The caller will still
     38      * own the fd for the purpose of closing it.
     39      * @param offset Offset parameter to mmap.
     40      * @param ef Pointer to address of the EventFlag object that gets created. Will be set to
     41      * nullptr if unsuccesful.
     42      *
     43      * @return status Returns a status_t error code. Likely error codes are
     44      * NO_ERROR if the method is successful or BAD_VALUE due to invalid
     45      * mapping arguments.
     46      */
     47     static status_t createEventFlag(int fd, off_t offset, EventFlag** ef);
     48 
     49     /**
     50      * Create an event flag object from the address of the flag word.
     51      *
     52      * @param  efWordPtr Pointer to the event flag word.
     53      * @param status Returns a status_t error code. Likely error codes are
     54      * NO_ERROR if the method is successful or BAD_VALUE if efWordPtr is a null
     55      * pointer.
     56      * @param ef Pointer to the address of the EventFlag object that gets created. Will be set to
     57      * nullptr if unsuccesful.
     58      *
     59      * @return Returns a status_t error code. Likely error codes are
     60      * NO_ERROR if the method is successful or BAD_VALUE if efAddr is a null
     61      * pointer.
     62      *
     63      */
     64     static status_t createEventFlag(std::atomic<uint32_t>* efWordPtr,
     65                                     EventFlag** ef);
     66 
     67     /**
     68      * Delete an EventFlag object.
     69      *
     70      * @param ef A double pointer to the EventFlag object to be destroyed.
     71      *
     72      * @return Returns a status_t error code. Likely error codes are
     73      * NO_ERROR if the method is successful or BAD_VALUE due to
     74      * a bad input parameter.
     75      */
     76     static status_t deleteEventFlag(EventFlag** ef);
     77 
     78     /**
     79      * Set the specified bits of the event flag word here and wake up a thread.
     80      * @param bitmask The bits to be set on the event flag word.
     81      *
     82      * @return Returns a status_t error code. Likely error codes are
     83      * NO_ERROR if the method is successful or BAD_VALUE if the bit mask
     84      * does not have any bits set.
     85      */
     86     status_t wake(uint32_t bitmask);
     87 
     88     /**
     89      * Wait for any of the bits in the bit mask to be set.
     90      *
     91      * @param bitmask The bits to wait on.
     92      * @param timeoutNanoSeconds Specifies timeout duration in nanoseconds. It is converted to
     93      * an absolute timeout for the wait according to the CLOCK_MONOTONIC clock.
     94      * @param efState The event flag bits that caused the return from wake.
     95      * @param retry If true, retry automatically for a spurious wake. If false,
     96      * will return -EINTR or -EAGAIN for a spurious wake.
     97      *
     98      * @return Returns a status_t error code. Likely error codes are
     99      * NO_ERROR if the method is successful, BAD_VALUE due to bad input
    100      * parameters, TIMED_OUT if the wait timedout as per the timeout
    101      * parameter, -EAGAIN or -EINTR to indicate that the caller needs to invoke
    102      * wait() again. -EAGAIN or -EINTR error codes will not be returned if
    103      * 'retry' is true since the method will retry waiting in that case.
    104      */
    105     status_t wait(uint32_t bitmask,
    106                   uint32_t* efState,
    107                   int64_t timeOutNanoSeconds = 0,
    108                   bool retry = false);
    109 private:
    110     bool mEfWordNeedsUnmapping = false;
    111     std::atomic<uint32_t>* mEfWordPtr = nullptr;
    112 
    113     /*
    114      * mmap memory for the event flag word.
    115      */
    116     EventFlag(int fd, off_t offset, status_t* status);
    117 
    118     /*
    119      * Use this constructor if we already know where the event flag word
    120      * lives.
    121      */
    122     EventFlag(std::atomic<uint32_t>* efWordPtr, status_t* status);
    123 
    124     /*
    125      * Disallow constructor without argument and copying.
    126      */
    127     EventFlag();
    128     EventFlag& operator=(const EventFlag& other) = delete;
    129     EventFlag(const EventFlag& other) = delete;
    130 
    131     /*
    132      * Wait for any of the bits in the bit mask to be set.
    133      */
    134     status_t waitHelper(uint32_t bitmask, uint32_t* efState, int64_t timeOutNanoSeconds);
    135 
    136     /*
    137      * Utility method to unmap the event flag word.
    138      */
    139     static status_t unmapEventFlagWord(std::atomic<uint32_t>* efWordPtr,
    140                                        bool* efWordNeedsUnmapping);
    141 
    142     /*
    143      * Utility method to convert timeout duration to an absolute CLOCK_MONOTONIC
    144      * clock time which is required by futex syscalls.
    145      */
    146     inline void addNanosecondsToCurrentTime(int64_t nanoseconds, struct timespec* timeAbs);
    147     ~EventFlag();
    148 };
    149 }  // namespace hardware
    150 }  // namespace android
    151 #endif
    152