/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <windows.h> #include <assert.h> #include <NdbStdio.h> #include "NdbMem.h" struct AWEINFO { SIZE_T dwSizeInBytesRequested; ULONG_PTR nNumberOfPagesRequested; ULONG_PTR nNumberOfPagesActual; ULONG_PTR nNumberOfPagesFreed; ULONG_PTR* pnPhysicalMemoryPageArray; void* pRegionReserved; }; const size_t cNdbMem_nMaxAWEinfo = 256; size_t gNdbMem_nAWEinfo = 0; struct AWEINFO* gNdbMem_pAWEinfo = 0; void ShowLastError(const char* szContext, const char* szFunction) { DWORD dwError = GetLastError(); LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL ); printf("%s : %s failed : %lu : %s\n", szContext, szFunction, dwError, (char*)lpMsgBuf); LocalFree(lpMsgBuf); } void NdbMem_Create() { // Address Windowing Extensions struct PRIVINFO { DWORD Count; LUID_AND_ATTRIBUTES Privilege[1]; } Info; HANDLE hProcess = GetCurrentProcess(); HANDLE hToken; if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) { ShowLastError("NdbMem_Create", "OpenProcessToken"); } Info.Count = 1; Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; if(!LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid))) { ShowLastError("NdbMem_Create", "LookupPrivilegeValue"); } if(!AdjustTokenPrivileges(hToken, FALSE, (PTOKEN_PRIVILEGES)&Info, 0, 0, 0)) { ShowLastError("NdbMem_Create", "AdjustTokenPrivileges"); } if(!CloseHandle(hToken)) { ShowLastError("NdbMem_Create", "CloseHandle"); } return; } void NdbMem_Destroy() { /* Do nothing */ return; } void* NdbMem_Allocate(size_t size) { // Address Windowing Extensions struct AWEINFO* pAWEinfo; HANDLE hProcess; SYSTEM_INFO sysinfo; if(!gNdbMem_pAWEinfo) { gNdbMem_pAWEinfo = VirtualAlloc(0, sizeof(struct AWEINFO)*cNdbMem_nMaxAWEinfo, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); } assert(gNdbMem_nAWEinfo < cNdbMem_nMaxAWEinfo); pAWEinfo = gNdbMem_pAWEinfo+gNdbMem_nAWEinfo++; hProcess = GetCurrentProcess(); GetSystemInfo(&sysinfo); pAWEinfo->nNumberOfPagesRequested = (size+sysinfo.dwPageSize-1)/sysinfo.dwPageSize; pAWEinfo->pnPhysicalMemoryPageArray = VirtualAlloc(0, sizeof(ULONG_PTR)*pAWEinfo->nNumberOfPagesRequested, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); pAWEinfo->nNumberOfPagesActual = pAWEinfo->nNumberOfPagesRequested; if(!AllocateUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesActual), pAWEinfo->pnPhysicalMemoryPageArray)) { ShowLastError("NdbMem_Allocate", "AllocateUserPhysicalPages"); return 0; } if(pAWEinfo->nNumberOfPagesRequested != pAWEinfo->nNumberOfPagesActual) { ShowLastError("NdbMem_Allocate", "nNumberOfPagesRequested != nNumberOfPagesActual"); return 0; } pAWEinfo->dwSizeInBytesRequested = size; pAWEinfo->pRegionReserved = VirtualAlloc(0, pAWEinfo->dwSizeInBytesRequested, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE); if(!pAWEinfo->pRegionReserved) { ShowLastError("NdbMem_Allocate", "VirtualAlloc"); return 0; } if(!MapUserPhysicalPages(pAWEinfo->pRegionReserved, pAWEinfo->nNumberOfPagesActual, pAWEinfo->pnPhysicalMemoryPageArray)) { ShowLastError("NdbMem_Allocate", "MapUserPhysicalPages"); return 0; } /* printf("allocate AWE memory: %lu bytes, %lu pages, address %lx\n", pAWEinfo->dwSizeInBytesRequested, pAWEinfo->nNumberOfPagesActual, pAWEinfo->pRegionReserved); */ return pAWEinfo->pRegionReserved; } void* NdbMem_AllocateAlign(size_t size, size_t alignment) { /* return (void*)memalign(alignment, size); TEMP fix */ return NdbMem_Allocate(size); } void NdbMem_Free(void* ptr) { // VirtualFree(ptr, 0, MEM_DECOMMIT|MEM_RELEASE); // Address Windowing Extensions struct AWEINFO* pAWEinfo = 0; size_t i; HANDLE hProcess; for(i=0; i<gNdbMem_nAWEinfo; ++i) { if(ptr==gNdbMem_pAWEinfo[i].pRegionReserved) { pAWEinfo = gNdbMem_pAWEinfo+i; } } if(!pAWEinfo) { ShowLastError("NdbMem_Free", "ptr is not AWE memory"); } hProcess = GetCurrentProcess(); if(!MapUserPhysicalPages(ptr, pAWEinfo->nNumberOfPagesActual, 0)) { ShowLastError("NdbMem_Free", "MapUserPhysicalPages"); } if(!VirtualFree(ptr, 0, MEM_RELEASE)) { ShowLastError("NdbMem_Free", "VirtualFree"); } pAWEinfo->nNumberOfPagesFreed = pAWEinfo->nNumberOfPagesActual; if(!FreeUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesFreed), pAWEinfo->pnPhysicalMemoryPageArray)) { ShowLastError("NdbMem_Free", "FreeUserPhysicalPages"); } VirtualFree(pAWEinfo->pnPhysicalMemoryPageArray, 0, MEM_DECOMMIT|MEM_RELEASE); } int NdbMem_MemLockAll() { /* HANDLE hProcess = GetCurrentProcess(); SIZE_T nMinimumWorkingSetSize; SIZE_T nMaximumWorkingSetSize; GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize); ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl; SetProcessWorkingSetSize(hProcess, 50000000, 100000000); GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize); ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl; */ return -1; } int NdbMem_MemUnlockAll() { //VirtualUnlock(); return -1; }