/*
 * Copyright (C) 2017 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.
 */

#include "guest/vsoc/lib/gralloc_region_view.h"

#include <common/vsoc/lib/lock_guard.h>
#include <log/log.h>
#include <sys/types.h>
#include <uapi/vsoc_shm.h>
#include <atomic>

using vsoc::gralloc::GrallocRegionView;
using vsoc::layout::gralloc::BufferEntry;
using vsoc::layout::gralloc::GrallocBufferLayout;
using vsoc::layout::gralloc::GrallocManagerLayout;

namespace {
template <typename T>
inline T gralloc_align(T val) {
  return (val + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
}

// Use the thread id to identify the original creator of a buffer.
inline uint32_t gralloc_owned_value() {
  return gettid();
}

}  // namespace

bool GrallocRegionView::Open() {
  if (!vsoc::ManagerRegionView<GrallocRegionView, GrallocManagerLayout>::Open()) {
    return false;
  }
  std::shared_ptr<vsoc::RegionControl> managed_region =
      vsoc::RegionControl::Open(
          GrallocManagerLayout::ManagedRegion::region_name);
  if (!managed_region) {
    LOG_FATAL("Unable to open managed region");
    return false;
  }
  offset_of_buffer_memory_ = gralloc_align<uint32_t>(
      managed_region->region_desc().offset_of_region_data);
  total_buffer_memory_ =
      managed_region->region_size() - offset_of_buffer_memory_;

  // TODO(jemoreira): Handle the case of unexpected values in the region.
  return true;
}

int GrallocRegionView::AllocateBuffer(size_t size, uint32_t* begin_offset) {
  size = gralloc_align<size_t>(size);
  // Cache the value of buffer_count in shared memory.
  uint32_t buffer_count_local = 0;
  {
    vsoc::LockGuard<vsoc::layout::GuestLock>(&data()->new_buffer_lock);
    buffer_count_local = data()->buffer_count;
  }
  // Find a free buffer entry of the appropriate size.
  for (uint32_t idx = 0; idx < buffer_count_local; ++idx) {
    BufferEntry& entry = data()->buffers_table[idx];
    if (entry.owned_by == VSOC_REGION_FREE && entry.buffer_size() == size) {
      int fd = control_->CreateFdScopedPermission(
          GrallocManagerLayout::ManagedRegion::region_name,
          pointer_to_region_offset(&entry.owned_by),
          gralloc_owned_value(),
          entry.buffer_begin,
          entry.buffer_end);
      if (fd >= 0) {
        if (begin_offset) {
          *begin_offset = entry.buffer_begin;
        }
        return fd;
      }
    }
  }

  // We couldn't find any suitable buffer, create one
  {
    vsoc::LockGuard<vsoc::layout::GuestLock>(&data()->new_buffer_lock);
    // don't use the cached value here!!!
    uint32_t idx = data()->buffer_count;
    if (pointer_to_region_offset(&data()->buffers_table[idx + 1]) >
        control_->region_size()) {
      ALOGE(
          "Out of memory in gralloc_manager (total: %d, used: %d, "
          "requested: %d)",
          static_cast<int>(control_->region_size()),
          static_cast<int>(
              pointer_to_region_offset(&data()->buffers_table[idx])),
          static_cast<int>(sizeof(data()->buffers_table[idx])));
      return -ENOMEM;
    }
    if (total_buffer_memory_ - data()->allocated_buffer_memory < size) {
      ALOGE(
          "Out of memory in gralloc_memory (total: %d, used: %d, requested: %d)",
          static_cast<int>(total_buffer_memory_),
          static_cast<int>(data()->allocated_buffer_memory),
          static_cast<int>(size));
      return -ENOMEM;
    }
    // Initialize the buffer entry and acquire ownership
    // Do it before increasing buffer_count so that another thread looking for
    // free entries doesn't find this one
    BufferEntry& new_entry = data()->buffers_table[idx];
    new_entry.buffer_begin =
        offset_of_buffer_memory_ + data()->allocated_buffer_memory;
    data()->allocated_buffer_memory += size;
    new_entry.buffer_end = new_entry.buffer_begin + size;
    int fd = control_->CreateFdScopedPermission(
        GrallocManagerLayout::ManagedRegion::region_name,
        pointer_to_region_offset(&new_entry.owned_by),
        gralloc_owned_value(),
        new_entry.buffer_begin,
        new_entry.buffer_end);
    if (fd < 0) {
      LOG_FATAL(
          "Unexpected error while creating fd scoped permission over "
          "uncontested memory: %s",
          strerror(-fd));
      return fd;
    }
    // Increment buffer_count now that the entry can't be taken from us
    data()->buffer_count++;
    if (begin_offset) {
      *begin_offset = new_entry.buffer_begin;
    }
    return fd;
  }
}
