blob: ee61f705133d56327934c4376b7e3465ade91f3c [file] [log] [blame]
/*
* Copyright (c) 2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file heap.cpp
//! \brief Implements functionalities pertaining to heaps.
//!
#include "heap.h"
Heap::Heap()
{
HEAP_FUNCTION_ENTER;
m_id = m_invalidId;
}
Heap::Heap(uint32_t id)
{
HEAP_FUNCTION_ENTER;
m_id = id;
}
Heap::~Heap()
{
HEAP_FUNCTION_ENTER;
if (m_osInterface != nullptr)
{
if (m_lockedHeap != nullptr)
{
m_osInterface->pfnUnlockResource(m_osInterface, m_resource);
}
if (!Mos_ResourceIsNull(m_resource))
{
m_osInterface->pfnFreeResource(m_osInterface, m_resource);
MOS_FreeMemory(m_resource);
}
}
}
MOS_STATUS Heap::RegisterOsInterface(PMOS_INTERFACE osInterface)
{
HEAP_FUNCTION_ENTER;
HEAP_CHK_NULL(osInterface);
m_osInterface = osInterface;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Heap::Allocate(uint32_t heapSize, bool keepLocked)
{
HEAP_FUNCTION_ENTER;
if (heapSize == 0)
{
HEAP_ASSERTMESSAGE("No size requested for heap allocation!");
return MOS_STATUS_INVALID_PARAMETER;
}
if (m_resource != nullptr)
{
HEAP_ASSERTMESSAGE("A heap has already been allocated!");
return MOS_STATUS_INVALID_PARAMETER;
}
m_resource = (PMOS_RESOURCE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE));
HEAP_CHK_NULL(m_resource);
HEAP_CHK_NULL(m_osInterface);
MOS_ALLOC_GFXRES_PARAMS allocParams;
memset(&allocParams, 0, sizeof(allocParams));
allocParams.Type = MOS_GFXRES_BUFFER;
allocParams.TileType = MOS_TILE_LINEAR;
allocParams.Format = Format_Buffer;
allocParams.dwBytes = heapSize;
allocParams.pBufName = "Heap";
HEAP_CHK_STATUS(m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParams,
m_resource));
// explicit set to skip resource sync, heap resource should be used block by block
// driver should ensure non concurrent access the same block
HEAP_CHK_STATUS(m_osInterface->pfnSkipResourceSync(m_resource));
if (keepLocked)
{
m_lockedHeap = Lock();
HEAP_CHK_NULL(m_lockedHeap);
m_keepLocked = keepLocked;
}
m_size = heapSize;
m_freeSpace = m_size;
return MOS_STATUS_SUCCESS;
}
uint8_t* Heap::Lock()
{
HEAP_FUNCTION_ENTER_VERBOSE;
if (m_keepLocked)
{
return m_lockedHeap;
}
if (m_osInterface == nullptr)
{
HEAP_ASSERTMESSAGE("Invalid m_osInterface(nullptr)");
return nullptr;
}
MOS_LOCK_PARAMS lockParams;
memset(&lockParams, 0, sizeof(lockParams));
lockParams.WriteOnly = 1;
lockParams.NoOverWrite = 1;
lockParams.Uncached = 1;
uint8_t* pLockedResource =
(uint8_t*)m_osInterface->pfnLockResource(m_osInterface, m_resource, &lockParams);
return pLockedResource;
}
MOS_STATUS Heap::Dump()
{
return MOS_STATUS_UNIMPLEMENTED;
}
MOS_STATUS Heap::AdjustFreeSpace(uint32_t addedSpace)
{
HEAP_FUNCTION_ENTER_VERBOSE;
if (addedSpace + m_freeSpace > m_size ||
m_usedSpace < addedSpace)
{
HEAP_ASSERTMESSAGE("Provided space will not fit in the heap");
return MOS_STATUS_INVALID_PARAMETER;
}
m_freeSpace += addedSpace;
m_usedSpace -= addedSpace;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Heap::AdjustUsedSpace(uint32_t addedSpace)
{
HEAP_FUNCTION_ENTER_VERBOSE;
if (addedSpace + m_usedSpace > m_size ||
m_freeSpace < addedSpace)
{
HEAP_ASSERTMESSAGE("Provided space will not fit in the heap");
return MOS_STATUS_INVALID_PARAMETER;
}
if (m_freeInProgress)
{
HEAP_ASSERTMESSAGE("Heap is in the process of being freed, cannot add space as used");
return MOS_STATUS_INVALID_PARAMETER;
}
m_freeSpace -= addedSpace;
m_usedSpace += addedSpace;
return MOS_STATUS_SUCCESS;
}