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