/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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.
 */

//#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 <cutils/log.h>
#include <cutils/ashmem.h>

#include "gralloc_priv.h"
#include "pmemalloc.h"


#define BEGIN_FUNC ALOGV("%s begin", __PRETTY_FUNCTION__)
#define END_FUNC ALOGV("%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()
{
    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;
    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) {
            ALOGE("%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) {
            ALOGE("%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 {
        ALOGE("%s: failed to open pmem device: %s", pmemdev,
                strerror(deps.getErrno()));
        err = -deps.getErrno();
    }
    END_FUNC;
    return err;
}


int PmemUserspaceAllocator::init_pmem_area()
{
    BEGIN_FUNC;
    pthread_mutex_lock(&lock);
    int err = master_fd;
    if (err == MASTER_FD_INIT) {
        // first time, try to initialize pmem
        err = init_pmem_area_locked();
        if (err) {
            ALOGE("%s: failed to initialize pmem area", pmemdev);
            master_fd = err;
        }
    } else if (err < 0) {
        // pmem couldn't be initialized, never use it
    } else {
        // pmem OK
        err = 0;
    }
    pthread_mutex_unlock(&lock);
    END_FUNC;
    return err;
}


int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
        void** pBase, int* pOffset, int* pFd)
{
    BEGIN_FUNC;
    int err = init_pmem_area();
    if (err == 0) {
        void* base = master_base;
        int offset = allocator.allocate(size);
        if (offset < 0) {
            // no more pmem memory
            ALOGE("%s: no more pmem available", pmemdev);
            err = -ENOMEM;
        } else {
            int openFlags = get_open_flags(usage);

            //ALOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset);

            // now create the "sub-heap"
            int fd = deps.open(pmemdev, openFlags, 0);
            err = fd < 0 ? fd : 0;

            // and connect to it
            if (err == 0)
                err = deps.connectPmem(fd, master_fd);

            // and make it available to the client process
            if (err == 0)
                err = deps.mapPmem(fd, offset, size);

            if (err < 0) {
                ALOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev,
                        err);
                err = -deps.getErrno();
                deps.close(fd);
                allocator.deallocate(offset);
                fd = -1;
            } else {
                ALOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size);
                memset((char*)base + offset, 0, size);
                *pBase = base;
                *pOffset = offset;
                *pFd = fd;
            }
            //ALOGD_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)
{
    BEGIN_FUNC;
    int err = 0;
    if (fd >= 0) {
        int err = deps.unmapPmem(fd, offset, size);
        ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, "
                "sub.size=%u", strerror(deps.getErrno()), 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);
        }
    }
    END_FUNC;
    return err;
}

PmemUserspaceAllocator::Deps::Allocator::~Allocator()
{
    BEGIN_FUNC;
    END_FUNC;
}

PmemUserspaceAllocator::Deps::~Deps()
{
    BEGIN_FUNC;
    END_FUNC;
}

PmemKernelAllocator::PmemKernelAllocator(Deps& deps, const char* pmemdev):
    deps(deps),
    pmemdev(pmemdev)
{
    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)
{
    BEGIN_FUNC;

    *pBase = 0;
    *pOffset = 0;
    *pFd = -1;

    int err;
    int openFlags = get_open_flags(usage);
    int fd = deps.open(pmemdev, openFlags, 0);
    if (fd < 0) {
        err = -deps.getErrno();
        END_FUNC;
        return err;
    }

    // The size should already be page aligned, now round it up to a power of 2.
    size = clp2(size);

    void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (base == MAP_FAILED) {
        ALOGE("%s: failed to map pmem fd: %s", pmemdev,
             strerror(deps.getErrno()));
        err = -deps.getErrno();
        deps.close(fd);
        END_FUNC;
        return err;
    }

    memset(base, 0, size);

    *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();
        ALOGW("%s: error unmapping pmem fd: %s", pmemdev, strerror(err));
        return -err;
    }
    END_FUNC;
    return 0;
}

PmemKernelAllocator::Deps::~Deps()
{
    BEGIN_FUNC;
    END_FUNC;
}
