summaryrefslogtreecommitdiff
path: root/indra/llcommon/llmemory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llmemory.cpp')
-rw-r--r--indra/llcommon/llmemory.cpp708
1 files changed, 354 insertions, 354 deletions
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 6e0715d697..0e5b91c9b8 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -1,354 +1,354 @@
-/**
- * @file llmemory.cpp
- * @brief Very special memory allocation/deallocation stuff here
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-
-#include "llthread.h"
-
-#if defined(LL_WINDOWS)
-# include <psapi.h>
-#elif defined(LL_DARWIN)
-# include <sys/types.h>
-# include <mach/task.h>
-# include <mach/mach_init.h>
-#include <mach/mach_host.h>
-#elif LL_LINUX
-# include <unistd.h>
-# include <sys/resource.h>
-#endif
-
-#include "llmemory.h"
-
-#include "llsys.h"
-#include "llframetimer.h"
-#include "lltrace.h"
-#include "llerror.h"
-//----------------------------------------------------------------------------
-
-//static
-U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
-U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
-static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
-static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");
-U32Kilobytes LLMemory::sAllocatedMemInKB(0);
-U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
-U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
-
-void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
-{
-#if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN)
- //do not check
- return;
-#else
- #ifdef SHOW_ASSERT
- // Redundant, place to set breakpoints.
- if (ptr%alignment!=0)
- {
- LL_WARNS() << "alignment check failed" << LL_ENDL;
- }
- llassert(ptr%alignment==0);
- #endif
-#endif
-}
-
-//static
-void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)
-{
- sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
-}
-
-//static
-void LLMemory::updateMemoryInfo()
-{
- LL_PROFILE_ZONE_SCOPED
-#if LL_WINDOWS
- PROCESS_MEMORY_COUNTERS counters;
-
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
- {
- LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
- return ;
- }
-
- sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
- sample(sAllocatedMem, sAllocatedMemInKB);
- sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
- sample(sVirtualMem, sAllocatedPageSizeInKB);
-
- U32Kilobytes avail_phys, avail_virtual;
- LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
- sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
-
- if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
- {
- sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
- }
- else
- {
- sAvailPhysicalMemInKB = U32Kilobytes(0);
- }
-
-#elif defined(LL_DARWIN)
- task_vm_info info;
- mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT;
- // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint.
- if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &infoCount) == KERN_SUCCESS)
- {
- // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of
- // memory that the memory manager has committed for a running process", which is rss.
- sAllocatedPageSizeInKB = U32Bytes(info.resident_size);
-
- // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size
- // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less.
- // I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals.
- //
- // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value
- // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint.
- //
- // (On Windows, we use WorkingSetSize.)
- sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable);
- }
- else
- {
- LL_WARNS() << "task_info failed" << LL_ENDL;
- }
-
- // Total installed and available physical memory are properties of the host, not just our process.
- vm_statistics64_data_t vmstat;
- mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
- mach_port_t host = mach_host_self();
- vm_size_t page_size;
- host_page_size(host, &page_size);
- kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count);
- if (result == KERN_SUCCESS) {
- // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.'
- // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure.
- sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size);
- sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize();
- }
- else
- {
- LL_WARNS() << "task_info failed" << LL_ENDL;
- }
-
-#else
- //not valid for other systems for now.
- sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
- sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
- sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
-#endif
-
- return ;
-}
-
-//
-//this function is to test if there is enough space with the size in the virtual address space.
-//it does not do any real allocation
-//if success, it returns the address where the memory chunk can fit in;
-//otherwise it returns NULL.
-//
-//static
-void* LLMemory::tryToAlloc(void* address, U32 size)
-{
-#if LL_WINDOWS
- address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
- if(address)
- {
- if(!VirtualFree(address, 0, MEM_RELEASE))
- {
- LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
- }
- }
- return address ;
-#else
- return (void*)0x01 ; //skip checking
-#endif
-}
-
-//static
-void LLMemory::logMemoryInfo(bool update)
-{
- LL_PROFILE_ZONE_SCOPED
- if(update)
- {
- updateMemoryInfo() ;
- }
-
- LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
- LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
- LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
- LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
-}
-
-//static
-U32Kilobytes LLMemory::getAvailableMemKB()
-{
- return sAvailPhysicalMemInKB ;
-}
-
-//static
-U32Kilobytes LLMemory::getMaxMemKB()
-{
- return sMaxPhysicalMemInKB ;
-}
-
-//static
-U32Kilobytes LLMemory::getAllocatedMemKB()
-{
- return sAllocatedMemInKB ;
-}
-
-//----------------------------------------------------------------------------
-
-#if defined(LL_WINDOWS)
-
-//static
-U64 LLMemory::getCurrentRSS()
-{
- PROCESS_MEMORY_COUNTERS counters;
-
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
- {
- LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
- return 0;
- }
-
- return counters.WorkingSetSize;
-}
-
-#elif defined(LL_DARWIN)
-
-// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
-// {
-// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
-// return 0;
-// } else {
-// return page_size;
-// }
-// }
-
-U64 LLMemory::getCurrentRSS()
-{
- U64 residentSize = 0;
- mach_task_basic_info_data_t basicInfo;
- mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
- if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
- {
- residentSize = basicInfo.resident_size;
- // 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size.
- // basicInfo.virtual_size is not what we want.
- }
- else
- {
- LL_WARNS() << "task_info failed" << LL_ENDL;
- }
-
- return residentSize;
-}
-
-#elif defined(LL_LINUX)
-
-U64 LLMemory::getCurrentRSS()
-{
- struct rusage usage;
-
- if (getrusage(RUSAGE_SELF, &usage) != 0) {
- // Error handling code could be here
- return 0;
- }
-
- // ru_maxrss (since Linux 2.6.32)
- // This is the maximum resident set size used (in kilobytes).
- return usage.ru_maxrss * 1024;
-}
-
-#else
-
-U64 LLMemory::getCurrentRSS()
-{
- return 0;
-}
-
-#endif
-
-//--------------------------------------------------------------------
-
-#if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN)
-
-#include <map>
-
-struct mem_info {
- std::map<void*, void*> memory_info;
- LLMutex mutex;
-
- static mem_info& get() {
- static mem_info instance;
- return instance;
- }
-
-private:
- mem_info(){}
-};
-
-void* ll_aligned_malloc_fallback( size_t size, int align )
-{
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
-
- unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;
-
- void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
- if(NULL == p) {
- // call debugger
- __asm int 3;
- }
- DWORD old;
- bool Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old);
- if(false == Res) {
- // call debugger
- __asm int 3;
- }
-
- void* ret = (void*)((char*)p + for_alloc-size);
-
- {
- LLMutexLock lock(&mem_info::get().mutex);
- mem_info::get().memory_info.insert(std::pair<void*, void*>(ret, p));
- }
-
-
- return ret;
-}
-
-void ll_aligned_free_fallback( void* ptr )
-{
- LLMutexLock lock(&mem_info::get().mutex);
- VirtualFree(mem_info::get().memory_info.find(ptr)->second, 0, MEM_RELEASE);
- mem_info::get().memory_info.erase(ptr);
-}
-
-#endif
+/**
+ * @file llmemory.cpp
+ * @brief Very special memory allocation/deallocation stuff here
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+
+#include "llthread.h"
+
+#if defined(LL_WINDOWS)
+# include <psapi.h>
+#elif defined(LL_DARWIN)
+# include <sys/types.h>
+# include <mach/task.h>
+# include <mach/mach_init.h>
+#include <mach/mach_host.h>
+#elif LL_LINUX
+# include <unistd.h>
+# include <sys/resource.h>
+#endif
+
+#include "llmemory.h"
+
+#include "llsys.h"
+#include "llframetimer.h"
+#include "lltrace.h"
+#include "llerror.h"
+//----------------------------------------------------------------------------
+
+//static
+U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
+U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
+static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
+static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");
+U32Kilobytes LLMemory::sAllocatedMemInKB(0);
+U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
+U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
+
+void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
+{
+#if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN)
+ //do not check
+ return;
+#else
+ #ifdef SHOW_ASSERT
+ // Redundant, place to set breakpoints.
+ if (ptr%alignment!=0)
+ {
+ LL_WARNS() << "alignment check failed" << LL_ENDL;
+ }
+ llassert(ptr%alignment==0);
+ #endif
+#endif
+}
+
+//static
+void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)
+{
+ sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
+}
+
+//static
+void LLMemory::updateMemoryInfo()
+{
+ LL_PROFILE_ZONE_SCOPED
+#if LL_WINDOWS
+ PROCESS_MEMORY_COUNTERS counters;
+
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+ {
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
+ return ;
+ }
+
+ sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
+ sample(sAllocatedMem, sAllocatedMemInKB);
+ sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
+ sample(sVirtualMem, sAllocatedPageSizeInKB);
+
+ U32Kilobytes avail_phys, avail_virtual;
+ LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
+ sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
+
+ if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+ {
+ sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+ }
+ else
+ {
+ sAvailPhysicalMemInKB = U32Kilobytes(0);
+ }
+
+#elif defined(LL_DARWIN)
+ task_vm_info info;
+ mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT;
+ // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint.
+ if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &infoCount) == KERN_SUCCESS)
+ {
+ // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of
+ // memory that the memory manager has committed for a running process", which is rss.
+ sAllocatedPageSizeInKB = U32Bytes(info.resident_size);
+
+ // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size
+ // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less.
+ // I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals.
+ //
+ // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value
+ // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint.
+ //
+ // (On Windows, we use WorkingSetSize.)
+ sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable);
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
+ // Total installed and available physical memory are properties of the host, not just our process.
+ vm_statistics64_data_t vmstat;
+ mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
+ mach_port_t host = mach_host_self();
+ vm_size_t page_size;
+ host_page_size(host, &page_size);
+ kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count);
+ if (result == KERN_SUCCESS) {
+ // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.'
+ // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure.
+ sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size);
+ sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize();
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
+#else
+ //not valid for other systems for now.
+ sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
+ sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
+ sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
+#endif
+
+ return ;
+}
+
+//
+//this function is to test if there is enough space with the size in the virtual address space.
+//it does not do any real allocation
+//if success, it returns the address where the memory chunk can fit in;
+//otherwise it returns NULL.
+//
+//static
+void* LLMemory::tryToAlloc(void* address, U32 size)
+{
+#if LL_WINDOWS
+ address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
+ if(address)
+ {
+ if(!VirtualFree(address, 0, MEM_RELEASE))
+ {
+ LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
+ }
+ }
+ return address ;
+#else
+ return (void*)0x01 ; //skip checking
+#endif
+}
+
+//static
+void LLMemory::logMemoryInfo(bool update)
+{
+ LL_PROFILE_ZONE_SCOPED
+ if(update)
+ {
+ updateMemoryInfo() ;
+ }
+
+ LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
+ LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
+}
+
+//static
+U32Kilobytes LLMemory::getAvailableMemKB()
+{
+ return sAvailPhysicalMemInKB ;
+}
+
+//static
+U32Kilobytes LLMemory::getMaxMemKB()
+{
+ return sMaxPhysicalMemInKB ;
+}
+
+//static
+U32Kilobytes LLMemory::getAllocatedMemKB()
+{
+ return sAllocatedMemInKB ;
+}
+
+//----------------------------------------------------------------------------
+
+#if defined(LL_WINDOWS)
+
+//static
+U64 LLMemory::getCurrentRSS()
+{
+ PROCESS_MEMORY_COUNTERS counters;
+
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+ {
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
+ return 0;
+ }
+
+ return counters.WorkingSetSize;
+}
+
+#elif defined(LL_DARWIN)
+
+// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
+// {
+// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
+// return 0;
+// } else {
+// return page_size;
+// }
+// }
+
+U64 LLMemory::getCurrentRSS()
+{
+ U64 residentSize = 0;
+ mach_task_basic_info_data_t basicInfo;
+ mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
+ if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
+ {
+ residentSize = basicInfo.resident_size;
+ // 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size.
+ // basicInfo.virtual_size is not what we want.
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
+ return residentSize;
+}
+
+#elif defined(LL_LINUX)
+
+U64 LLMemory::getCurrentRSS()
+{
+ struct rusage usage;
+
+ if (getrusage(RUSAGE_SELF, &usage) != 0) {
+ // Error handling code could be here
+ return 0;
+ }
+
+ // ru_maxrss (since Linux 2.6.32)
+ // This is the maximum resident set size used (in kilobytes).
+ return usage.ru_maxrss * 1024;
+}
+
+#else
+
+U64 LLMemory::getCurrentRSS()
+{
+ return 0;
+}
+
+#endif
+
+//--------------------------------------------------------------------
+
+#if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN)
+
+#include <map>
+
+struct mem_info {
+ std::map<void*, void*> memory_info;
+ LLMutex mutex;
+
+ static mem_info& get() {
+ static mem_info instance;
+ return instance;
+ }
+
+private:
+ mem_info(){}
+};
+
+void* ll_aligned_malloc_fallback( size_t size, int align )
+{
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+
+ unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;
+
+ void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ if(NULL == p) {
+ // call debugger
+ __asm int 3;
+ }
+ DWORD old;
+ bool Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old);
+ if(false == Res) {
+ // call debugger
+ __asm int 3;
+ }
+
+ void* ret = (void*)((char*)p + for_alloc-size);
+
+ {
+ LLMutexLock lock(&mem_info::get().mutex);
+ mem_info::get().memory_info.insert(std::pair<void*, void*>(ret, p));
+ }
+
+
+ return ret;
+}
+
+void ll_aligned_free_fallback( void* ptr )
+{
+ LLMutexLock lock(&mem_info::get().mutex);
+ VirtualFree(mem_info::get().memory_info.find(ptr)->second, 0, MEM_RELEASE);
+ mem_info::get().memory_info.erase(ptr);
+}
+
+#endif