1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
#include "stdafx.h"
#include "Stack.h"
#include "Exception.h"
#include "Utils/Bitwise.h"
#ifdef POSIX
#include <sys/mman.h>
#endif
namespace os {
Stack::Stack(size_t size) : desc(null), detourActive(0), detourTo(null), alloc(null), size(0) {
allocate(size);
initDesc();
}
Stack::Stack(void *base) : desc(null), detourActive(0), detourTo(null), alloc(base), size(0) {
// Nothing more to do!
}
Stack::~Stack() {
if (size > 0) {
free();
size = 0;
}
}
void Stack::clear() {
initDesc();
}
#if defined(WINDOWS)
static size_t pageSize() {
static size_t sz = 0;
if (sz == 0) {
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
sz = sysInfo.dwPageSize;
}
return sz;
}
void Stack::allocate(size_t size) {
size_t pageSz = pageSize();
size = roundUp(size, pageSz);
size += pageSz; // We want a guard page.
byte *mem = (byte *)VirtualAlloc(null, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (mem == null) {
// TODO: What to do in this case?
throw ThreadError(L"Out of memory when spawning a thread.");
}
DWORD oldProt;
VirtualProtect(mem, 1, PAGE_READONLY | PAGE_GUARD, &oldProt);
// Do not show the guard page to other parts...
this->alloc = mem + pageSz;
this->size = size - pageSz;
}
void Stack::free() {
byte *mem = (byte *)alloc;
mem -= pageSize();
VirtualFree(mem, 0, MEM_RELEASE);
}
void Stack::initDesc() {
// Put the initial stack description in the 'top' of the stack.
// It will be updated when we initialize the stack later.
byte *r = (byte *)alloc;
desc = (Desc *)alloc;
desc->low = r + size;
desc->dummy = r;
desc->high = r + size;
}
#elif defined(POSIX)
static size_t pageSize() {
static size_t sz = 0;
if (sz == 0) {
int s = getpagesize();
assert(s > 0, L"Failed to acquire the page size for your system!");
sz = (size_t)s;
}
return sz;
}
void Stack::allocate(size_t size) {
size_t pageSz = pageSize();
size = roundUp(size, pageSz);
size += pageSz; // We want a guard page.
byte *mem = (byte *)mmap(null, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mem == null) {
// TODO: What to do in this case?
throw ThreadError(L"Out of memory when spawning a thread.");
}
mprotect(mem, 1, PROT_NONE); // no special guard-page it seems...
// Do not show the guard page to other parts...
this->alloc = mem + pageSz;
this->size = size - pageSz;
}
void Stack::free() {
byte *mem = (byte *)alloc;
size_t pageSz = pageSize();
mem -= pageSz;
munmap(mem, size + pageSz);
}
void Stack::initDesc() {
// Put the initial stack description in the 'top' of the stack.
// It will be updated when we initialize the stack later.
byte *r = (byte *)alloc;
desc = (Desc *)alloc;
desc->low = r + size;
desc->dummy = r;
desc->high = r + size;
}
#endif
}
|