• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 /**
17  * @addtogroup DriverHdi
18  * @{
19  *
20  * @brief Provides APIs for a system ability to obtain hardware device interface (HDI) services,
21  * load or unload a device, and listen for service status, and capabilities for the hdi-gen tool to
22  * automatically generate code in interface description language (IDL).
23  *
24  * The HDF and IDL code generated allow the system ability to accesses HDI driver services.
25  *
26  * @since 1.0
27  */
28 
29 /**
30  * @file hdi_smq_meta.h
31  *
32  * @brief Defines the metadata struct of the shared memory queue (SMQ) and provides APIs for obtaining
33  * the data struct members and serializing and deserializing the metadata struct.
34  *
35  * @since 1.0
36  */
37 
38 #ifndef HDI_SHARED_MEM_QUEUE_META_H
39 #define HDI_SHARED_MEM_QUEUE_META_H
40 
41 #include <atomic>
42 #include <cstddef>
43 #include <memory>
44 #include <message_parcel.h>
45 #include <unistd.h>
46 #include "securec.h"
47 
48 #ifndef HDF_LOG_TAG
49 #define HDF_LOG_TAG smq
50 #endif
51 
52 namespace OHOS {
53 namespace HDI {
54 namespace Base {
55 /**
56  * @brief Enumerates the SMQ types.
57  */
58 enum SmqType : uint32_t {
59     /** SMQ for synchronous communication */
60     SYNCED_SMQ = 0x01,
61     /** SMQ for asynchronous communication */
62     UNSYNC_SMQ = 0x02,
63 };
64 
65 /**
66  * @brief Defines the <b>MemZone</b> struct.
67  */
68 struct MemZone {
69     /** Memory zone size */
70     uint32_t size;
71     /** Memory zone offset */
72     uint32_t offset;
73 };
74 
75 /**
76  * @brief Defines the metadata template type of the SMQ.
77  */
78 template <typename T>
79 class SharedMemQueueMeta {
80 public:
81     /**
82      * @brief Default constructor used to create a <b>SharedMemQueueMeta</b> object.
83      */
SharedMemQueueMeta()84     SharedMemQueueMeta() : SharedMemQueueMeta(-1, 0, 0) {}
85 
86     /**
87      * @brief A constructor used to create a <b>SharedMemQueueMeta</b> object.
88      *
89      * @param elementCount Indicates the queue size.
90      * @param type Indicates the SMQ type.
91      */
SharedMemQueueMeta(size_t elementCount,SmqType type)92     SharedMemQueueMeta(size_t elementCount, SmqType type) : SharedMemQueueMeta(-1, elementCount, type) {}
93 
94     /**
95      * @brief A constructor used to create a <b>SharedMemQueueMeta</b> object.
96      *
97      * @param fd Indicates the file descriptor (FD) of the shared memory file.
98      * @param elementCount Indicates the queue size.
99      * @param type Indicates the SMQ type.
100      */
101     SharedMemQueueMeta(int fd, size_t elementCount, SmqType type);
102 
103     /**
104      * @brief A constructor used to copy a <b>SharedMemQueueMeta</b> object.
105      *
106      * @param other Indicates the <b>SharedMemQueueMeta</b> object to copy.
107      */
108     SharedMemQueueMeta(const SharedMemQueueMeta<T> &other);
109     ~SharedMemQueueMeta();
110 
111     /**
112      * @brief A constructor used to assign values to the <b>SharedMemQueueMeta</b> object.
113      *
114      * @param other Indicates the <b>SharedMemQueueMeta</b> object to copy.
115      */
116     SharedMemQueueMeta &operator=(const SharedMemQueueMeta<T> &other);
117 
118     /**
119      * @brief Sets an FD.
120      *
121      * @param fd Indicates the FD to set.
122      */
123     void SetFd(int fd);
124 
125     /**
126      * @brief Obtains the FD.
127      *
128      * @return Returns the FD obtained.
129      */
130     int GetFd() const;
131 
132     /**
133      * @brief Obtains the shared memory size.
134      *
135      * @return Returns the shared memory size obtained.
136      */
137     size_t GetSize();
138 
139     /**
140      * @brief Obtains the SMQ type.
141      *
142      * @return Returns the SMQ type obtained.
143      */
144     uint32_t GetType();
145 
146     /**
147      * @brief Obtains the number of elements in the SMQ.
148      *
149      * @return Returns the number of elements in the SMQ obtained.
150      */
151     size_t GetElementCount();
152 
153     /**
154      * @brief Obtains the size of a single element in the SMQ.
155      *
156      * @return Returns the size of a single element obtained.
157      */
158     size_t GetElemenetSize() const;
159 
160     /**
161      * @brief Enumerates the shared memory zone types.
162      */
163     enum MemZoneType : uint32_t {
164         /** Read pointer */
165         MEMZONE_RPTR,
166         /** Write pointer */
167         MEMZONE_WPTR,
168         /** Syncword */
169         MEMZONE_SYNCER,
170         /** Data */
171         MEMZONE_DATA,
172         /** Number of shared memory zones */
173         MEMZONE_COUNT,
174     };
175 
176     /**
177      * @brief Obtains the memory zone of the specified type.
178      *
179      * @param type Indicates the type of the shared memory zone.
180      * @return Returns the shared memory zone obtained.
181      */
182     MemZone *GetMemZone(uint32_t type);
183 
184     /**
185      * @brief Writes the SMQ to a <b>MessageParcel</b> object.
186      *
187      * @param parcel Indicates the <b>MessageParcel</b> object.
188      * @return Returns <b>true</b> if the operation is successful; returns <b>false</b> otherwise.
189      */
190     bool Marshalling(MessageParcel &parcel);
191 
192     /**
193      * @brief Reads the SMQ from a <b>MessageParcel</b> object.
194      *
195      * @param parcel Indicates the <b>MessageParcel</b> object from which the SMQ is to read.
196      * @return Returns a <b>SharedMemQueueMeta</b> object, which can be used to create an SQM object.
197      */
198     static std::shared_ptr<SharedMemQueueMeta<T>> UnMarshalling(MessageParcel &parcel);
199 
200     /**
201      * @brief Aligns the buffer by 8 bytes.
202      *
203      * @param num Indicates the number of bytes for aligning the buffer.
204      * @return Returns the number of bytes after alignment.
205      */
AlignToWord(size_t num)206     size_t AlignToWord(size_t num)
207     {
208         constexpr uint32_t alignByteSize = 8;
209         return (num + alignByteSize - 1) & (~(alignByteSize - 1));
210     }
211 
212 private:
213     /** FD of the shared memory file */
214     int ashmemFd_;
215 
216     /** Size of the shared memory */
217     size_t size_;
218 
219     /** Number of elements in the SMQ */
220     size_t elementCount_;
221 
222     /** Size of an element in the SMQ */
223     size_t elementSize_;
224 
225     /** SMQ type */
226     SmqType type_;
227 
228     /** Number of shared memory zones */
229     MemZone memzone_[MEMZONE_COUNT];
230 };
231 
232 /**
233  * @brief A constructor used to assign values to the <b>SharedMemQueueMeta</b> object.
234  *
235  * @param other Indicates the <b>SharedMemQueueMeta</b> object to copy.
236  */
237 template <typename T>
238 SharedMemQueueMeta<T> &SharedMemQueueMeta<T>::operator=(const SharedMemQueueMeta<T> &other)
239 {
240     if (this != &other) {
241         if (ashmemFd_ >= 0) {
242             close(ashmemFd_);
243         }
244         ashmemFd_ = dup(other.ashmemFd_);
245         size_ = other.size_;
246         elementCount_ = other.elementCount_;
247         elementSize_ = other.elementSize_;
248         type_ = other.type_;
249         if (memcpy_s(memzone_, sizeof(memzone_), other.memzone_, sizeof(other.memzone_)) != EOK) {
250             HDF_LOGW("failed to memcpy_s overload memzone_");
251         }
252     }
253 
254     return *this;
255 }
256 
257 template <typename T>
SharedMemQueueMeta(int fd,size_t elementCount,SmqType type)258 SharedMemQueueMeta<T>::SharedMemQueueMeta(int fd, size_t elementCount, SmqType type)
259     : ashmemFd_(fd), size_(0), elementCount_(elementCount), elementSize_(sizeof(T)), type_(type)
260 {
261     // max size UIN32_MAX byte
262     if (elementCount_ > UINT32_MAX / elementSize_) {
263         return;
264     }
265 
266     size_t dataSize = elementCount_ * elementSize_;
267     size_t memZoneSize[] = {
268         sizeof(uint64_t), // read ptr
269         sizeof(uint64_t), // write ptr
270         sizeof(uint32_t), // sync word
271         dataSize,
272     };
273 
274     size_t offset = 0;
275     for (size_t i = 0; i < MEMZONE_COUNT; offset += memZoneSize[i++]) {
276         memzone_[i].offset = AlignToWord(offset);
277         memzone_[i].size = memZoneSize[i];
278     }
279 
280     size_ = memzone_[MEMZONE_DATA].offset + memzone_[MEMZONE_DATA].size;
281 }
282 
283 template <typename T>
SharedMemQueueMeta(const SharedMemQueueMeta<T> & other)284 SharedMemQueueMeta<T>::SharedMemQueueMeta(const SharedMemQueueMeta<T> &other)
285 {
286     ashmemFd_ = dup(other.ashmemFd_);
287     if (ashmemFd_ < 0) {
288         HDF_LOGW("failed to dup ashmem fd for smq");
289     }
290     elementCount_ = other.elementCount_;
291     elementSize_ = other.elementSize_;
292     size_ = other.size_;
293     type_ = other.type_;
294     if (memcpy_s(memzone_, sizeof(memzone_), other.memzone_, sizeof(other.memzone_)) != EOK) {
295         HDF_LOGW("failed to memcpy_s memzone_");
296     }
297 }
298 
299 template <typename T>
~SharedMemQueueMeta()300 SharedMemQueueMeta<T>::~SharedMemQueueMeta()
301 {
302     if (ashmemFd_ >= 0) {
303         close(ashmemFd_);
304     }
305     ashmemFd_ = -1;
306 }
307 
308 /**
309  * @brief Sets an FD.
310  *
311  * @param fd Indicates the FD to set.
312  */
313 template <typename T>
SetFd(int fd)314 void SharedMemQueueMeta<T>::SetFd(int fd)
315 {
316     if (ashmemFd_ >= 0) {
317         close(ashmemFd_);
318     }
319     ashmemFd_ = fd;
320 }
321 
322 /**
323  * @brief Obtains the FD.
324  *
325  * @return Returns the FD obtained.
326  */
327 template <typename T>
GetFd()328 int SharedMemQueueMeta<T>::GetFd() const
329 {
330     return ashmemFd_;
331 }
332 
333 /**
334  * @brief Obtains the shared memory size.
335  *
336  * @return Returns the shared memory size obtained.
337  */
338 template <typename T>
GetSize()339 size_t SharedMemQueueMeta<T>::GetSize()
340 {
341     return size_;
342 }
343 
344 /**
345  * @brief Obtains the SMQ type.
346  *
347  * @return Returns the SMQ type obtained.
348  */
349 template <typename T>
GetType()350 uint32_t SharedMemQueueMeta<T>::GetType()
351 {
352     return type_;
353 }
354 
355 /**
356  * @brief Obtains the number of elements in the SMQ.
357  *
358  * @return Returns the number of elements in the SMQ obtained.
359  */
360 template <typename T>
GetElementCount()361 size_t SharedMemQueueMeta<T>::GetElementCount()
362 {
363     return elementCount_;
364 }
365 
366 /**
367  * @brief Obtains the size of a single element in the SMQ.
368  *
369  * @return Returns the size of a single element obtained.
370  */
371 template <typename T>
GetElemenetSize()372 size_t SharedMemQueueMeta<T>::GetElemenetSize() const
373 {
374     return elementSize_;
375 }
376 
377 /**
378  * @brief Obtains the memory zone of the specified type.
379  *
380  * @param type Indicates the type of the shared memory zone.
381  * @return Returns the shared memory zone obtained.
382  */
383 template <typename T>
GetMemZone(uint32_t type)384 MemZone *SharedMemQueueMeta<T>::GetMemZone(uint32_t type)
385 {
386     if (type >= MEMZONE_COUNT) {
387         return nullptr;
388     }
389 
390     return &memzone_[type];
391 }
392 
393 /**
394  * @brief Marshals the SMQ into a <b>MessageParcel</b> object.
395  *
396  * @param parcel Indicates the <b>MessageParcel</b> object after marshalling.
397  * @return Returns <b>true</b> if the operation is successful; returns <b>false</b> otherwise.
398  */
399 template <typename T>
Marshalling(MessageParcel & parcel)400 bool SharedMemQueueMeta<T>::Marshalling(MessageParcel &parcel)
401 {
402     if (!parcel.WriteFileDescriptor(ashmemFd_)) {
403         HDF_LOGE("%{public}s: failed to write ashmemFd_", __func__);
404         return false;
405     }
406 
407     if (!parcel.WriteUint64(static_cast<uint64_t>(elementCount_))) {
408         HDF_LOGE("%{public}s: failed to write elementCount_", __func__);
409         return false;
410     }
411 
412     if (!parcel.WriteUint32(static_cast<uint32_t>(type_))) {
413         HDF_LOGE("%{public}s: failed to write type_", __func__);
414         return false;
415     }
416 
417     return true;
418 }
419 
420 /**
421  * @brief Unmarshals the SMQ from a <b>MessageParcel</b> object.
422  *
423  * @param parcel Indicates the <b>MessageParcel</b> object to unmarshal.
424  * @return Returns a <b>SharedMemQueueMeta</b> object, which can be used to create an SQM object.
425  */
426 template <typename T>
UnMarshalling(MessageParcel & parcel)427 std::shared_ptr<SharedMemQueueMeta<T>> SharedMemQueueMeta<T>::UnMarshalling(MessageParcel &parcel)
428 {
429     int fd = parcel.ReadFileDescriptor();
430     if (fd < 0) {
431         HDF_LOGE("read invalid fd of smq");
432         return nullptr;
433     }
434 
435     uint64_t readElementCount = 0;
436     if (!parcel.ReadUint64(readElementCount)) {
437         HDF_LOGE("read invalid elementCount of smq");
438         close(fd);
439         return nullptr;
440     }
441     size_t elementCount = static_cast<size_t>(readElementCount);
442 
443     uint32_t typecode = 0;
444     if (!parcel.ReadUint32(typecode)) {
445         HDF_LOGE("read invalid typecode of smq");
446         close(fd);
447         return nullptr;
448     }
449     SmqType type = static_cast<SmqType>(typecode);
450     return std::make_shared<SharedMemQueueMeta<T>>(fd, elementCount, type);
451 }
452 } // namespace Base
453 } // namespace HDI
454 } // namespace OHOS
455 
456 #ifdef HDF_LOG_TAG
457 #undef HDF_LOG_TAG
458 #endif
459 
460 #endif /* HDI_SHARED_MEM_QUEUE_META_H */
461