blob: e31352389d2baf4b17e69a04a56ed44c7e8862a6 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
/*! \file oscl_mem_imp.cpp
\brief This file contains the implementation of advanced memory APIs
*/
#include "oscl_mem.h"
//////////////////////
// OsclMem
//////////////////////
OSCL_EXPORT_REF void OsclMem::Init()
{
#if(!OSCL_BYPASS_MEMMGT)
OsclMemGlobalAuditObject::createGlobalMemAuditObject();
#endif
}
OSCL_EXPORT_REF void OsclMem::Cleanup()
{
#if(!OSCL_BYPASS_MEMMGT)
OsclMemGlobalAuditObject::deleteGlobalMemAuditObject();
#endif
}
//////////////////////
// OsclMemInit
//////////////////////
OSCL_EXPORT_REF void OsclMemInit(OsclAuditCB & auditCB)
{
#if(!OSCL_BYPASS_MEMMGT)
auditCB.pStatsNode = NULL;
auditCB.pAudit = (OsclMemGlobalAuditObject::getGlobalMemAuditObject());
#else
OSCL_UNUSED_ARG(auditCB);
#endif
}
#if(!OSCL_BYPASS_MEMMGT)
#include "oscl_mem_audit.h"
#include "oscl_singleton.h"
//////////////////////
// OsclMemGlobalAuditObject
//////////////////////
OSCL_EXPORT_REF OsclMemGlobalAuditObject::audit_type* OsclMemGlobalAuditObject::getGlobalMemAuditObject()
{
return (audit_type*)OsclSingletonRegistryEx::getInstance(OSCL_SINGLETON_ID_OSCLMEM);
}
void OsclMemGlobalAuditObject::createGlobalMemAuditObject()
{
audit_type* audit = (audit_type*)OsclSingletonRegistryEx::lockAndGetInstance(OSCL_SINGLETON_ID_OSCLMEM);
if (audit)
{
audit->iRefCount++;
}
else
{
OsclAny *ptr = _oscl_malloc(sizeof(audit_type));
if (!ptr)
{
OsclSingletonRegistryEx::registerInstanceAndUnlock(audit, OSCL_SINGLETON_ID_OSCLMEM);
OsclError::Leave(OsclErrNoMemory);
return;
}
audit = OSCL_PLACEMENT_NEW(ptr, audit_type());
}
OsclSingletonRegistryEx::registerInstanceAndUnlock(audit, OSCL_SINGLETON_ID_OSCLMEM);
}
void OsclMemGlobalAuditObject::deleteGlobalMemAuditObject()
{
audit_type* audit = (audit_type*)OsclSingletonRegistryEx::lockAndGetInstance(OSCL_SINGLETON_ID_OSCLMEM);
if (!audit)
{
OsclSingletonRegistryEx::registerInstanceAndUnlock(audit, OSCL_SINGLETON_ID_OSCLMEM);
OsclError::Leave(OsclErrNotInstalled);
return;
}
audit->iRefCount--;
if (audit->iRefCount == 0)
{
audit->~OsclMemAudit();
_oscl_free(audit);
audit = NULL;
}
OsclSingletonRegistryEx::registerInstanceAndUnlock(audit, OSCL_SINGLETON_ID_OSCLMEM);
}
//////////////////////
// Default new/malloc
//////////////////////
OSCL_EXPORT_REF void* _oscl_default_audit_new(size_t nBytes, const char * file_name, const int line_num)
{
//get global mem audit object.
OsclAuditCB audit;
OsclMemInit(audit);
return _oscl_audit_new(nBytes, audit, file_name, line_num);
}
OSCL_EXPORT_REF void* _oscl_default_audit_malloc(size_t nBytes, const char * file_name, const int line_num)
{
//get global mem audit object.
OsclAuditCB audit;
OsclMemInit(audit);
return _oscl_audit_malloc(nBytes, audit, file_name, line_num);
}
OSCL_EXPORT_REF void* _oscl_default_audit_calloc(size_t num, size_t nBytes, const char * file_name, const int line_num)
{
//get global mem audit object.
OsclAuditCB audit;
OsclMemInit(audit);
return _oscl_audit_calloc(num, nBytes, audit, file_name, line_num);
}
OSCL_EXPORT_REF void* _oscl_default_audit_realloc(void* in_ptr, size_t nBytes, const char * file_name, const int line_num)
{
//get global mem audit object.
OsclAuditCB audit;
OsclMemInit(audit);
return _oscl_audit_realloc(in_ptr, nBytes, audit, file_name, line_num);
}
//////////////////////
// Audit new/malloc
//////////////////////
OSCL_EXPORT_REF void* _oscl_audit_new(size_t nBytes, OsclAuditCB & auditCB, const char * file_name, const int line_num)
{
void * pTmp = auditCB.pAudit->MM_allocate(auditCB.pStatsNode, nBytes, file_name, line_num);
if (!pTmp)
OsclError::LeaveIfNull(pTmp);
return pTmp;
}
OSCL_EXPORT_REF void* _oscl_audit_malloc(size_t nBytes, OsclAuditCB & auditCB, const char * file_name, const int line_num)
{
return auditCB.pAudit->MM_allocate(auditCB.pStatsNode, nBytes, file_name, line_num);
}
OSCL_EXPORT_REF void* _oscl_audit_calloc(size_t num, size_t nBytes, OsclAuditCB & auditCB, const char * file_name, const int line_num)
{
size_t size = num * nBytes;
void* ptr = _oscl_audit_malloc(size, auditCB, file_name, line_num);
if (ptr)
oscl_memset(ptr, 0, size);
//note: return pointer can be null.
return ptr;
}
OSCL_EXPORT_REF void* _oscl_audit_realloc(void* in_ptr, size_t nBytes, OsclAuditCB & auditCB, const char * file_name, const int line_num)
{
if (nBytes > 0)
{
//allocate new space
void* ptr = _oscl_audit_malloc(nBytes, auditCB, file_name, line_num);
if (in_ptr && ptr)
{
//copy current contents to new space.
//note: the getSize call leaves if it's a bad pointer.
//just propagate the leave to the caller.
if (MM_Audit_Imp::getSize(in_ptr) > MM_Audit_Imp::getSize(ptr))
{
oscl_memcpy(ptr, in_ptr, MM_Audit_Imp::getSize(ptr));
}
else
{
oscl_memcpy(ptr, in_ptr, MM_Audit_Imp::getSize(in_ptr));
}
//free original space.
_oscl_audit_free(in_ptr);
}
else if (in_ptr)
{
return in_ptr;
}
//note: return pointer can be null.
return ptr;
}
else
{
_oscl_audit_free(in_ptr);
return NULL;
}
}
//////////////
// Free
//////////////
OSCL_EXPORT_REF void _oscl_audit_free(void *p)
{
//always free from the root node-- global audit object.
//Get the audit root from within the alloc block rather
//than from TLS, since we can't be sure this call is
//in the same thread as the allocation.
OsclMemAudit *pAuditRoot = MM_Audit_Imp::getAuditRoot(p) ;
if (pAuditRoot)
{
pAuditRoot->MM_deallocate(p);
}
else
{//bad or corrupt block?
OSCL_LEAVE(OsclErrArgument);
}
}
#else
OSCL_EXPORT_REF void* _oscl_default_new(size_t nBytes)
{
void * pTmp = _oscl_malloc(nBytes);
if (!pTmp)
OsclError::LeaveIfNull(pTmp);
return pTmp;
}
#endif //OSCL_BYPASS_MEMMGT