blob: 5e45106182569e06ff3a78990e35f8801536ed5a [file]
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
/*++
Module Name:
palobjbase.cpp
Abstract:
PAL object base class
--*/
#include "palobjbase.hpp"
#include "pal/malloc.hpp"
#include "pal/dbgmsg.h"
SET_DEFAULT_DEBUG_CHANNEL(PAL);
using namespace CorUnix;
CObjectType* CObjectType::s_rgotIdMapping[ObjectTypeIdCount];
/*++
Function:
CPalObjectBase::Initialize
Performs possibly-failing initialization for a newly-constructed
object
Parameters:
pthr -- thread data for calling thread
poa -- the object attributes (e.g., name) for the object
--*/
PAL_ERROR
CPalObjectBase::Initialize(
CPalThread *pthr,
CObjectAttributes *poa
)
{
PAL_ERROR palError = NO_ERROR;
_ASSERTE(NULL != pthr);
_ASSERTE(NULL != poa);
ENTRY("CPalObjectBase::Initialize"
"(this = %p, pthr = %p, poa = %p)\n",
this,
pthr,
poa
);
if (0 != m_pot->GetImmutableDataSize())
{
m_pvImmutableData = InternalMalloc(m_pot->GetImmutableDataSize());
if (NULL != m_pvImmutableData)
{
ZeroMemory(m_pvImmutableData, m_pot->GetImmutableDataSize());
}
else
{
ERROR("Unable to allocate immutable data\n");
palError = ERROR_OUTOFMEMORY;
goto IntializeExit;
}
}
if (0 != m_pot->GetProcessLocalDataSize())
{
palError = m_sdlLocalData.Initialize();
if (NO_ERROR != palError)
{
ERROR("Unable to initialize local data lock!\n");
goto IntializeExit;
}
m_pvLocalData = InternalMalloc(m_pot->GetProcessLocalDataSize());
if (NULL != m_pvLocalData)
{
ZeroMemory(m_pvLocalData, m_pot->GetProcessLocalDataSize());
}
else
{
ERROR("Unable to allocate local data\n");
palError = ERROR_OUTOFMEMORY;
goto IntializeExit;
}
}
if (0 != poa->sObjectName.GetStringLength())
{
palError = m_oa.sObjectName.CopyString(&poa->sObjectName);
}
IntializeExit:
LOGEXIT("CPalObjectBase::Initialize returns %d\n", palError);
return palError;
}
/*++
Function:
CPalObjectBase::GetObjectType
Returns the type of the object
--*/
CObjectType *
CPalObjectBase::GetObjectType(
VOID
)
{
ENTRY("CPalObjectBase::GetObjectType(this = %p)\n", this);
LOGEXIT("CPalObjectBase::GetObjectType returns %p\n", m_pot);
return m_pot;
}
/*++
Function:
CPalObjectBase::GetObjectAttributes
Returns the attributes of the object
--*/
CObjectAttributes *
CPalObjectBase::GetObjectAttributes(
VOID
)
{
ENTRY("CPalObjectBase::GetObjectAttributes(this = %p)\n", this);
LOGEXIT("CPalObjectBase::GetObjectAttributes returns %p\n", &m_oa);
return &m_oa;
}
/*++
Function:
CPalObjectBase::GetImmutableData
Provides the caller access to the object's immutable data (if any)
Parameters:
ppvImmutableData -- on success, receives a pointer to the object's
immutable data
--*/
PAL_ERROR
CPalObjectBase::GetImmutableData(
void **ppvImmutableData // OUT
)
{
_ASSERTE(NULL != ppvImmutableData);
ENTRY("CPalObjectBase::GetImmutableData"
"(this = %p, ppvImmutableData = %p)\n",
this,
ppvImmutableData
);
_ASSERTE(0 < m_pot->GetImmutableDataSize());
*ppvImmutableData = m_pvImmutableData;
LOGEXIT("CPalObjectBase::GetImmutableData returns %d\n", NO_ERROR);
return NO_ERROR;
}
/*++
Function:
CPalObjectBase::GetProcessLocalData
Provides the caller access to the object's local data (if any)
Parameters:
pthr -- thread data for calling thread
eLockRequest -- specifies if the caller desires a read lock or a
write lock on the data (currently ignored)
ppDataLock -- on success, receives a pointer to the data lock instance
for the local data
ppvProcssLocalData -- on success, receives a pointer to the local data
--*/
PAL_ERROR
CPalObjectBase::GetProcessLocalData(
CPalThread *pthr,
LockType eLockRequest,
IDataLock **ppDataLock, // OUT
void **ppvProcessLocalData // OUT
)
{
_ASSERTE(NULL != pthr);
_ASSERTE(ReadLock == eLockRequest || WriteLock == eLockRequest);
_ASSERTE(NULL != ppDataLock);
_ASSERTE(NULL != ppvProcessLocalData);
ENTRY("CPalObjectBase::GetProcessLocalData"
"(this = %p, pthr = %p, eLockRequest = %d, ppDataLock = %p,"
" ppvProcessLocalData = %p)\n",
this,
pthr,
eLockRequest,
ppDataLock,
ppvProcessLocalData
);
_ASSERTE(0 < m_pot->GetProcessLocalDataSize());
m_sdlLocalData.AcquireLock(pthr, ppDataLock);
*ppvProcessLocalData = m_pvLocalData;
LOGEXIT("CPalObjectBase::GetProcessLocalData returns %d\n", NO_ERROR);
return NO_ERROR;
}
/*++
Function:
CPalObjectBase::AddReference
Increments the object's reference count. The updated count is returned
for diagnostic purposes only
--*/
DWORD
CPalObjectBase::AddReference(
void
)
{
LONG lRefCount;
ENTRY("CPalObjectBase::AddReference(this = %p)\n", this);
_ASSERTE(m_lRefCount > 0);
lRefCount = InterlockedIncrement(&m_lRefCount);
LOGEXIT("CPalObjectBase::AddReference returns %d\n", lRefCount);
return lRefCount;
}
/*++
Function:
CPalObjectBase::ReleaseReference
Decrements the object's reference count. The updated count is returned
for diagnostic purposes only
Parameters:
pthr -- thread data for calling thread
--*/
DWORD
CPalObjectBase::ReleaseReference(
CPalThread *pthr
)
{
LONG lRefCount;
_ASSERTE(NULL != pthr);
ENTRY("CPalObjectBase::ReleaseReference"
"(this = %p, pthr = %p)\n",
this,
pthr
);
AcquireObjectDestructionLock(pthr);
_ASSERTE(m_lRefCount > 0);
//
// Even though object destruction takes place under a lock
// we still need to use an interlocked decrement, as AddRef
// operates lock free
//
lRefCount = InterlockedDecrement(&m_lRefCount);
if (0 == lRefCount)
{
bool fCleanupSharedState = ReleaseObjectDestructionLock(pthr, TRUE);
//
// We need to do two things with the calling thread data here:
// 1) store it in m_pthrCleanup so it is available to the destructors
// 2) Add a reference to it before starting any cleanup, and release
// that reference afterwords.
//
// Step 2 is necessary when we're cleaning up the thread object that
// represents the calling thread -- it ensures that the thread data
// is available throughout the entire cleanup process.
//
m_pthrCleanup = pthr;
pthr->AddThreadReference();
if (NULL != m_pot->GetObjectCleanupRoutine())
{
(*m_pot->GetObjectCleanupRoutine())(
pthr,
static_cast<IPalObject*>(this),
FALSE,
fCleanupSharedState
);
}
InternalDelete(this);
pthr->ReleaseThreadReference();
}
else
{
ReleaseObjectDestructionLock(pthr, FALSE);
}
LOGEXIT("CPalObjectBase::ReleaseReference returns %d\n", lRefCount);
return lRefCount;
}
/*++
Function:
CPalObjectBase::~CPalObjectBase
Object destructor
--*/
CPalObjectBase::~CPalObjectBase()
{
ENTRY("CPalObjectBase::~CPalObjectBase(this = %p)\n", this);
if (NULL != m_pvImmutableData)
{
InternalFree(m_pvImmutableData);
}
if (NULL != m_pvLocalData)
{
InternalFree(m_pvLocalData);
}
if (NULL != m_oa.sObjectName.GetString())
{
m_oa.sObjectName.FreeBuffer();
}
LOGEXIT("CPalObjectBase::~CPalObjectBase\n");
}