Loading media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp +19 −0 Original line number Original line Diff line number Diff line Loading @@ -745,4 +745,23 @@ TEST_F(C2BufferTest, BufferTest) { EXPECT_FALSE(buffer->hasInfo(info2->type())); EXPECT_FALSE(buffer->hasInfo(info2->type())); } } TEST_F(C2BufferTest, MultipleLinearMapTest) { std::shared_ptr<C2BlockPool> pool(makeLinearBlockPool()); constexpr size_t kCapacity = 524288u; for (int i = 0; i < 100; ++i) { std::vector<C2WriteView> wViews; std::vector<C2ReadView> rViews; for (int j = 0; j < 16; ++j) { std::shared_ptr<C2LinearBlock> block; ASSERT_EQ(C2_OK, pool->fetchLinearBlock( kCapacity, { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, &block)); wViews.push_back(block->map().get()); C2ConstLinearBlock cBlock = block->share(0, kCapacity / 2, C2Fence()); rViews.push_back(cBlock.map().get()); } } } } // namespace android } // namespace android media/libstagefright/codec2/vndk/C2AllocatorIon.cpp +44 −30 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define LOG_TAG "C2AllocatorIon" #define LOG_TAG "C2AllocatorIon" #include <utils/Log.h> #include <utils/Log.h> #include <list> #include <ion/ion.h> #include <ion/ion.h> #include <sys/mman.h> #include <sys/mman.h> #include <unistd.h> #include <unistd.h> Loading Loading @@ -161,8 +163,7 @@ private: mBuffer(buffer), mBuffer(buffer), mId(id), mId(id), mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)), mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)), mMapFd(-1), mMapFd(-1) { mMapSize(0) { if (mInit != C2_OK) { if (mInit != C2_OK) { // close ionFd now on error // close ionFd now on error if (mIonFd >= 0) { if (mIonFd >= 0) { Loading Loading @@ -221,7 +222,8 @@ public: c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) { c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) { (void)fence; // TODO: wait for fence (void)fence; // TODO: wait for fence *addr = nullptr; *addr = nullptr; if (mMapSize > 0) { if (!mMappings.empty()) { ALOGV("multiple map"); // TODO: technically we should return DUPLICATE here, but our block views don't // TODO: technically we should return DUPLICATE here, but our block views don't // actually unmap, so we end up remapping an ion buffer multiple times. // actually unmap, so we end up remapping an ion buffer multiple times. // // Loading @@ -244,54 +246,63 @@ public: size_t alignmentBytes = offset % PAGE_SIZE; size_t alignmentBytes = offset % PAGE_SIZE; size_t mapOffset = offset - alignmentBytes; size_t mapOffset = offset - alignmentBytes; size_t mapSize = size + alignmentBytes; size_t mapSize = size + alignmentBytes; Mapping map = { nullptr, alignmentBytes, mapSize }; c2_status_t err = C2_OK; c2_status_t err = C2_OK; if (mMapFd == -1) { if (mMapFd == -1) { int ret = ion_map(mIonFd, mBuffer, mapSize, prot, int ret = ion_map(mIonFd, mBuffer, mapSize, prot, flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd); flags, mapOffset, (unsigned char**)&map.addr, &mMapFd); if (ret) { if (ret) { mMapFd = -1; mMapFd = -1; *addr = nullptr; map.addr = *addr = nullptr; err = c2_map_errno<EINVAL>(-ret); err = c2_map_errno<EINVAL>(-ret); } else { } else { *addr = (uint8_t *)mMapAddr + alignmentBytes; *addr = (uint8_t *)map.addr + alignmentBytes; mMapAlignmentBytes = alignmentBytes; mMapSize = mapSize; } } } else { } else { mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset); map.addr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset); if (mMapAddr == MAP_FAILED) { if (map.addr == MAP_FAILED) { mMapAddr = *addr = nullptr; map.addr = *addr = nullptr; err = c2_map_errno<EINVAL>(errno); err = c2_map_errno<EINVAL>(errno); } else { } else { *addr = (uint8_t *)mMapAddr + alignmentBytes; *addr = (uint8_t *)map.addr + alignmentBytes; mMapAlignmentBytes = alignmentBytes; } mMapSize = mapSize; } } if (map.addr) { mMappings.push_back(map); } } return err; return err; } } c2_status_t unmap(void *addr, size_t size, C2Fence *fence) { c2_status_t unmap(void *addr, size_t size, C2Fence *fence) { if (mMapFd < 0 || mMapSize == 0) { if (mMapFd < 0 || mMappings.empty()) { return C2_NOT_FOUND; return C2_NOT_FOUND; } } if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes || for (auto it = mMappings.begin(); it != mMappings.end(); ++it) { size + mMapAlignmentBytes != mMapSize) { if (addr != (uint8_t *)it->addr + it->alignmentBytes || return C2_BAD_VALUE; size + it->alignmentBytes != it->size) { continue; } } int err = munmap(mMapAddr, mMapSize); int err = munmap(it->addr, it->size); if (err != 0) { if (err != 0) { return c2_map_errno<EINVAL>(errno); return c2_map_errno<EINVAL>(errno); } } if (fence) { if (fence) { *fence = C2Fence(); // not using fences *fence = C2Fence(); // not using fences } } mMapSize = 0; (void)mMappings.erase(it); return C2_OK; return C2_OK; } } return C2_BAD_VALUE; } ~Impl() { ~Impl() { if (!mMappings.empty()) { ALOGD("Dangling mappings!"); for (const Mapping &map : mMappings) { (void)munmap(map.addr, map.size); } } if (mMapFd >= 0) { if (mMapFd >= 0) { close(mMapFd); close(mMapFd); mMapFd = -1; mMapFd = -1; Loading Loading @@ -328,9 +339,12 @@ private: C2Allocator::id_t mId; C2Allocator::id_t mId; c2_status_t mInit; c2_status_t mInit; int mMapFd; // only one for now int mMapFd; // only one for now void *mMapAddr; struct Mapping { size_t mMapAlignmentBytes; void *addr; size_t mMapSize; size_t alignmentBytes; size_t size; }; std::list<Mapping> mMappings; }; }; c2_status_t C2AllocationIon::map( c2_status_t C2AllocationIon::map( Loading Loading
media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp +19 −0 Original line number Original line Diff line number Diff line Loading @@ -745,4 +745,23 @@ TEST_F(C2BufferTest, BufferTest) { EXPECT_FALSE(buffer->hasInfo(info2->type())); EXPECT_FALSE(buffer->hasInfo(info2->type())); } } TEST_F(C2BufferTest, MultipleLinearMapTest) { std::shared_ptr<C2BlockPool> pool(makeLinearBlockPool()); constexpr size_t kCapacity = 524288u; for (int i = 0; i < 100; ++i) { std::vector<C2WriteView> wViews; std::vector<C2ReadView> rViews; for (int j = 0; j < 16; ++j) { std::shared_ptr<C2LinearBlock> block; ASSERT_EQ(C2_OK, pool->fetchLinearBlock( kCapacity, { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, &block)); wViews.push_back(block->map().get()); C2ConstLinearBlock cBlock = block->share(0, kCapacity / 2, C2Fence()); rViews.push_back(cBlock.map().get()); } } } } // namespace android } // namespace android
media/libstagefright/codec2/vndk/C2AllocatorIon.cpp +44 −30 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define LOG_TAG "C2AllocatorIon" #define LOG_TAG "C2AllocatorIon" #include <utils/Log.h> #include <utils/Log.h> #include <list> #include <ion/ion.h> #include <ion/ion.h> #include <sys/mman.h> #include <sys/mman.h> #include <unistd.h> #include <unistd.h> Loading Loading @@ -161,8 +163,7 @@ private: mBuffer(buffer), mBuffer(buffer), mId(id), mId(id), mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)), mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)), mMapFd(-1), mMapFd(-1) { mMapSize(0) { if (mInit != C2_OK) { if (mInit != C2_OK) { // close ionFd now on error // close ionFd now on error if (mIonFd >= 0) { if (mIonFd >= 0) { Loading Loading @@ -221,7 +222,8 @@ public: c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) { c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) { (void)fence; // TODO: wait for fence (void)fence; // TODO: wait for fence *addr = nullptr; *addr = nullptr; if (mMapSize > 0) { if (!mMappings.empty()) { ALOGV("multiple map"); // TODO: technically we should return DUPLICATE here, but our block views don't // TODO: technically we should return DUPLICATE here, but our block views don't // actually unmap, so we end up remapping an ion buffer multiple times. // actually unmap, so we end up remapping an ion buffer multiple times. // // Loading @@ -244,54 +246,63 @@ public: size_t alignmentBytes = offset % PAGE_SIZE; size_t alignmentBytes = offset % PAGE_SIZE; size_t mapOffset = offset - alignmentBytes; size_t mapOffset = offset - alignmentBytes; size_t mapSize = size + alignmentBytes; size_t mapSize = size + alignmentBytes; Mapping map = { nullptr, alignmentBytes, mapSize }; c2_status_t err = C2_OK; c2_status_t err = C2_OK; if (mMapFd == -1) { if (mMapFd == -1) { int ret = ion_map(mIonFd, mBuffer, mapSize, prot, int ret = ion_map(mIonFd, mBuffer, mapSize, prot, flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd); flags, mapOffset, (unsigned char**)&map.addr, &mMapFd); if (ret) { if (ret) { mMapFd = -1; mMapFd = -1; *addr = nullptr; map.addr = *addr = nullptr; err = c2_map_errno<EINVAL>(-ret); err = c2_map_errno<EINVAL>(-ret); } else { } else { *addr = (uint8_t *)mMapAddr + alignmentBytes; *addr = (uint8_t *)map.addr + alignmentBytes; mMapAlignmentBytes = alignmentBytes; mMapSize = mapSize; } } } else { } else { mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset); map.addr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset); if (mMapAddr == MAP_FAILED) { if (map.addr == MAP_FAILED) { mMapAddr = *addr = nullptr; map.addr = *addr = nullptr; err = c2_map_errno<EINVAL>(errno); err = c2_map_errno<EINVAL>(errno); } else { } else { *addr = (uint8_t *)mMapAddr + alignmentBytes; *addr = (uint8_t *)map.addr + alignmentBytes; mMapAlignmentBytes = alignmentBytes; } mMapSize = mapSize; } } if (map.addr) { mMappings.push_back(map); } } return err; return err; } } c2_status_t unmap(void *addr, size_t size, C2Fence *fence) { c2_status_t unmap(void *addr, size_t size, C2Fence *fence) { if (mMapFd < 0 || mMapSize == 0) { if (mMapFd < 0 || mMappings.empty()) { return C2_NOT_FOUND; return C2_NOT_FOUND; } } if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes || for (auto it = mMappings.begin(); it != mMappings.end(); ++it) { size + mMapAlignmentBytes != mMapSize) { if (addr != (uint8_t *)it->addr + it->alignmentBytes || return C2_BAD_VALUE; size + it->alignmentBytes != it->size) { continue; } } int err = munmap(mMapAddr, mMapSize); int err = munmap(it->addr, it->size); if (err != 0) { if (err != 0) { return c2_map_errno<EINVAL>(errno); return c2_map_errno<EINVAL>(errno); } } if (fence) { if (fence) { *fence = C2Fence(); // not using fences *fence = C2Fence(); // not using fences } } mMapSize = 0; (void)mMappings.erase(it); return C2_OK; return C2_OK; } } return C2_BAD_VALUE; } ~Impl() { ~Impl() { if (!mMappings.empty()) { ALOGD("Dangling mappings!"); for (const Mapping &map : mMappings) { (void)munmap(map.addr, map.size); } } if (mMapFd >= 0) { if (mMapFd >= 0) { close(mMapFd); close(mMapFd); mMapFd = -1; mMapFd = -1; Loading Loading @@ -328,9 +339,12 @@ private: C2Allocator::id_t mId; C2Allocator::id_t mId; c2_status_t mInit; c2_status_t mInit; int mMapFd; // only one for now int mMapFd; // only one for now void *mMapAddr; struct Mapping { size_t mMapAlignmentBytes; void *addr; size_t mMapSize; size_t alignmentBytes; size_t size; }; std::list<Mapping> mMappings; }; }; c2_status_t C2AllocationIon::map( c2_status_t C2AllocationIon::map( Loading