Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a16d4f1c authored by Wonsik Kim's avatar Wonsik Kim Committed by android-build-merger
Browse files

Merge "codec2: handle multiple maps in linear block" into pi-dev am: 23409227

am: 965f551c

Change-Id: Ie8efc21417f926bc9ca8ff6a511f06beb2cd01c6
parents e84d9ca0 965f551c
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -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
+44 −30
Original line number Original line Diff line number Diff line
@@ -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>
@@ -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) {
@@ -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.
            //
            //
@@ -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;
@@ -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(