Rev. | 7b00b56bfbf3446f786255c6fee3f39c715b1a35 |
---|---|
Size | 3,200 bytes |
Time | 2020-07-04 19:11:41 |
Author | simphone |
Log Message | electric fence 2.1 win32 |
#include "efence.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static caddr_t startAddr = (caddr_t) 0;
/* TODO: This function is not thread safe. */
static const char *
stringErrorReport(void)
{
static char buf[1024];
DWORD err = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 78, NULL, err, 0, buf, sizeof(buf), NULL);
buf[sizeof(buf)-1] = 0;
return buf;
}
/*
* Create memory.
*/
void *
Page_Create(size_t size)
{
caddr_t allocation;
/*
* In this version, "startAddr" is a _hint_, not a demand.
* When the memory I map here is contiguous with other
* mappings, the allocator can coalesce the memory from two
* or more mappings into one large contiguous chunk, and thus
* might be able to find a fit that would not otherwise have
* been possible. I could _force_ it to be contiguous by using
* the MMAP_FIXED flag, but I don't want to stomp on memory mappings
* generated by other software, etc.
*/
allocation = (caddr_t) VirtualAlloc(
(LPVOID)startAddr
,size
,MEM_RESERVE|MEM_COMMIT
,PAGE_READWRITE);
#ifndef _WIN32
/*
* Set the "address hint" for the next mmap() so that it will abut
* the mapping we just created.
*
* Windows doesn't treat the address as a hint.
*
* Maybe TODO: Hint and retry when the hint fails.
*/
startAddr = allocation + size;
#endif
if ( allocation == 0 )
EF_Exit("VirtualAlloc() failed: %s", stringErrorReport());
return (void *)allocation;
}
static DWORD AllocationGranularity;
static void
mprotectFailed(void)
{
EF_Exit("VirtualProtect() failed: %s", stringErrorReport());
}
/* Win32's VirtualProtect does not work across VirtualAlloc boundaries */
/* Therefore, avoid the problem by doing all operations in AllocationGranularity sized chunks */
void
Page_AllowAccess(void * address, size_t size)
{
DWORD old;
while (size) {
size_t mySize;
mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
if (!VirtualProtect(address, mySize, PAGE_READWRITE, &old))
mprotectFailed();
size -= mySize;
address = (void *)((DWORD_PTR)address + mySize);
}
}
void
Page_DenyAccess(void * address, size_t size)
{
DWORD old;
while (size) {
size_t mySize;
mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
if (!VirtualProtect(address, mySize, PAGE_NOACCESS, &old))
mprotectFailed();
size -= mySize;
address = (void *)((DWORD_PTR)address + mySize);
}
}
void
Page_Delete(void * address, size_t size)
{
// Page_DenyAccess(address, size);
while (size) {
size_t mySize;
mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
if (!VirtualFree(address, mySize, MEM_DECOMMIT))
EF_Exit("VirtualFree() failed: %s", stringErrorReport());
size -= mySize;
address = (void *)((DWORD_PTR)address + mySize);
}
}
size_t
Page_Size(void)
{
SYSTEM_INFO info;
GetSystemInfo(&info);
AllocationGranularity = info.dwAllocationGranularity;
return info.dwPageSize;
}