blob: af184484c1efcabfd18669d16f24f243f0f39538 [file] [log] [blame]
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -08001/*
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
24namespace android {
25namespace 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 */
32struct 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.
Hridya Valsaraju10f59dc2016-12-20 12:50:44 -080092 * @param timeoutNanoSeconds Specifies timeout duration in nanoseconds. It is converted to
93 * an absolute timeout for the wait according to the CLOCK_MONOTONIC clock.
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -080094 * @param efState The event flag bits that caused the return from wake.
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -070095 * @param retry If true, retry automatically for a spurious wake. If false,
96 * will return -EINTR or -EAGAIN for a spurious wake.
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -080097 *
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
Hridya Valsaraju77c8aba2017-03-03 07:57:37 -0800101 * parameter, -EAGAIN or -EINTR to indicate that the caller needs to invoke
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -0700102 * 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.
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -0800104 */
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -0700105 status_t wait(uint32_t bitmask,
106 uint32_t* efState,
107 int64_t timeOutNanoSeconds = 0,
108 bool retry = false);
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -0800109private:
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 /*
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -0700132 * 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 /*
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -0800137 * Utility method to unmap the event flag word.
138 */
139 static status_t unmapEventFlagWord(std::atomic<uint32_t>* efWordPtr,
140 bool* efWordNeedsUnmapping);
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -0700141
Hridya Valsaraju10f59dc2016-12-20 12:50:44 -0800142 /*
Hridya Valsarajuf1aa0582017-03-21 11:33:33 -0700143 * Utility method to convert timeout duration to an absolute CLOCK_MONOTONIC
144 * clock time which is required by futex syscalls.
Hridya Valsaraju10f59dc2016-12-20 12:50:44 -0800145 */
146 inline void addNanosecondsToCurrentTime(int64_t nanoseconds, struct timespec* timeAbs);
Hridya Valsaraju8b0d5a52016-12-16 10:29:03 -0800147 ~EventFlag();
148};
149} // namespace hardware
150} // namespace android
151#endif