aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/shared/external/src/UserAllocator.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/external/src/UserAllocator.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/shared/external/src/UserAllocator.cpp')
-rw-r--r--APEX_1.4/shared/external/src/UserAllocator.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/APEX_1.4/shared/external/src/UserAllocator.cpp b/APEX_1.4/shared/external/src/UserAllocator.cpp
new file mode 100644
index 00000000..e9343c4a
--- /dev/null
+++ b/APEX_1.4/shared/external/src/UserAllocator.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#include <stdio.h>
+#include "UserAllocator.h"
+
+#include "MemTracker.h"
+
+#include "PxAssert.h"
+
+#pragma warning(disable:4100 4152)
+
+#ifdef USE_MEM_TRACKER
+
+static const char* USERALLOCATOR = "UserAllocator";
+#endif
+
+/*============ UserPxAllocator ============*/
+
+#ifdef USE_MEM_TRACKER
+
+#include <windows.h>
+
+class MemMutex
+{
+public:
+ MemMutex(void);
+ ~MemMutex(void);
+
+public:
+ // Blocking Lock.
+ void Lock(void);
+
+ // Unlock.
+ void Unlock(void);
+
+private:
+ CRITICAL_SECTION m_Mutex;
+};
+
+//==================================================================================
+MemMutex::MemMutex(void)
+{
+ InitializeCriticalSection(&m_Mutex);
+}
+
+//==================================================================================
+MemMutex::~MemMutex(void)
+{
+ DeleteCriticalSection(&m_Mutex);
+}
+
+//==================================================================================
+// Blocking Lock.
+//==================================================================================
+void MemMutex::Lock(void)
+{
+ EnterCriticalSection(&m_Mutex);
+}
+
+//==================================================================================
+// Unlock.
+//==================================================================================
+void MemMutex::Unlock(void)
+{
+ LeaveCriticalSection(&m_Mutex);
+}
+
+static inline MemMutex& gMemMutex()
+{
+ static MemMutex sMemMutex;
+ return sMemMutex;
+}
+
+static size_t getThreadId(void)
+{
+ return GetCurrentThreadId();
+}
+
+static bool memoryReport(MEM_TRACKER::MemTracker *memTracker,MEM_TRACKER::MemoryReportFormat format,const char *fname,bool reportAllLeaks) // detect memory leaks and, if any, write out a report to the filename specified.
+{
+ bool ret = false;
+
+ size_t leakCount;
+ size_t leaked = memTracker->detectLeaks(leakCount);
+ if ( leaked )
+ {
+ uint32_t dataLen;
+ void *mem = memTracker->generateReport(format,fname,dataLen,reportAllLeaks);
+ if ( mem )
+ {
+ FILE *fph = fopen(fname,"wb");
+ fwrite(mem,dataLen,1,fph);
+ fclose(fph);
+ memTracker->releaseReportMemory(mem);
+ }
+ ret = true; // it leaked memory!
+ }
+ return ret;
+}
+
+class ScopedLock
+{
+public:
+ ScopedLock(MemMutex &mutex, bool enabled) : mMutex(mutex), mEnabled(enabled)
+ {
+ if (mEnabled) mMutex.Lock();
+ }
+ ~ScopedLock()
+ {
+ if (mEnabled) mMutex.Unlock();
+ }
+
+private:
+ ScopedLock();
+ ScopedLock(const ScopedLock&);
+ ScopedLock& operator=(const ScopedLock&);
+
+ MemMutex& mMutex;
+ bool mEnabled;
+};
+
+#define SCOPED_TRACKER_LOCK_IF(USE_TRACKER) ScopedLock lock(gMemMutex(), (USE_TRACKER))
+#define TRACKER_CALL_IF(USE_TRACKER, CALL) if ((USE_TRACKER)) { (CALL); }
+
+void releaseAndReset(MEM_TRACKER::MemTracker*& memTracker)
+{
+ MEM_TRACKER::releaseMemTracker(memTracker);
+ memTracker = NULL;
+}
+
+#else
+
+#define SCOPED_TRACKER_LOCK_IF(USE_TRACKER)
+#define TRACKER_CALL_IF(USE_TRACKER, CALL)
+
+#endif
+
+int UserPxAllocator::gMemoryTrackerClients = 0;
+MEM_TRACKER::MemTracker *UserPxAllocator::mMemoryTracker=NULL;
+
+unsigned int UserPxAllocator::mNumAllocations = 0;
+unsigned int UserPxAllocator::mNumFrees = 0;
+
+UserPxAllocator::UserPxAllocator(const char* context,
+ const char* /*dllName*/,
+ bool useTrackerIfSupported /* = true */)
+ : mContext(context)
+ , mMemoryAllocated(0)
+ , mUseTracker(useTrackerIfSupported)
+{
+ SCOPED_TRACKER_LOCK_IF(mUseTracker);
+ TRACKER_CALL_IF(mUseTracker && NULL == mMemoryTracker, mMemoryTracker = MEM_TRACKER::createMemTracker());
+ TRACKER_CALL_IF(trackerEnabled(), ++gMemoryTrackerClients);
+}
+
+void* UserPxAllocator::allocate(size_t size, const char* typeName, const char* filename, int line)
+{
+ void* ret = 0;
+
+ PX_UNUSED(typeName);
+ PX_UNUSED(filename);
+ PX_UNUSED(line);
+ SCOPED_TRACKER_LOCK_IF(trackerEnabled());
+
+#if PX_WINDOWS_FAMILY
+ ret = ::_aligned_malloc(size, 16);
+#elif PX_ANDROID || PX_LINUX_FAMILY
+ /* Allocate size + (15 + sizeof(void*)) bytes and shift pointer further, write original address in the beginning of block.*/
+ /* Weirdly, memalign sometimes returns unaligned address */
+ // ret = ::memalign(size, 16);
+ size_t alignment = 16;
+ void* originalRet = ::malloc(size + 2*alignment + sizeof(void*));
+ // find aligned location
+ ret = ((char*)originalRet) + 2 * alignment - (((size_t)originalRet) & 0xF);
+ // write block address prior to aligned position, so it could be possible to free it later
+ ::memcpy((char*)ret - sizeof(originalRet), &originalRet, sizeof(originalRet));
+#else
+ ret = ::malloc(size);
+#endif
+
+ TRACKER_CALL_IF(trackerEnabled(), mMemoryAllocated += size);
+ TRACKER_CALL_IF(trackerEnabled(), mMemoryTracker->trackAlloc(getThreadId(),ret, size, MEM_TRACKER::MT_MALLOC, USERALLOCATOR, typeName, filename, (uint32_t)line));
+
+ // this should probably be a atomic increment
+ mNumAllocations++;
+
+ return ret;
+}
+
+void UserPxAllocator::deallocate(void* memory)
+{
+ SCOPED_TRACKER_LOCK_IF(trackerEnabled());
+
+ if (memory)
+ {
+#if PX_WINDOWS_FAMILY
+ ::_aligned_free(memory);
+#elif PX_ANDROID || PX_LINUX_FAMILY
+ // Looks scary, but all it does is getting original unaligned block address back from 4/8 bytes (depends on pointer size) prior to <memory> pointer and frees this memory
+ void* originalPtr = (void*)(*(size_t*)((char*)memory - sizeof(void*)));
+ ::free(originalPtr);
+#else
+ ::free(memory);
+#endif
+
+ // this should probably be a atomic decrement
+ mNumFrees++;
+ }
+
+ TRACKER_CALL_IF(trackerEnabled(), mMemoryTracker->trackFree(getThreadId(), memory, MEM_TRACKER::MT_FREE, USERALLOCATOR, __FILE__, __LINE__));
+}
+
+
+UserPxAllocator::~UserPxAllocator()
+{
+ SCOPED_TRACKER_LOCK_IF(trackerEnabled());
+ TRACKER_CALL_IF(trackerEnabled() && (0 == --gMemoryTrackerClients), releaseAndReset(mMemoryTracker));
+}
+
+bool UserPxAllocator::dumpMemoryLeaks(const char* filename)
+{
+ bool leaked = false;
+
+ PX_UNUSED(filename);
+ TRACKER_CALL_IF(mMemoryTracker, leaked = memoryReport(mMemoryTracker, MEM_TRACKER::MRF_SIMPLE_HTML, filename, true));
+
+ return leaked;
+}
+
+#undef SCOPED_TRACKER_LOCK_IF
+#undef TRACKER_CALL_IF \ No newline at end of file