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 <unistd.h> 21 22 #include <cutils/native_handle.h> 23 #include <fmq/MQDescriptorBase.h> 24 #include <hidl/HidlInternal.h> 25 #include <hidl/HidlSupport.h> 26 27 namespace android { 28 namespace hardware { 29 30 template <typename T, MQFlavor flavor> 31 struct MQDescriptor { 32 // Takes ownership of handle 33 MQDescriptor( 34 const std::vector<GrantorDescriptor>& grantors, 35 native_handle_t* nHandle, size_t size); 36 37 // Takes ownership of handle 38 MQDescriptor(size_t bufferSize, native_handle_t* nHandle, 39 size_t messageSize, bool configureEventFlag = false); 40 41 MQDescriptor(); 42 ~MQDescriptor(); 43 44 explicit MQDescriptor(const MQDescriptor& other) : MQDescriptor() { *this = other; } 45 MQDescriptor& operator=(const MQDescriptor& other); 46 47 size_t getSize() const; 48 49 size_t getQuantum() const; 50 51 int32_t getFlags() const; 52 53 bool isHandleValid() const { return mHandle != nullptr; } 54 size_t countGrantors() const { return mGrantors.size(); } 55 56 inline const ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() const { 57 return mGrantors; 58 } 59 60 inline const ::native_handle_t *handle() const { 61 return mHandle; 62 } 63 64 inline ::native_handle_t *handle() { 65 return mHandle; 66 } 67 68 static const size_t kOffsetOfGrantors; 69 static const size_t kOffsetOfHandle; 70 71 private: 72 ::android::hardware::hidl_vec<GrantorDescriptor> mGrantors; 73 ::android::hardware::details::hidl_pointer<native_handle_t> mHandle; 74 uint32_t mQuantum; 75 uint32_t mFlags; 76 }; 77 78 template<typename T, MQFlavor flavor> 79 const size_t MQDescriptor<T, flavor>::kOffsetOfGrantors = offsetof(MQDescriptor, mGrantors); 80 81 template<typename T, MQFlavor flavor> 82 const size_t MQDescriptor<T, flavor>::kOffsetOfHandle = offsetof(MQDescriptor, mHandle); 83 84 /* 85 * MQDescriptorSync will describe the wait-free synchronized 86 * flavor of FMQ. 87 */ 88 template<typename T> 89 using MQDescriptorSync = MQDescriptor<T, kSynchronizedReadWrite>; 90 91 /* 92 * MQDescriptorUnsync will describe the unsynchronized write 93 * flavor of FMQ. 94 */ 95 template<typename T> 96 using MQDescriptorUnsync = MQDescriptor<T, kUnsynchronizedWrite>; 97 98 template <typename T, MQFlavor flavor> 99 MQDescriptor<T, flavor>::MQDescriptor(const std::vector<GrantorDescriptor>& grantors, 100 native_handle_t* nhandle, size_t size) 101 : mHandle(nhandle), mQuantum(static_cast<uint32_t>(size)), mFlags(flavor) { 102 mGrantors.resize(grantors.size()); 103 for (size_t i = 0; i < grantors.size(); ++i) { 104 mGrantors[i] = grantors[i]; 105 } 106 } 107 108 template <typename T, MQFlavor flavor> 109 MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t* nHandle, 110 size_t messageSize, bool configureEventFlag) 111 : mHandle(nHandle), mQuantum(static_cast<uint32_t>(messageSize)), mFlags(flavor) { 112 /* 113 * If configureEventFlag is true, allocate an additional spot in mGrantor 114 * for containing the fd and offset for mmapping the EventFlag word. 115 */ 116 mGrantors.resize(configureEventFlag ? details::kMinGrantorCountForEvFlagSupport 117 : details::kMinGrantorCount); 118 119 size_t memSize[] = { 120 sizeof(details::RingBufferPosition), /* memory to be allocated for read pointer counter 121 */ 122 sizeof(details::RingBufferPosition), /* memory to be allocated for write pointer counter 123 */ 124 bufferSize, /* memory to be allocated for data buffer */ 125 sizeof(std::atomic<uint32_t>) /* memory to be allocated for EventFlag word */ 126 }; 127 128 /* 129 * Create a default grantor descriptor for read, write pointers and 130 * the data buffer. fdIndex parameter is set to 0 by default and 131 * the offset for each grantor is contiguous. 132 */ 133 for (size_t grantorPos = 0, offset = 0; 134 grantorPos < mGrantors.size(); 135 offset += memSize[grantorPos++]) { 136 mGrantors[grantorPos] = {0 /* grantor flags */, 0 /* fdIndex */, 137 static_cast<uint32_t>(details::alignToWordBoundary(offset)), 138 memSize[grantorPos]}; 139 } 140 } 141 142 template <typename T, MQFlavor flavor> 143 MQDescriptor<T, flavor>& MQDescriptor<T, flavor>::operator=(const MQDescriptor& other) { 144 mGrantors = other.mGrantors; 145 if (mHandle != nullptr) { 146 native_handle_close(mHandle); 147 native_handle_delete(mHandle); 148 mHandle = nullptr; 149 } 150 mQuantum = other.mQuantum; 151 mFlags = other.mFlags; 152 153 if (other.mHandle != nullptr) { 154 mHandle = native_handle_create( 155 other.mHandle->numFds, other.mHandle->numInts); 156 157 for (int i = 0; i < other.mHandle->numFds; ++i) { 158 mHandle->data[i] = dup(other.mHandle->data[i]); 159 } 160 161 memcpy(&mHandle->data[other.mHandle->numFds], &other.mHandle->data[other.mHandle->numFds], 162 static_cast<size_t>(other.mHandle->numInts) * sizeof(int)); 163 } 164 165 return *this; 166 } 167 168 template<typename T, MQFlavor flavor> 169 MQDescriptor<T, flavor>::MQDescriptor() : MQDescriptor( 170 std::vector<android::hardware::GrantorDescriptor>(), 171 nullptr /* nHandle */, 172 0 /* size */) {} 173 174 template<typename T, MQFlavor flavor> 175 MQDescriptor<T, flavor>::~MQDescriptor() { 176 if (mHandle != nullptr) { 177 native_handle_close(mHandle); 178 native_handle_delete(mHandle); 179 } 180 } 181 182 template<typename T, MQFlavor flavor> 183 size_t MQDescriptor<T, flavor>::getSize() const { 184 return static_cast<size_t>(mGrantors[details::DATAPTRPOS].extent); 185 } 186 187 template<typename T, MQFlavor flavor> 188 size_t MQDescriptor<T, flavor>::getQuantum() const { return mQuantum; } 189 190 template<typename T, MQFlavor flavor> 191 int32_t MQDescriptor<T, flavor>::getFlags() const { return mFlags; } 192 193 template<typename T, MQFlavor flavor> 194 std::string toString(const MQDescriptor<T, flavor> &q) { 195 std::string os; 196 if (flavor & kSynchronizedReadWrite) { 197 os += "fmq_sync"; 198 } 199 if (flavor & kUnsynchronizedWrite) { 200 os += "fmq_unsync"; 201 } 202 os += " {" 203 + toString(q.grantors().size()) + " grantor(s), " 204 + "size = " + toString(q.getSize()) 205 + ", .handle = " + toString(q.handle()) 206 + ", .quantum = " + toString(q.getQuantum()) + "}"; 207 return os; 208 } 209 210 } // namespace hardware 211 } // namespace android 212 213 #endif // FMSGQ_DESCRIPTOR_H 214