display: Add support for pmem in the new gralloc
Change-Id: Ice6f436a01c3344a6d859ee0afc77673f151dbe4
This commit is contained in:
		@@ -1,8 +1,4 @@
 | 
			
		||||
#Enables the listed display HAL modules
 | 
			
		||||
display-hals := libhwcomposer liboverlay
 | 
			
		||||
ifeq ($(TARGET_USES_ION),true)
 | 
			
		||||
    display-hals += libgralloc
 | 
			
		||||
    include $(call all-named-subdir-makefiles,$(display-hals))
 | 
			
		||||
endif
 | 
			
		||||
display-hals := libhwcomposer liboverlay libgralloc
 | 
			
		||||
include $(call all-named-subdir-makefiles,$(display-hals))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
 | 
			
		||||
# Use this flag until pmem/ashmem is implemented in the new gralloc
 | 
			
		||||
ifeq ($(TARGET_USES_ION),true)
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
# HAL module implemenation, not prelinked and stored in
 | 
			
		||||
@@ -28,13 +27,11 @@ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 | 
			
		||||
LOCAL_SRC_FILES :=  framebuffer.cpp \
 | 
			
		||||
                    gpu.cpp         \
 | 
			
		||||
                    gralloc.cpp     \
 | 
			
		||||
                    mapper.cpp      \
 | 
			
		||||
                    pmemalloc.cpp   \
 | 
			
		||||
                    pmem_bestfit_alloc.cpp
 | 
			
		||||
                    mapper.cpp
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS -DUSE_ION
 | 
			
		||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
 | 
			
		||||
 | 
			
		||||
ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true)
 | 
			
		||||
    LOCAL_CFLAGS += -DTARGET_MSM7x27
 | 
			
		||||
@@ -53,6 +50,7 @@ endif
 | 
			
		||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
 | 
			
		||||
    LOCAL_CFLAGS += -DUSE_ASHMEM
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
 | 
			
		||||
#MemAlloc Library
 | 
			
		||||
@@ -64,9 +62,15 @@ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
 | 
			
		||||
LOCAL_SRC_FILES :=  ionalloc.cpp \
 | 
			
		||||
                    ashmemalloc.cpp \
 | 
			
		||||
                    pmemalloc.cpp \
 | 
			
		||||
                    pmem_bestfit_alloc.cpp \
 | 
			
		||||
                    alloc_controller.cpp
 | 
			
		||||
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\" -DLOG_NDDEBUG=0 -DUSE_ION
 | 
			
		||||
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\" -DLOG_NDDEBUG=0
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_USES_ION),true)
 | 
			
		||||
    LOCAL_CFLAGS += -DUSE_ION
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE := libmemalloc
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
endif #TARGET_USES_ION
 | 
			
		||||
 
 | 
			
		||||
@@ -29,33 +29,19 @@
 | 
			
		||||
 | 
			
		||||
#include <cutils/log.h>
 | 
			
		||||
#include <utils/RefBase.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include "gralloc_priv.h"
 | 
			
		||||
#include "alloc_controller.h"
 | 
			
		||||
#include "memalloc.h"
 | 
			
		||||
#include "ionalloc.h"
 | 
			
		||||
#include "pmemalloc.h"
 | 
			
		||||
#include "ashmemalloc.h"
 | 
			
		||||
 | 
			
		||||
using namespace gralloc;
 | 
			
		||||
using android::sp;
 | 
			
		||||
 | 
			
		||||
sp<IAllocController> IAllocController::sController = NULL;
 | 
			
		||||
sp<IAllocController> IAllocController::getInstance(void)
 | 
			
		||||
{
 | 
			
		||||
    if(sController == NULL) {
 | 
			
		||||
#ifdef USE_ION
 | 
			
		||||
        sController = new IonController();
 | 
			
		||||
#else
 | 
			
		||||
        // XXX: Return pmem/ashmem controller when completed
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    return sController;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IonController::IonController()
 | 
			
		||||
{
 | 
			
		||||
    mIonAlloc = new IonAlloc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool canFallback(int compositionType, int usage, int flags)
 | 
			
		||||
//Common functions
 | 
			
		||||
static bool canFallback(int compositionType, int usage, bool triedSystem)
 | 
			
		||||
{
 | 
			
		||||
    // Fallback to system heap when alloc fails unless
 | 
			
		||||
    // 1. Composition type is MDP
 | 
			
		||||
@@ -64,7 +50,7 @@ static bool canFallback(int compositionType, int usage, int flags)
 | 
			
		||||
 | 
			
		||||
    if(compositionType == MDP_COMPOSITION)
 | 
			
		||||
        return false;
 | 
			
		||||
    if(flags & ION_HEAP_SYSTEM_ID)
 | 
			
		||||
    if(triedSystem)
 | 
			
		||||
        return false;
 | 
			
		||||
    if(usage &(GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
 | 
			
		||||
               GRALLOC_USAGE_PRIVATE_EBI_HEAP |
 | 
			
		||||
@@ -74,6 +60,29 @@ static bool canFallback(int compositionType, int usage, int flags)
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sp<IAllocController> IAllocController::sController = NULL;
 | 
			
		||||
sp<IAllocController> IAllocController::getInstance(bool useMasterHeap)
 | 
			
		||||
{
 | 
			
		||||
    if(sController == NULL) {
 | 
			
		||||
#ifdef USE_ION
 | 
			
		||||
        sController = new IonController();
 | 
			
		||||
#else
 | 
			
		||||
        if(useMasterHeap)
 | 
			
		||||
            sController = new PmemAshmemController();
 | 
			
		||||
        else
 | 
			
		||||
            sController = new PmemKernelController();
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    return sController;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//-------------- IonController-----------------------//
 | 
			
		||||
IonController::IonController()
 | 
			
		||||
{
 | 
			
		||||
    mIonAlloc = new IonAlloc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int IonController::allocate(alloc_data& data, int usage,
 | 
			
		||||
        int compositionType)
 | 
			
		||||
{
 | 
			
		||||
@@ -110,7 +119,10 @@ int IonController::allocate(alloc_data& data, int usage,
 | 
			
		||||
    ret = mIonAlloc->alloc_buffer(data);
 | 
			
		||||
 | 
			
		||||
    // Fallback
 | 
			
		||||
    if(ret < 0 && canFallback(compositionType, usage, ionFlags)) {
 | 
			
		||||
    if(ret < 0 && canFallback(compositionType,
 | 
			
		||||
                              usage,
 | 
			
		||||
                              (ionFlags & ION_HEAP_SYSTEM_ID)))
 | 
			
		||||
    {
 | 
			
		||||
        LOGW("Falling back to system heap");
 | 
			
		||||
        data.flags = 1 << ION_HEAP_SYSTEM_ID;
 | 
			
		||||
        ret = mIonAlloc->alloc_buffer(data);
 | 
			
		||||
@@ -134,20 +146,144 @@ sp<IMemAlloc> IonController::getAllocator(int flags)
 | 
			
		||||
    return memalloc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//-------------- PmemKernelController-----------------------//
 | 
			
		||||
 | 
			
		||||
PmemKernelController::PmemKernelController()
 | 
			
		||||
{
 | 
			
		||||
     mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
 | 
			
		||||
     // XXX: Right now, there is no need to maintain an instance
 | 
			
		||||
     // of the SMI allocator as we need it only in a few cases
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemKernelController::~PmemKernelController()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemKernelController::allocate(alloc_data& data, int usage,
 | 
			
		||||
        int compositionType)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    bool adspFallback = false;
 | 
			
		||||
 | 
			
		||||
    // Try SMI first
 | 
			
		||||
    if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) ||
 | 
			
		||||
        (usage & GRALLOC_USAGE_EXTERNAL_DISP)    ||
 | 
			
		||||
        (usage & GRALLOC_USAGE_PROTECTED))
 | 
			
		||||
    {
 | 
			
		||||
        int tempFd = open(DEVICE_PMEM_SMIPOOL, O_RDWR, 0);
 | 
			
		||||
        if(tempFd > 0) {
 | 
			
		||||
            close(tempFd);
 | 
			
		||||
            sp<IMemAlloc> memalloc;
 | 
			
		||||
            memalloc = new PmemKernelAlloc(DEVICE_PMEM_SMIPOOL);
 | 
			
		||||
            ret = memalloc->alloc_buffer(data);
 | 
			
		||||
            if(ret >= 0)
 | 
			
		||||
                return ret;
 | 
			
		||||
            else {
 | 
			
		||||
                adspFallback = true;
 | 
			
		||||
                LOGW("Allocation from SMI failed, trying ADSP");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || adspFallback) {
 | 
			
		||||
        ret = mPmemAdspAlloc->alloc_buffer(data);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sp<IMemAlloc> PmemKernelController::getAllocator(int flags)
 | 
			
		||||
{
 | 
			
		||||
    sp<IMemAlloc> memalloc;
 | 
			
		||||
    if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)
 | 
			
		||||
        memalloc = mPmemAdspAlloc;
 | 
			
		||||
    else {
 | 
			
		||||
        LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
 | 
			
		||||
        memalloc = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return memalloc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//-------------- PmemAshmmemController-----------------------//
 | 
			
		||||
 | 
			
		||||
PmemAshmemController::PmemAshmemController()
 | 
			
		||||
{
 | 
			
		||||
    mPmemUserspaceAlloc = new PmemUserspaceAlloc();
 | 
			
		||||
    mAshmemAlloc = new AshmemAlloc();
 | 
			
		||||
    mPmemKernelCtrl = new PmemKernelController();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemAshmemController::~PmemAshmemController()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemAshmemController::allocate(alloc_data& data, int usage,
 | 
			
		||||
        int compositionType)
 | 
			
		||||
{
 | 
			
		||||
    //XXX PMEM with ashmem fallback strategy
 | 
			
		||||
    return 0;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    // Decide caching
 | 
			
		||||
    // Decide based on usage
 | 
			
		||||
    uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK;
 | 
			
		||||
    uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
 | 
			
		||||
    if (uread == GRALLOC_USAGE_SW_READ_OFTEN ||
 | 
			
		||||
        uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) {
 | 
			
		||||
        data.uncached = false;
 | 
			
		||||
    } else {
 | 
			
		||||
        data.uncached = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Override if we explicitly need uncached buffers
 | 
			
		||||
    if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
 | 
			
		||||
        data.uncached = true;
 | 
			
		||||
 | 
			
		||||
    // If ADSP or SMI is requested use the kernel controller
 | 
			
		||||
    if(usage & (GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
 | 
			
		||||
                GRALLOC_USAGE_PRIVATE_SMI_HEAP)) {
 | 
			
		||||
        ret = mPmemKernelCtrl->allocate(data, usage, compositionType);
 | 
			
		||||
        if(ret < 0)
 | 
			
		||||
            LOGE("%s: Failed to allocate ADSP/SMI memory", __func__);
 | 
			
		||||
        else
 | 
			
		||||
            data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) {
 | 
			
		||||
        ret = mAshmemAlloc->alloc_buffer(data);
 | 
			
		||||
        if(ret >= 0)
 | 
			
		||||
            data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // if no memory specific flags are set,
 | 
			
		||||
    // default to EBI heap, so that bypass
 | 
			
		||||
    // can work. We can fall back to system
 | 
			
		||||
    // heap if we run out.
 | 
			
		||||
    ret = mPmemUserspaceAlloc->alloc_buffer(data);
 | 
			
		||||
 | 
			
		||||
    // Fallback
 | 
			
		||||
    if(ret >= 0 ) {
 | 
			
		||||
        data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM;
 | 
			
		||||
    } else if(ret < 0 && canFallback(compositionType, usage, false)) {
 | 
			
		||||
        LOGW("Falling back to ashmem");
 | 
			
		||||
        ret = mAshmemAlloc->alloc_buffer(data);
 | 
			
		||||
        if(ret >= 0)
 | 
			
		||||
            data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sp<IMemAlloc> PmemAshmemController::getAllocator(int flags)
 | 
			
		||||
{
 | 
			
		||||
    sp<IMemAlloc> memalloc;
 | 
			
		||||
    if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
 | 
			
		||||
        // XXX Return right allocator based on flags
 | 
			
		||||
        memalloc = NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
    if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM)
 | 
			
		||||
        memalloc = mPmemUserspaceAlloc;
 | 
			
		||||
    else if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)
 | 
			
		||||
        memalloc = mPmemKernelCtrl->getAllocator(flags);
 | 
			
		||||
    else if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
 | 
			
		||||
        memalloc = mAshmemAlloc;
 | 
			
		||||
    else {
 | 
			
		||||
        LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
 | 
			
		||||
        memalloc = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ namespace gralloc {
 | 
			
		||||
 | 
			
		||||
            virtual ~IAllocController() {};
 | 
			
		||||
 | 
			
		||||
            static android::sp<IAllocController> getInstance(void);
 | 
			
		||||
            static android::sp<IAllocController> getInstance(bool useMasterHeap);
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            static android::sp<IAllocController> sController;
 | 
			
		||||
@@ -72,6 +72,25 @@ namespace gralloc {
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class PmemKernelController : public IAllocController {
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
            virtual int allocate(alloc_data& data, int usage,
 | 
			
		||||
                    int compositionType);
 | 
			
		||||
 | 
			
		||||
            virtual android::sp<IMemAlloc> getAllocator(int flags);
 | 
			
		||||
 | 
			
		||||
            PmemKernelController ();
 | 
			
		||||
 | 
			
		||||
            ~PmemKernelController ();
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            android::sp<IMemAlloc> mPmemAdspAlloc;
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Main pmem controller - this should only
 | 
			
		||||
    // be used within gralloc
 | 
			
		||||
    class PmemAshmemController : public IAllocController {
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
@@ -79,7 +98,15 @@ namespace gralloc {
 | 
			
		||||
                    int compositionType);
 | 
			
		||||
 | 
			
		||||
            virtual android::sp<IMemAlloc> getAllocator(int flags);
 | 
			
		||||
            // XXX: Pmem and ashmem alloc objects
 | 
			
		||||
 | 
			
		||||
            PmemAshmemController();
 | 
			
		||||
 | 
			
		||||
            ~PmemAshmemController();
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            android::sp<IMemAlloc> mPmemUserspaceAlloc;
 | 
			
		||||
            android::sp<IMemAlloc> mAshmemAlloc;
 | 
			
		||||
            android::sp<IAllocController> mPmemKernelCtrl;
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -161,7 +161,6 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
 | 
			
		||||
    else
 | 
			
		||||
        data.align = getpagesize();
 | 
			
		||||
    data.pHandle = (unsigned int) pHandle;
 | 
			
		||||
    data.bufferType = bufferType;
 | 
			
		||||
    err = mAllocCtrl->allocate(data, usage, compositionType);
 | 
			
		||||
 | 
			
		||||
    if (err == 0) {
 | 
			
		||||
@@ -307,8 +306,8 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) {
 | 
			
		||||
                hnd->offset, hnd->fd);
 | 
			
		||||
        if(err)
 | 
			
		||||
            return err;
 | 
			
		||||
        terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
 | 
			
		||||
    }
 | 
			
		||||
    // XXX any additional cleanup.
 | 
			
		||||
    delete hnd;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ int gralloc_device_open(const hw_module_t* module, const char* name,
 | 
			
		||||
        const private_module_t* m = reinterpret_cast<const private_module_t*>(
 | 
			
		||||
                module);
 | 
			
		||||
        gpu_context_t *dev;
 | 
			
		||||
        sp<IAllocController> alloc_ctrl = IAllocController::getInstance();
 | 
			
		||||
        sp<IAllocController> alloc_ctrl = IAllocController::getInstance(true);
 | 
			
		||||
        dev = new gpu_context_t(m, alloc_ctrl);
 | 
			
		||||
        *device = &dev->common;
 | 
			
		||||
        status = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,7 @@ enum {
 | 
			
		||||
#define INTERLACE_MASK 0x80
 | 
			
		||||
#define S3D_FORMAT_MASK 0xFF000
 | 
			
		||||
#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
 | 
			
		||||
#define DEVICE_PMEM "/dev/pmem"
 | 
			
		||||
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
 | 
			
		||||
#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
 | 
			
		||||
/*****************************************************************************/
 | 
			
		||||
 
 | 
			
		||||
@@ -39,12 +39,10 @@
 | 
			
		||||
 | 
			
		||||
#include "gralloc_priv.h"
 | 
			
		||||
#include "gr.h"
 | 
			
		||||
#include "ionalloc.h"
 | 
			
		||||
#include "ashmemalloc.h"
 | 
			
		||||
#include "alloc_controller.h"
 | 
			
		||||
#include "memalloc.h"
 | 
			
		||||
 | 
			
		||||
using gralloc::IMemAlloc;
 | 
			
		||||
using gralloc::IonAlloc;
 | 
			
		||||
using gralloc::AshmemAlloc;
 | 
			
		||||
using namespace gralloc;
 | 
			
		||||
using android::sp;
 | 
			
		||||
/*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
@@ -53,14 +51,8 @@ using android::sp;
 | 
			
		||||
static sp<IMemAlloc> getAllocator(int flags)
 | 
			
		||||
{
 | 
			
		||||
    sp<IMemAlloc> memalloc;
 | 
			
		||||
    if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
 | 
			
		||||
        memalloc =  new IonAlloc();
 | 
			
		||||
    }
 | 
			
		||||
    if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
 | 
			
		||||
        memalloc =  new AshmemAlloc();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // XXX Return allocator for pmem
 | 
			
		||||
    sp<IAllocController> alloc_ctrl = IAllocController::getInstance(true);
 | 
			
		||||
    memalloc = alloc_ctrl->getAllocator(flags);
 | 
			
		||||
    return memalloc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -192,7 +184,8 @@ int terminateBuffer(gralloc_module_t const* module,
 | 
			
		||||
        // this buffer was mapped, unmap it now
 | 
			
		||||
        if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
 | 
			
		||||
                          private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
 | 
			
		||||
                          private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
 | 
			
		||||
                          private_handle_t::PRIV_FLAGS_USES_ASHMEM |
 | 
			
		||||
                          private_handle_t::PRIV_FLAGS_USES_ION)) {
 | 
			
		||||
            if (hnd->pid != getpid()) {
 | 
			
		||||
                // ... unless it's a "master" pmem buffer, that is a buffer
 | 
			
		||||
                // mapped in the process it's been allocated.
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,6 @@ namespace gralloc {
 | 
			
		||||
        unsigned int   pHandle;
 | 
			
		||||
        bool           uncached;
 | 
			
		||||
        unsigned int   flags;
 | 
			
		||||
        int            bufferType;
 | 
			
		||||
        int            allocType;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * A simple templatized doubly linked-list implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
template <typename NODE>
 | 
			
		||||
class LinkedList
 | 
			
		||||
{
 | 
			
		||||
@@ -93,7 +92,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SimpleBestFitAllocator : public PmemUserspaceAllocator::Deps::Allocator
 | 
			
		||||
class SimpleBestFitAllocator : public gralloc::PmemUserspaceAlloc::Allocator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
@@ -127,5 +126,4 @@ private:
 | 
			
		||||
    LinkedList<chunk_t> mList;
 | 
			
		||||
    size_t              mHeapSize;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* GRALLOC_ALLOCATOR_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,135 +1,157 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are
 | 
			
		||||
 * met:
 | 
			
		||||
 *   * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *     notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   * Redistributions in binary form must reproduce the above
 | 
			
		||||
 *     copyright notice, this list of conditions and the following
 | 
			
		||||
 *     disclaimer in the documentation and/or other materials provided
 | 
			
		||||
 *     with the distribution.
 | 
			
		||||
 *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
 | 
			
		||||
 *     contributors may be used to endorse or promote products derived
 | 
			
		||||
 *     from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 | 
			
		||||
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
			
		||||
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 | 
			
		||||
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 | 
			
		||||
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <cutils/log.h>
 | 
			
		||||
#include <cutils/ashmem.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <linux/android_pmem.h>
 | 
			
		||||
#include "gralloc_priv.h"
 | 
			
		||||
#include "pmemalloc.h"
 | 
			
		||||
#include "pmem_bestfit_alloc.h"
 | 
			
		||||
 | 
			
		||||
using namespace gralloc;
 | 
			
		||||
using android::sp;
 | 
			
		||||
 | 
			
		||||
#define BEGIN_FUNC LOGV("%s begin", __PRETTY_FUNCTION__)
 | 
			
		||||
#define END_FUNC LOGV("%s end", __PRETTY_FUNCTION__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int get_open_flags(int usage) {
 | 
			
		||||
    int openFlags = O_RDWR | O_SYNC;
 | 
			
		||||
    uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK;
 | 
			
		||||
    uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
 | 
			
		||||
    if (uread == GRALLOC_USAGE_SW_READ_OFTEN ||
 | 
			
		||||
        uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) {
 | 
			
		||||
        openFlags &= ~O_SYNC;
 | 
			
		||||
    }
 | 
			
		||||
    return openFlags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemAllocator::~PmemAllocator()
 | 
			
		||||
// Common functions between userspace
 | 
			
		||||
// and kernel allocators
 | 
			
		||||
static int getPmemTotalSize(int fd, size_t* size)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps,
 | 
			
		||||
        Deps::Allocator& allocator, const char* pmemdev):
 | 
			
		||||
    deps(deps),
 | 
			
		||||
    allocator(allocator),
 | 
			
		||||
    pmemdev(pmemdev),
 | 
			
		||||
    master_fd(MASTER_FD_INIT)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    pthread_mutex_init(&lock, NULL);
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PmemUserspaceAllocator::~PmemUserspaceAllocator()
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* PmemUserspaceAllocator::get_base_address() {
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return master_base;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAllocator::init_pmem_area_locked()
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    //XXX: 7x27
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    int fd = deps.open(pmemdev, O_RDWR, 0);
 | 
			
		||||
    if (fd >= 0) {
 | 
			
		||||
        size_t size = 0;
 | 
			
		||||
        err = deps.getPmemTotalSize(fd, &size);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            LOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", pmemdev,
 | 
			
		||||
                    err);
 | 
			
		||||
            size = 8<<20;   // 8 MiB
 | 
			
		||||
        }
 | 
			
		||||
        allocator.setSize(size);
 | 
			
		||||
 | 
			
		||||
        void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
 | 
			
		||||
                0);
 | 
			
		||||
        if (base == MAP_FAILED) {
 | 
			
		||||
            LOGE("%s: failed to map pmem master fd: %s", pmemdev,
 | 
			
		||||
                    strerror(deps.getErrno()));
 | 
			
		||||
            err = -deps.getErrno();
 | 
			
		||||
            base = 0;
 | 
			
		||||
            deps.close(fd);
 | 
			
		||||
            fd = -1;
 | 
			
		||||
        } else {
 | 
			
		||||
            master_fd = fd;
 | 
			
		||||
            master_base = base;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        LOGE("%s: failed to open pmem device: %s", pmemdev,
 | 
			
		||||
                strerror(deps.getErrno()));
 | 
			
		||||
        err = -deps.getErrno();
 | 
			
		||||
    pmem_region region;
 | 
			
		||||
    err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion);
 | 
			
		||||
    if (err == 0) {
 | 
			
		||||
        *size = region.len;
 | 
			
		||||
    }
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAllocator::init_pmem_area()
 | 
			
		||||
static int getOpenFlags(bool uncached)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    pthread_mutex_lock(&lock);
 | 
			
		||||
    int err = master_fd;
 | 
			
		||||
    if (err == MASTER_FD_INIT) {
 | 
			
		||||
    if(uncached)
 | 
			
		||||
        return O_RDWR | O_SYNC;
 | 
			
		||||
    else
 | 
			
		||||
        return O_RDWR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int connectPmem(int fd, int master_fd) {
 | 
			
		||||
    return ioctl(fd, PMEM_CONNECT, master_fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mapSubRegion(int fd, int offset, size_t size) {
 | 
			
		||||
    struct pmem_region sub = { offset, size };
 | 
			
		||||
    return ioctl(fd, PMEM_MAP, &sub);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int unmapSubRegion(int fd, int offset, size_t size) {
 | 
			
		||||
    struct pmem_region sub = { offset, size };
 | 
			
		||||
    return ioctl(fd, PMEM_UNMAP, &sub);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int alignPmem(int fd, size_t size, int align) {
 | 
			
		||||
    struct pmem_allocation allocation;
 | 
			
		||||
    allocation.size = size;
 | 
			
		||||
    allocation.align = align;
 | 
			
		||||
    return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cleanPmem(void *base, size_t size, int offset, int fd) {
 | 
			
		||||
    struct pmem_addr pmem_addr;
 | 
			
		||||
    pmem_addr.vaddr = (unsigned long) base;
 | 
			
		||||
    pmem_addr.offset = offset;
 | 
			
		||||
    pmem_addr.length = size;
 | 
			
		||||
    return ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//-------------- PmemUserspaceAlloc-----------------------//
 | 
			
		||||
PmemUserspaceAlloc::PmemUserspaceAlloc()
 | 
			
		||||
{
 | 
			
		||||
    mPmemDev = DEVICE_PMEM;
 | 
			
		||||
    mMasterFd = FD_INIT;
 | 
			
		||||
    mAllocator = new SimpleBestFitAllocator();
 | 
			
		||||
    pthread_mutex_init(&mLock, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemUserspaceAlloc::~PmemUserspaceAlloc()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAlloc::init_pmem_area_locked()
 | 
			
		||||
{
 | 
			
		||||
    LOGD("%s: Opening master pmem FD", __FUNCTION__);
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    int fd = open(mPmemDev, O_RDWR, 0);
 | 
			
		||||
    if (fd >= 0) {
 | 
			
		||||
        size_t size = 0;
 | 
			
		||||
        err = getPmemTotalSize(fd, &size);
 | 
			
		||||
        LOGD("%s: Total pmem size: %d", __FUNCTION__, size);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            LOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", mPmemDev,
 | 
			
		||||
                    err);
 | 
			
		||||
            size = 8<<20;   // 8 MiB
 | 
			
		||||
        }
 | 
			
		||||
        mAllocator->setSize(size);
 | 
			
		||||
 | 
			
		||||
        void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
 | 
			
		||||
                0);
 | 
			
		||||
        if (base == MAP_FAILED) {
 | 
			
		||||
            LOGE("%s: Failed to map pmem master fd: %s", mPmemDev,
 | 
			
		||||
                    strerror(errno));
 | 
			
		||||
            err = -errno;
 | 
			
		||||
            base = 0;
 | 
			
		||||
            close(fd);
 | 
			
		||||
            fd = -1;
 | 
			
		||||
        } else {
 | 
			
		||||
            mMasterFd = fd;
 | 
			
		||||
            mMasterBase = base;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        LOGE("%s: Failed to open pmem device: %s", mPmemDev,
 | 
			
		||||
                strerror(errno));
 | 
			
		||||
        err = -errno;
 | 
			
		||||
    }
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int  PmemUserspaceAlloc::init_pmem_area()
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_lock(&mLock);
 | 
			
		||||
    int err = mMasterFd;
 | 
			
		||||
    if (err == FD_INIT) {
 | 
			
		||||
        // first time, try to initialize pmem
 | 
			
		||||
        LOGD("%s: Initializing pmem area", __FUNCTION__);
 | 
			
		||||
        err = init_pmem_area_locked();
 | 
			
		||||
        if (err) {
 | 
			
		||||
            LOGE("%s: failed to initialize pmem area", pmemdev);
 | 
			
		||||
            master_fd = err;
 | 
			
		||||
            LOGE("%s: failed to initialize pmem area", mPmemDev);
 | 
			
		||||
            mMasterFd = err;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (err < 0) {
 | 
			
		||||
        // pmem couldn't be initialized, never use it
 | 
			
		||||
@@ -137,227 +159,211 @@ int PmemUserspaceAllocator::init_pmem_area()
 | 
			
		||||
        // pmem OK
 | 
			
		||||
        err = 0;
 | 
			
		||||
    }
 | 
			
		||||
    pthread_mutex_unlock(&lock);
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    pthread_mutex_unlock(&mLock);
 | 
			
		||||
    return err;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
 | 
			
		||||
        void** pBase, int* pOffset, int* pFd, int format)
 | 
			
		||||
int PmemUserspaceAlloc::alloc_buffer(alloc_data& data)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    int err = init_pmem_area();
 | 
			
		||||
    if (err == 0) {
 | 
			
		||||
        void* base = master_base;
 | 
			
		||||
        int offset = allocator.allocate(size);
 | 
			
		||||
        void* base = mMasterBase;
 | 
			
		||||
        size_t size = data.size;
 | 
			
		||||
        int offset = mAllocator->allocate(size);
 | 
			
		||||
        if (offset < 0) {
 | 
			
		||||
            // no more pmem memory
 | 
			
		||||
            LOGE("%s: no more pmem available", pmemdev);
 | 
			
		||||
            LOGE("%s: No more pmem available", mPmemDev);
 | 
			
		||||
            err = -ENOMEM;
 | 
			
		||||
        } else {
 | 
			
		||||
            int openFlags = get_open_flags(usage);
 | 
			
		||||
 | 
			
		||||
            //LOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset);
 | 
			
		||||
            int openFlags = getOpenFlags(data.uncached);
 | 
			
		||||
 | 
			
		||||
            // now create the "sub-heap"
 | 
			
		||||
            int fd = deps.open(pmemdev, openFlags, 0);
 | 
			
		||||
            int fd = open(mPmemDev, openFlags, 0);
 | 
			
		||||
            err = fd < 0 ? fd : 0;
 | 
			
		||||
 | 
			
		||||
            // and connect to it
 | 
			
		||||
            if (err == 0)
 | 
			
		||||
                err = deps.connectPmem(fd, master_fd);
 | 
			
		||||
                err = connectPmem(fd, mMasterFd);
 | 
			
		||||
 | 
			
		||||
            // and make it available to the client process
 | 
			
		||||
            if (err == 0)
 | 
			
		||||
                err = deps.mapPmem(fd, offset, size);
 | 
			
		||||
                err = mapSubRegion(fd, offset, size);
 | 
			
		||||
 | 
			
		||||
            if (err < 0) {
 | 
			
		||||
                LOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev,
 | 
			
		||||
                LOGE("%s: Failed to initialize pmem sub-heap: %d", mPmemDev,
 | 
			
		||||
                        err);
 | 
			
		||||
                err = -deps.getErrno();
 | 
			
		||||
                deps.close(fd);
 | 
			
		||||
                allocator.deallocate(offset);
 | 
			
		||||
                err = -errno;
 | 
			
		||||
                close(fd);
 | 
			
		||||
                mAllocator->deallocate(offset);
 | 
			
		||||
                fd = -1;
 | 
			
		||||
            } else {
 | 
			
		||||
                LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size);
 | 
			
		||||
                LOGD("%s: Allocated buffer base:%p size:%d offset:%d fd:%d",
 | 
			
		||||
                        mPmemDev, base, size, offset, fd);
 | 
			
		||||
                memset((char*)base + offset, 0, size);
 | 
			
		||||
                //Clean cache before flushing to ensure pmem is properly flushed
 | 
			
		||||
                err = deps.cleanPmem(fd, (unsigned long) base + offset, offset, size);
 | 
			
		||||
                err = clean_buffer((void*)((intptr_t) base + offset), size, offset, fd);
 | 
			
		||||
                if (err < 0) {
 | 
			
		||||
                    LOGE("cleanPmem failed: (%s)", strerror(deps.getErrno()));
 | 
			
		||||
                    LOGE("cleanPmem failed: (%s)", strerror(errno));
 | 
			
		||||
                }
 | 
			
		||||
#ifdef HOST
 | 
			
		||||
                 cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0);
 | 
			
		||||
#endif
 | 
			
		||||
                *pBase = base;
 | 
			
		||||
                *pOffset = offset;
 | 
			
		||||
                *pFd = fd;
 | 
			
		||||
                cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0);
 | 
			
		||||
                data.base = base;
 | 
			
		||||
                data.offset = offset;
 | 
			
		||||
                data.fd = fd;
 | 
			
		||||
            }
 | 
			
		||||
            //LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return err;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base,
 | 
			
		||||
                                             int offset, int fd)
 | 
			
		||||
int PmemUserspaceAlloc::free_buffer(void* base, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    LOGD("%s: Freeing buffer base:%p size:%d offset:%d fd:%d",
 | 
			
		||||
            mPmemDev, base, size, offset, fd);
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    if (fd >= 0) {
 | 
			
		||||
        int err = deps.unmapPmem(fd, offset, size);
 | 
			
		||||
        int err = unmapSubRegion(fd, offset, size);
 | 
			
		||||
        LOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, "
 | 
			
		||||
                "sub.size=%u", strerror(deps.getErrno()), fd, offset, size);
 | 
			
		||||
                "sub.size=%u", strerror(errno), fd, offset, size);
 | 
			
		||||
        if (err == 0) {
 | 
			
		||||
            // we can't deallocate the memory in case of UNMAP failure
 | 
			
		||||
            // because it would give that process access to someone else's
 | 
			
		||||
            // surfaces, which would be a security breach.
 | 
			
		||||
            allocator.deallocate(offset);
 | 
			
		||||
            mAllocator->deallocate(offset);
 | 
			
		||||
        }
 | 
			
		||||
        close(fd);
 | 
			
		||||
    }
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemUserspaceAllocator::Deps::Allocator::~Allocator()
 | 
			
		||||
int PmemUserspaceAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemUserspaceAllocator::Deps::~Deps()
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemKernelAllocator::PmemKernelAllocator(Deps& deps):
 | 
			
		||||
    deps(deps)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PmemKernelAllocator::~PmemKernelAllocator()
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* PmemKernelAllocator::get_base_address() {
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static unsigned clp2(unsigned x) {
 | 
			
		||||
    x = x - 1;
 | 
			
		||||
    x = x | (x >> 1);
 | 
			
		||||
    x = x | (x >> 2);
 | 
			
		||||
    x = x | (x >> 4);
 | 
			
		||||
    x = x | (x >> 8);
 | 
			
		||||
    x = x | (x >>16);
 | 
			
		||||
    return x + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
 | 
			
		||||
        void** pBase,int* pOffset, int* pFd, int format)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
 | 
			
		||||
    *pBase = 0;
 | 
			
		||||
    *pOffset = 0;
 | 
			
		||||
    *pFd = -1;
 | 
			
		||||
 | 
			
		||||
    int err, offset = 0;
 | 
			
		||||
    int openFlags = get_open_flags(usage);
 | 
			
		||||
    const char *device;
 | 
			
		||||
    if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
 | 
			
		||||
        device = DEVICE_PMEM_ADSP;
 | 
			
		||||
    } else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) {
 | 
			
		||||
        device = DEVICE_PMEM_SMIPOOL;
 | 
			
		||||
    } else if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
 | 
			
		||||
               (usage & GRALLOC_USAGE_PROTECTED)) {
 | 
			
		||||
        int tempFd = deps.open(DEVICE_PMEM_SMIPOOL, openFlags, 0);
 | 
			
		||||
        if (tempFd < 0) {
 | 
			
		||||
            device = DEVICE_PMEM_ADSP;
 | 
			
		||||
        } else {
 | 
			
		||||
            close(tempFd);
 | 
			
		||||
            device = DEVICE_PMEM_SMIPOOL;
 | 
			
		||||
        }
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    size += offset;
 | 
			
		||||
    void *base = mmap(0, size, PROT_READ| PROT_WRITE,
 | 
			
		||||
            MAP_SHARED, fd, 0);
 | 
			
		||||
    *pBase = base;
 | 
			
		||||
    if(base == MAP_FAILED) {
 | 
			
		||||
        LOGD("%s: Failed to map memory in the client: %s",
 | 
			
		||||
                mPmemDev, strerror(errno));
 | 
			
		||||
        err = -errno;
 | 
			
		||||
    } else {
 | 
			
		||||
        LOGE("Invalid device");
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
        LOGD("%s: Mapped buffer base:%p size:%d offset:%d fd:%d",
 | 
			
		||||
                mPmemDev, base, size, offset, fd);
 | 
			
		||||
    }
 | 
			
		||||
    return err;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAlloc::unmap_buffer(void *base, size_t size, int offset)
 | 
			
		||||
{
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    //pmem hack
 | 
			
		||||
    base = (void*)(intptr_t(base) - offset);
 | 
			
		||||
    size += offset;
 | 
			
		||||
    LOGD("%s: Unmapping buffer base:%p size:%d offset:%d",
 | 
			
		||||
            mPmemDev , base, size, offset);
 | 
			
		||||
    if (munmap(base, size) < 0) {
 | 
			
		||||
        LOGE("Could not unmap %s", strerror(errno));
 | 
			
		||||
        err = -errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int fd = deps.open(device, openFlags, 0);
 | 
			
		||||
   return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemUserspaceAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    return cleanPmem(base, size, offset, fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//-------------- PmemKernelAlloc-----------------------//
 | 
			
		||||
 | 
			
		||||
PmemKernelAlloc::PmemKernelAlloc(const char* pmemdev) :
 | 
			
		||||
    mPmemDev(pmemdev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemKernelAlloc::~PmemKernelAlloc()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemKernelAlloc::alloc_buffer(alloc_data& data)
 | 
			
		||||
{
 | 
			
		||||
    int err, offset = 0;
 | 
			
		||||
    int openFlags = getOpenFlags(data.uncached);
 | 
			
		||||
    int size = data.size;
 | 
			
		||||
 | 
			
		||||
    int fd = open(mPmemDev, openFlags, 0);
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        err = -deps.getErrno();
 | 
			
		||||
        END_FUNC;
 | 
			
		||||
        LOGE("Error opening %s", device);
 | 
			
		||||
        err = -errno;
 | 
			
		||||
        LOGE("%s: Error opening %s", __FUNCTION__, mPmemDev);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The size should already be page aligned, now round it up to a power of 2.
 | 
			
		||||
    //size = clp2(size);
 | 
			
		||||
 | 
			
		||||
    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
 | 
			
		||||
    if (data.align == 8192) {
 | 
			
		||||
        // Tile format buffers need physical alignment to 8K
 | 
			
		||||
        err = deps.alignPmem(fd, size, 8192);
 | 
			
		||||
        // Default page size does not need this ioctl
 | 
			
		||||
        err = alignPmem(fd, size, 8192);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            LOGE("alignPmem failed");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 | 
			
		||||
    void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 | 
			
		||||
    if (base == MAP_FAILED) {
 | 
			
		||||
        LOGE("%s: failed to map pmem fd: %s", device,
 | 
			
		||||
             strerror(deps.getErrno()));
 | 
			
		||||
        err = -deps.getErrno();
 | 
			
		||||
        deps.close(fd);
 | 
			
		||||
        END_FUNC;
 | 
			
		||||
        LOGE("%s: failed to map pmem fd: %s", mPmemDev,
 | 
			
		||||
                strerror(errno));
 | 
			
		||||
        err = -errno;
 | 
			
		||||
        close(fd);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
    memset(base, 0, size);
 | 
			
		||||
    //XXX: Flush here if cached
 | 
			
		||||
    data.base = base;
 | 
			
		||||
    data.offset = 0;
 | 
			
		||||
    data.fd = fd;
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemKernelAlloc::free_buffer(void* base, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    int err =  unmap_buffer(base, size, offset);
 | 
			
		||||
    close(fd);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PmemKernelAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    void *base = mmap(0, size, PROT_READ| PROT_WRITE,
 | 
			
		||||
            MAP_SHARED, fd, 0);
 | 
			
		||||
    *pBase = base;
 | 
			
		||||
    *pOffset = 0;
 | 
			
		||||
    *pFd = fd;
 | 
			
		||||
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base,
 | 
			
		||||
                                          int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    // The size should already be page aligned,
 | 
			
		||||
    // now round it up to a power of 2
 | 
			
		||||
    // like we did when allocating.
 | 
			
		||||
    //size = clp2(size);
 | 
			
		||||
 | 
			
		||||
    int err = deps.munmap(base, size);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        err = deps.getErrno();
 | 
			
		||||
        LOGW("error unmapping pmem fd: %s", strerror(err));
 | 
			
		||||
        return -err;
 | 
			
		||||
    if(base == MAP_FAILED) {
 | 
			
		||||
        LOGD("%s: Failed to map memory in the client: %s",
 | 
			
		||||
                __func__, strerror(errno));
 | 
			
		||||
        err = -errno;
 | 
			
		||||
    } else {
 | 
			
		||||
        LOGD("%s: Mapped %d bytes", __func__, size);
 | 
			
		||||
    }
 | 
			
		||||
    return err;
 | 
			
		||||
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PmemKernelAllocator::Deps::~Deps()
 | 
			
		||||
int PmemKernelAlloc::unmap_buffer(void *base, size_t size, int offset)
 | 
			
		||||
{
 | 
			
		||||
    BEGIN_FUNC;
 | 
			
		||||
    END_FUNC;
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    munmap(base, size);
 | 
			
		||||
    if (err < 0) {
 | 
			
		||||
        err = -errno;
 | 
			
		||||
        LOGW("Error unmapping pmem fd: %s", strerror(err));
 | 
			
		||||
    }
 | 
			
		||||
    return err;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
int PmemKernelAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
 | 
			
		||||
{
 | 
			
		||||
    return cleanPmem(base, size, offset, fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,161 +1,106 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are
 | 
			
		||||
 * met:
 | 
			
		||||
 *   * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *     notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   * Redistributions in binary form must reproduce the above
 | 
			
		||||
 *     copyright notice, this list of conditions and the following
 | 
			
		||||
 *     disclaimer in the documentation and/or other materials provided
 | 
			
		||||
 *     with the distribution.
 | 
			
		||||
 *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
 | 
			
		||||
 *     contributors may be used to endorse or promote products derived
 | 
			
		||||
 *     from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 | 
			
		||||
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
			
		||||
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 | 
			
		||||
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 | 
			
		||||
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GRALLOC_QSD8K_PMEMALLOC_H
 | 
			
		||||
#define GRALLOC_QSD8K_PMEMALLOC_H
 | 
			
		||||
#ifndef GRALLOC_PMEMALLOC_H
 | 
			
		||||
#define GRALLOC_PMEMALLOC_H
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <linux/ion.h>
 | 
			
		||||
#include <utils/RefBase.h>
 | 
			
		||||
#include "memalloc.h"
 | 
			
		||||
 | 
			
		||||
namespace gralloc {
 | 
			
		||||
    class PmemUserspaceAlloc : public IMemAlloc  {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An interface to the PMEM allocators.
 | 
			
		||||
 */
 | 
			
		||||
class PmemAllocator {
 | 
			
		||||
        public:
 | 
			
		||||
            class Allocator: public android::RefBase {
 | 
			
		||||
                public:
 | 
			
		||||
                    virtual ~Allocator() {};
 | 
			
		||||
                    virtual ssize_t setSize(size_t size) = 0;
 | 
			
		||||
                    virtual size_t  size() const = 0;
 | 
			
		||||
                    virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
 | 
			
		||||
                    virtual ssize_t deallocate(size_t offset) = 0;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
            virtual int alloc_buffer(alloc_data& data);
 | 
			
		||||
 | 
			
		||||
    virtual ~PmemAllocator();
 | 
			
		||||
            virtual int free_buffer(void *base, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
    // Only valid after init_pmem_area() has completed successfully.
 | 
			
		||||
    virtual void* get_base_address() = 0;
 | 
			
		||||
            virtual int map_buffer(void **pBase, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
 | 
			
		||||
            int* pOffset, int* pFd, int format) = 0;
 | 
			
		||||
    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0;
 | 
			
		||||
};
 | 
			
		||||
            virtual int unmap_buffer(void *base, size_t size,
 | 
			
		||||
                    int offset);
 | 
			
		||||
 | 
			
		||||
            virtual int clean_buffer(void*base, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A PMEM allocator that allocates the entire pmem memory from the kernel and
 | 
			
		||||
 * then uses a user-space allocator to suballocate from that.  This requires
 | 
			
		||||
 * that the PMEM device driver have kernel allocation disabled.
 | 
			
		||||
 */
 | 
			
		||||
class PmemUserspaceAllocator: public PmemAllocator {
 | 
			
		||||
            PmemUserspaceAlloc();
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
            ~PmemUserspaceAlloc();
 | 
			
		||||
 | 
			
		||||
    class Deps {
 | 
			
		||||
     public:
 | 
			
		||||
        private:
 | 
			
		||||
            int mMasterFd;
 | 
			
		||||
            void* mMasterBase;
 | 
			
		||||
            const char* mPmemDev;
 | 
			
		||||
            android::sp<Allocator> mAllocator;
 | 
			
		||||
            pthread_mutex_t mLock;
 | 
			
		||||
            int init_pmem_area();
 | 
			
		||||
            int init_pmem_area_locked();
 | 
			
		||||
 | 
			
		||||
        class Allocator {
 | 
			
		||||
         public:
 | 
			
		||||
            virtual ~Allocator();
 | 
			
		||||
            virtual ssize_t setSize(size_t size) = 0;
 | 
			
		||||
            virtual size_t  size() const = 0;
 | 
			
		||||
            virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
 | 
			
		||||
            virtual ssize_t deallocate(size_t offset) = 0;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        virtual ~Deps();
 | 
			
		||||
 | 
			
		||||
        // pmem
 | 
			
		||||
        virtual size_t getPmemTotalSize(int fd, size_t* size) = 0;
 | 
			
		||||
        virtual int connectPmem(int fd, int master_fd) = 0;
 | 
			
		||||
        virtual int mapPmem(int fd, int offset, size_t size) = 0;
 | 
			
		||||
        virtual int unmapPmem(int fd, int offset, size_t size) = 0;
 | 
			
		||||
        virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) = 0;
 | 
			
		||||
 | 
			
		||||
        // C99
 | 
			
		||||
        virtual int getErrno() = 0;
 | 
			
		||||
 | 
			
		||||
        // POSIX
 | 
			
		||||
        virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
 | 
			
		||||
                off_t offset) = 0;
 | 
			
		||||
        virtual int open(const char* pathname, int flags, int mode) = 0;
 | 
			
		||||
        virtual int close(int fd) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev);
 | 
			
		||||
    virtual ~PmemUserspaceAllocator();
 | 
			
		||||
    class PmemKernelAlloc : public IMemAlloc  {
 | 
			
		||||
 | 
			
		||||
    // Only valid after init_pmem_area() has completed successfully.
 | 
			
		||||
    virtual void* get_base_address();
 | 
			
		||||
        public:
 | 
			
		||||
            virtual int alloc_buffer(alloc_data& data);
 | 
			
		||||
 | 
			
		||||
    virtual int init_pmem_area_locked();
 | 
			
		||||
    virtual int init_pmem_area();
 | 
			
		||||
    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
 | 
			
		||||
            int* pOffset, int* pFd, int format);
 | 
			
		||||
    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
 | 
			
		||||
            virtual int free_buffer(void *base, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
#ifndef ANDROID_OS
 | 
			
		||||
    // DO NOT USE: For testing purposes only.
 | 
			
		||||
    void set_master_values(int fd, void* base) {
 | 
			
		||||
        master_fd = fd;
 | 
			
		||||
        master_base = base;
 | 
			
		||||
    }
 | 
			
		||||
#endif // ANDROID_OS
 | 
			
		||||
            virtual int map_buffer(void **pBase, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
            virtual int unmap_buffer(void *base, size_t size,
 | 
			
		||||
                    int offset);
 | 
			
		||||
 | 
			
		||||
            virtual int clean_buffer(void*base, size_t size,
 | 
			
		||||
                    int offset, int fd);
 | 
			
		||||
 | 
			
		||||
            PmemKernelAlloc(const char* device);
 | 
			
		||||
 | 
			
		||||
            ~PmemKernelAlloc();
 | 
			
		||||
        private:
 | 
			
		||||
            const char* mPmemDev;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        MASTER_FD_INIT = -1,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Deps& deps;
 | 
			
		||||
    Deps::Allocator& allocator;
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_t lock;
 | 
			
		||||
    const char* pmemdev;
 | 
			
		||||
    int master_fd;
 | 
			
		||||
    void* master_base;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A PMEM allocator that allocates each individual allocation from the kernel
 | 
			
		||||
 * (using the kernel's allocator).  This requires the kernel driver for the
 | 
			
		||||
 * particular PMEM device being allocated from to support kernel allocation.
 | 
			
		||||
 */
 | 
			
		||||
class PmemKernelAllocator: public PmemAllocator {
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
 | 
			
		||||
    class Deps {
 | 
			
		||||
     public:
 | 
			
		||||
 | 
			
		||||
        virtual ~Deps();
 | 
			
		||||
 | 
			
		||||
        // C99
 | 
			
		||||
        virtual int getErrno() = 0;
 | 
			
		||||
 | 
			
		||||
        // POSIX
 | 
			
		||||
        virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
 | 
			
		||||
                off_t offset) = 0;
 | 
			
		||||
        virtual int munmap(void* start, size_t length) = 0;
 | 
			
		||||
        virtual int open(const char* pathname, int flags, int mode) = 0;
 | 
			
		||||
        virtual int close(int fd) = 0;
 | 
			
		||||
        virtual int alignPmem(int fd, size_t size, int align) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    PmemKernelAllocator(Deps& deps);
 | 
			
		||||
    virtual ~PmemKernelAllocator();
 | 
			
		||||
 | 
			
		||||
    // Only valid after init_pmem_area() has completed successfully.
 | 
			
		||||
    virtual void* get_base_address();
 | 
			
		||||
 | 
			
		||||
    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
 | 
			
		||||
            int* pOffset, int* pFd, int format);
 | 
			
		||||
    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
 | 
			
		||||
    Deps& deps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // GRALLOC_QSD8K_PMEMALLOC_H
 | 
			
		||||
}
 | 
			
		||||
#endif /* GRALLOC_PMEMALLOC_H */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user