2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "MemoryHeapPmem"
24 #include <sys/types.h>
26 #include <sys/ioctl.h>
28 #include <cutils/log.h>
30 #include <binder/MemoryHeapPmem.h>
31 #include <binder/MemoryHeapBase.h>
34 #include <linux/android_pmem.h>
39 // ---------------------------------------------------------------------------
41 MemoryHeapPmem::MemoryPmem::MemoryPmem(const sp<MemoryHeapPmem>& heap)
42 : BnMemory(), mClientHeap(heap)
46 MemoryHeapPmem::MemoryPmem::~MemoryPmem() {
47 if (mClientHeap != NULL) {
48 mClientHeap->remove(this);
52 // ---------------------------------------------------------------------------
54 class SubRegionMemory : public MemoryHeapPmem::MemoryPmem {
56 SubRegionMemory(const sp<MemoryHeapPmem>& heap, ssize_t offset, size_t size);
57 virtual ~SubRegionMemory();
58 virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
60 friend class MemoryHeapPmem;
66 SubRegionMemory::SubRegionMemory(const sp<MemoryHeapPmem>& heap,
67 ssize_t offset, size_t size)
68 : MemoryHeapPmem::MemoryPmem(heap), mSize(size), mOffset(offset)
71 void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + offset);
72 memset(start_ptr, 0xda, size);
77 const size_t pagesize = getpagesize();
78 size = (size + pagesize-1) & ~(pagesize-1);
79 int our_fd = heap->heapID();
80 struct pmem_region sub = { offset, size };
81 int err = ioctl(our_fd, PMEM_MAP, &sub);
82 LOGE_IF(err<0, "PMEM_MAP failed (%s), "
83 "mFD=%d, sub.offset=%lu, sub.size=%lu",
84 strerror(errno), our_fd, sub.offset, sub.len);
89 sp<IMemoryHeap> SubRegionMemory::getMemory(ssize_t* offset, size_t* size) const
91 if (offset) *offset = mOffset;
92 if (size) *size = mSize;
96 SubRegionMemory::~SubRegionMemory()
102 void SubRegionMemory::revoke()
104 // NOTE: revoke() doesn't need to be protected by a lock because it
105 // can only be called from MemoryHeapPmem::revoke(), which means
106 // that we can't be in ~SubRegionMemory(), or in ~SubRegionMemory(),
107 // which means MemoryHeapPmem::revoke() wouldn't have been able to
112 const sp<MemoryHeapPmem>& heap(getHeap());
113 int our_fd = heap->heapID();
114 struct pmem_region sub;
115 sub.offset = mOffset;
117 int err = ioctl(our_fd, PMEM_UNMAP, &sub);
118 LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
119 "mFD=%d, sub.offset=%lu, sub.size=%lu",
120 strerror(errno), our_fd, sub.offset, sub.len);
126 // ---------------------------------------------------------------------------
128 MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
132 char const * const device = pmemHeap->getDevice();
135 int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0));
136 LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno));
138 int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID());
140 LOGE("PMEM_CONNECT failed (%s), mFD=%d, sub-fd=%d",
141 strerror(errno), fd, pmemHeap->heapID());
144 // everything went well...
145 mParentHeap = pmemHeap;
146 MemoryHeapBase::init(fd,
149 pmemHeap->getFlags() | flags,
155 mParentHeap = pmemHeap;
156 MemoryHeapBase::init(
157 dup(pmemHeap->heapID()),
160 pmemHeap->getFlags() | flags,
165 MemoryHeapPmem::~MemoryHeapPmem()
169 sp<IMemory> MemoryHeapPmem::mapMemory(size_t offset, size_t size)
171 sp<MemoryPmem> memory = createMemory(offset, size);
173 Mutex::Autolock _l(mLock);
174 mAllocations.add(memory);
179 sp<MemoryHeapPmem::MemoryPmem> MemoryHeapPmem::createMemory(
180 size_t offset, size_t size)
182 sp<SubRegionMemory> memory;
184 memory = new SubRegionMemory(this, offset, size);
188 status_t MemoryHeapPmem::slap()
191 size_t size = getSize();
192 const size_t pagesize = getpagesize();
193 size = (size + pagesize-1) & ~(pagesize-1);
194 int our_fd = getHeapID();
195 struct pmem_region sub = { 0, size };
196 int err = ioctl(our_fd, PMEM_MAP, &sub);
197 LOGE_IF(err<0, "PMEM_MAP failed (%s), "
198 "mFD=%d, sub.offset=%lu, sub.size=%lu",
199 strerror(errno), our_fd, sub.offset, sub.len);
206 status_t MemoryHeapPmem::unslap()
209 size_t size = getSize();
210 const size_t pagesize = getpagesize();
211 size = (size + pagesize-1) & ~(pagesize-1);
212 int our_fd = getHeapID();
213 struct pmem_region sub = { 0, size };
214 int err = ioctl(our_fd, PMEM_UNMAP, &sub);
215 LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
216 "mFD=%d, sub.offset=%lu, sub.size=%lu",
217 strerror(errno), our_fd, sub.offset, sub.len);
224 void MemoryHeapPmem::revoke()
226 SortedVector< wp<MemoryPmem> > allocations;
229 Mutex::Autolock _l(mLock);
230 allocations = mAllocations;
233 ssize_t count = allocations.size();
234 for (ssize_t i=0 ; i<count ; i++) {
235 sp<MemoryPmem> memory(allocations[i].promote());
241 void MemoryHeapPmem::remove(const wp<MemoryPmem>& memory)
243 Mutex::Autolock _l(mLock);
244 mAllocations.remove(memory);
247 // ---------------------------------------------------------------------------
248 }; // namespace android