• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef HDI_SHARED_MEM_QUEUE_META_H
16 #define HDI_SHARED_MEM_QUEUE_META_H
17 
18 #include <atomic>
19 #include <cstddef>
20 #include <memory>
21 #include <message_parcel.h>
22 #include <unistd.h>
23 
24 #ifndef HDF_LOG_TAG
25 #define HDF_LOG_TAG smq
26 #endif
27 
28 namespace OHOS {
29 namespace HDI {
30 namespace Base {
31 enum SmqType : uint32_t {
32     SYNCED_SMQ = 0x01,
33     UNSYNC_SMQ = 0x02,
34 };
35 
36 struct MemZone {
37     uint32_t size;
38     uint32_t offset;
39 };
40 
41 template <typename T>
42 class SharedMemQueueMeta {
43 public:
SharedMemQueueMeta()44     SharedMemQueueMeta() : SharedMemQueueMeta(-1, 0, 0) {};
SharedMemQueueMeta(size_t elementCount,SmqType type)45     SharedMemQueueMeta(size_t elementCount, SmqType type) : SharedMemQueueMeta(-1, elementCount, type) {};
46     SharedMemQueueMeta(int fd, size_t elementCount, SmqType type);
47     SharedMemQueueMeta(const SharedMemQueueMeta<T> &other);
48     ~SharedMemQueueMeta() = default;
49 
50     void SetFd(int fd);
51     int GetFd();
52     size_t GetSize();
53     uint32_t GetType();
54     size_t GetElementCount();
55     size_t GetElemenetSize() const;
56     enum MemZoneType : uint32_t {
57         MEMZONE_RPTR = 0,
58         MEMZONE_WPTR,
59         MEMZONE_SYNCER,
60         MEMZONE_DATA,
61         MEMZONE_COUNT,
62     };
63 
64     MemZone *GetMemZone(uint32_t type);
65     bool Marshalling(MessageParcel &parcel);
66     static std::shared_ptr<SharedMemQueueMeta<T>> UnMarshalling(MessageParcel &parcel);
67 
AlignToWord(size_t num)68     size_t AlignToWord(size_t num)
69     {
70         constexpr uint32_t alignByteSize = 8;
71         return (num + alignByteSize - 1) & (~(alignByteSize - 1));
72     }
73 
74 private:
75     int ashmemFd_;
76     size_t size_;
77     size_t elementCount_;
78     size_t elementSize_;
79     SmqType type_;
80     MemZone memzone_[MEMZONE_COUNT];
81 };
82 
83 template <typename T>
SharedMemQueueMeta(int fd,size_t elementCount,SmqType type)84 SharedMemQueueMeta<T>::SharedMemQueueMeta(int fd, size_t elementCount, SmqType type)
85     : ashmemFd_(fd), size_(0), elementCount_(elementCount), elementSize_(AlignToWord(sizeof(T))), type_(type)
86 {
87     // max size UIN32_MAX byte
88     if (elementCount_ > UINT32_MAX / elementSize_) {
89         return;
90     }
91 
92     size_t dataSize = elementCount_ * elementSize_;
93     size_t memZoneSize[] = {
94         sizeof(uint64_t), // read ptr
95         sizeof(uint64_t), // write ptr
96         sizeof(uint32_t), // sync word
97         dataSize,
98     };
99 
100     size_t offset = 0;
101     for (size_t i = 0; i < MEMZONE_COUNT; offset += memZoneSize[i++]) {
102         memzone_[i].offset = AlignToWord(offset);
103         memzone_[i].size = memZoneSize[i];
104     }
105 
106     size_ = memzone_[MEMZONE_DATA].offset + memzone_[MEMZONE_DATA].size;
107 }
108 
109 template <typename T>
SharedMemQueueMeta(const SharedMemQueueMeta<T> & other)110 SharedMemQueueMeta<T>::SharedMemQueueMeta(const SharedMemQueueMeta<T> &other)
111 {
112     if (ashmemFd_ >= 0) {
113         close(ashmemFd_);
114     }
115 
116     ashmemFd_ = dup(other.ashmemFd_);
117     if (ashmemFd_ < 0) {
118         HDF_LOGW("failed to dup ashmem fd for smq");
119     }
120     elementCount_ = other.elementCount_;
121     elementSize_ = other.elementSize_;
122     size_ = other.size_;
123     type_ = other.type_;
124     memcpy(memzone_, other.memzone_, sizeof(memzone_));
125 }
126 
127 template <typename T>
SetFd(int fd)128 void SharedMemQueueMeta<T>::SetFd(int fd)
129 {
130     if (ashmemFd_ >= 0) {
131         close(ashmemFd_);
132     }
133     ashmemFd_ = fd;
134 }
135 
136 template <typename T>
GetFd()137 int SharedMemQueueMeta<T>::GetFd()
138 {
139     return ashmemFd_;
140 }
141 
142 template <typename T>
GetSize()143 size_t SharedMemQueueMeta<T>::GetSize()
144 {
145     return size_;
146 }
147 
148 template <typename T>
GetType()149 uint32_t SharedMemQueueMeta<T>::GetType()
150 {
151     return type_;
152 }
153 
154 template <typename T>
GetElementCount()155 size_t SharedMemQueueMeta<T>::GetElementCount()
156 {
157     return elementCount_;
158 }
159 
160 template <typename T>
GetElemenetSize()161 size_t SharedMemQueueMeta<T>::GetElemenetSize() const
162 {
163     return elementSize_;
164 }
165 
166 template <typename T>
GetMemZone(uint32_t type)167 MemZone *SharedMemQueueMeta<T>::GetMemZone(uint32_t type)
168 {
169     if (type >= MEMZONE_COUNT) {
170         return nullptr;
171     }
172 
173     return &memzone_[type];
174 }
175 
176 template <typename T>
Marshalling(MessageParcel & parcel)177 bool SharedMemQueueMeta<T>::Marshalling(MessageParcel &parcel)
178 {
179     if (!parcel.WriteBuffer(this, sizeof(SharedMemQueueMeta<T>))) {
180         return false;
181     }
182 
183     return parcel.WriteFileDescriptor(ashmemFd_);
184 }
185 
186 template <typename T>
UnMarshalling(MessageParcel & parcel)187 std::shared_ptr<SharedMemQueueMeta<T>> SharedMemQueueMeta<T>::UnMarshalling(MessageParcel &parcel)
188 {
189     auto readMeta = reinterpret_cast<const SharedMemQueueMeta<T> *>(parcel.ReadBuffer(sizeof(SharedMemQueueMeta<T>)));
190     if (readMeta == nullptr) {
191         HDF_LOGE("read invalid smq meta");
192         return nullptr;
193     }
194 
195     auto fd = parcel.ReadFileDescriptor();
196     if (fd < 0) {
197         HDF_LOGE("read invalid smq fd");
198         return nullptr;
199     }
200 
201     auto meta = std::make_shared<SharedMemQueueMeta<T>>(*readMeta);
202     meta->SetFd(fd);
203 
204     return meta;
205 }
206 } // namespace Base
207 } // namespace HDI
208 } // namespace OHOS
209 
210 #ifdef HDF_LOG_TAG
211 #undef HDF_LOG_TAG
212 #endif
213 
214 #endif /* HDI_SHARED_MEM_QUEUE_META_H */
215