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