MQDescriptor.h revision f022e5b55478756e66163cd6f85c91f5dc7c58cb
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 _FMSGQ_DESCRIPTOR_H 18#define _FMSGQ_DESCRIPTOR_H 19 20#include <android-base/macros.h> 21#include <cutils/native_handle.h> 22#include <hidl/HidlInternal.h> 23#include <hidl/HidlSupport.h> 24 25namespace android { 26namespace hardware { 27 28typedef uint64_t RingBufferPosition; 29 30struct GrantorDescriptor { 31 uint32_t flags __attribute__ ((aligned(4))); 32 uint32_t fdIndex __attribute__ ((aligned(4))); 33 uint32_t offset __attribute__ ((aligned(4))); 34 uint64_t extent __attribute__ ((aligned(8))); 35}; 36 37static_assert(offsetof(GrantorDescriptor, flags) == 0, "wrong offset"); 38static_assert(offsetof(GrantorDescriptor, fdIndex) == 4, "wrong offset"); 39static_assert(offsetof(GrantorDescriptor, offset) == 8, "wrong offset"); 40static_assert(offsetof(GrantorDescriptor, extent) == 16, "wrong offset"); 41static_assert(sizeof(GrantorDescriptor) == 24, "wrong size"); 42static_assert(__alignof(GrantorDescriptor) == 8, "wrong alignment"); 43 44enum MQFlavor : uint32_t { 45 /* 46 * kSynchronizedReadWrite represents the wait-free synchronized flavor of the 47 * FMQ. It is intended to be have a single reader and single writer. 48 * Attempts to overflow/underflow returns a failure. 49 */ 50 kSynchronizedReadWrite = 0x01, 51 /* 52 * kUnsynchronizedWrite represents the flavor of FMQ where writes always 53 * succeed. This flavor allows one writer and many readers. A read operation 54 * can detect an overwrite and reset the read counter. 55 */ 56 kUnsynchronizedWrite = 0x02 57}; 58 59template <typename T, MQFlavor flavor> 60struct MQDescriptor { 61 MQDescriptor( 62 const std::vector<GrantorDescriptor>& grantors, 63 native_handle_t* nHandle, size_t size); 64 65 MQDescriptor(size_t bufferSize, native_handle_t* nHandle, 66 size_t messageSize, bool configureEventFlag = false); 67 68 MQDescriptor(); 69 ~MQDescriptor(); 70 71 explicit MQDescriptor(const MQDescriptor &other); 72 MQDescriptor &operator=(const MQDescriptor &other) = delete; 73 74 size_t getSize() const; 75 76 size_t getQuantum() const; 77 78 int32_t getFlags() const; 79 80 bool isHandleValid() const { return mHandle != nullptr; } 81 size_t countGrantors() const { return mGrantors.size(); } 82 83 inline const ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() const { 84 return mGrantors; 85 } 86 87 inline ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() { 88 return mGrantors; 89 } 90 91 inline const ::native_handle_t *handle() const { 92 return mHandle; 93 } 94 95 inline ::native_handle_t *handle() { 96 return mHandle; 97 } 98 99 static const size_t kOffsetOfGrantors; 100 static const size_t kOffsetOfHandle; 101 enum GrantorType : int { READPTRPOS = 0, WRITEPTRPOS, DATAPTRPOS, EVFLAGWORDPOS }; 102 103 /* 104 * There should at least be GrantorDescriptors for the read counter, write 105 * counter and data buffer. A GrantorDescriptor for an EventFlag word is 106 * not required if there is no need for blocking FMQ operations. 107 */ 108 static constexpr int32_t kMinGrantorCount = DATAPTRPOS + 1; 109 110 /* 111 * Minimum number of GrantorDescriptors required if EventFlag support is 112 * needed for blocking FMQ operations. 113 */ 114 static constexpr int32_t kMinGrantorCountForEvFlagSupport = EVFLAGWORDPOS + 1; 115 116 //TODO(b/34160777) Identify a better solution that supports remoting. 117 static inline size_t alignToWordBoundary(size_t length) { 118 constexpr size_t kAlignmentSize = 64; 119 if (kAlignmentSize % __WORDSIZE != 0) { 120 details::logAlwaysFatal("Incompatible word size"); 121 } 122 123 /* 124 * Check if alignment to word boundary would cause an overflow. 125 */ 126 if (length > SIZE_MAX - kAlignmentSize/8 + 1) { 127 details::logAlwaysFatal("Queue size too large"); 128 } 129 130 return (length + kAlignmentSize/8 - 1) & ~(kAlignmentSize/8 - 1U); 131 } 132 133 static inline size_t isAlignedToWordBoundary(size_t offset) { 134 constexpr size_t kAlignmentSize = 64; 135 return (offset & (kAlignmentSize/8 - 1)) == 0; 136 } 137private: 138 ::android::hardware::hidl_vec<GrantorDescriptor> mGrantors; 139 ::android::hardware::details::hidl_pointer<native_handle_t> mHandle; 140 uint32_t mQuantum; 141 uint32_t mFlags; 142}; 143 144template<typename T, MQFlavor flavor> 145const size_t MQDescriptor<T, flavor>::kOffsetOfGrantors = offsetof(MQDescriptor, mGrantors); 146 147template<typename T, MQFlavor flavor> 148const size_t MQDescriptor<T, flavor>::kOffsetOfHandle = offsetof(MQDescriptor, mHandle); 149 150/* 151 * MQDescriptorSync will describe the wait-free synchronized 152 * flavor of FMQ. 153 */ 154template<typename T> 155using MQDescriptorSync = MQDescriptor<T, kSynchronizedReadWrite>; 156 157/* 158 * MQDescriptorUnsync will describe the unsynchronized write 159 * flavor of FMQ. 160 */ 161template<typename T> 162using MQDescriptorUnsync = MQDescriptor<T, kUnsynchronizedWrite>; 163 164template<typename T, MQFlavor flavor> 165MQDescriptor<T, flavor>::MQDescriptor( 166 const std::vector<GrantorDescriptor>& grantors, 167 native_handle_t* nhandle, 168 size_t size) 169 : mHandle(nhandle), 170 mQuantum(size), 171 mFlags(flavor) { 172 mGrantors.resize(grantors.size()); 173 for (size_t i = 0; i < grantors.size(); ++i) { 174 if (isAlignedToWordBoundary(grantors[i].offset) == false) { 175 details::logAlwaysFatal("Grantor offsets need to be aligned"); 176 } 177 mGrantors[i] = grantors[i]; 178 } 179} 180 181template<typename T, MQFlavor flavor> 182MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t *nHandle, 183 size_t messageSize, bool configureEventFlag) 184 : mHandle(nHandle), mQuantum(messageSize), mFlags(flavor) { 185 /* 186 * If configureEventFlag is true, allocate an additional spot in mGrantor 187 * for containing the fd and offset for mmapping the EventFlag word. 188 */ 189 mGrantors.resize(configureEventFlag? kMinGrantorCountForEvFlagSupport : kMinGrantorCount); 190 191 size_t memSize[] = { 192 sizeof(RingBufferPosition), /* memory to be allocated for read pointer counter */ 193 sizeof(RingBufferPosition), /* memory to be allocated for write pointer counter */ 194 bufferSize, /* memory to be allocated for data buffer */ 195 sizeof(std::atomic<uint32_t>)/* memory to be allocated for EventFlag word */ 196 }; 197 198 /* 199 * Create a default grantor descriptor for read, write pointers and 200 * the data buffer. fdIndex parameter is set to 0 by default and 201 * the offset for each grantor is contiguous. 202 */ 203 for (size_t grantorPos = 0, offset = 0; 204 grantorPos < mGrantors.size(); 205 offset += memSize[grantorPos++]) { 206 mGrantors[grantorPos] = { 207 0 /* grantor flags */, 208 0 /* fdIndex */, 209 static_cast<uint32_t>(alignToWordBoundary(offset)), 210 memSize[grantorPos] 211 }; 212 } 213} 214 215template<typename T, MQFlavor flavor> 216MQDescriptor<T, flavor>::MQDescriptor(const MQDescriptor<T, flavor> &other) 217 : mGrantors(other.mGrantors), 218 mHandle(nullptr), 219 mQuantum(other.mQuantum), 220 mFlags(other.mFlags) { 221 if (other.mHandle != nullptr) { 222 mHandle = native_handle_create( 223 other.mHandle->numFds, other.mHandle->numInts); 224 225 for (int i = 0; i < other.mHandle->numFds; ++i) { 226 mHandle->data[i] = dup(other.mHandle->data[i]); 227 } 228 229 memcpy(&mHandle->data[other.mHandle->numFds], 230 &other.mHandle->data[other.mHandle->numFds], 231 other.mHandle->numInts * sizeof(int)); 232 } 233} 234 235template<typename T, MQFlavor flavor> 236MQDescriptor<T, flavor>::MQDescriptor() : MQDescriptor( 237 std::vector<android::hardware::GrantorDescriptor>(), 238 nullptr /* nHandle */, 239 0 /* size */) {} 240 241template<typename T, MQFlavor flavor> 242MQDescriptor<T, flavor>::~MQDescriptor() { 243 if (mHandle != nullptr) { 244 native_handle_close(mHandle); 245 native_handle_delete(mHandle); 246 } 247} 248 249template<typename T, MQFlavor flavor> 250size_t MQDescriptor<T, flavor>::getSize() const { 251 return mGrantors[DATAPTRPOS].extent; 252} 253 254template<typename T, MQFlavor flavor> 255size_t MQDescriptor<T, flavor>::getQuantum() const { return mQuantum; } 256 257template<typename T, MQFlavor flavor> 258int32_t MQDescriptor<T, flavor>::getFlags() const { return mFlags; } 259 260template<typename T, MQFlavor flavor> 261std::string toString(const MQDescriptor<T, flavor> &q) { 262 std::string os; 263 if (flavor & kSynchronizedReadWrite) { 264 os += "fmq_sync"; 265 } 266 if (flavor & kUnsynchronizedWrite) { 267 os += "fmq_unsync"; 268 } 269 os += " {" 270 + toString(q.grantors().size()) + " grantor(s), " 271 + "size = " + toString(q.getSize()) 272 + ", .handle = " + toString(q.handle()) 273 + ", .quantum = " + toString(q.getQuantum()) + "}"; 274 return os; 275} 276 277} // namespace hardware 278} // namespace android 279 280#endif // FMSGQ_DESCRIPTOR_H 281