back-port allocator patch from libtorrent_aio to make the buffer debugging code generic and platform-independent

This commit is contained in:
Arvid Norberg 2014-01-20 03:55:24 +00:00
parent 452e78ba3b
commit e616b5b38e
2 changed files with 39 additions and 32 deletions

View File

@ -47,7 +47,7 @@ namespace libtorrent
typedef std::ptrdiff_t difference_type;
static char* malloc(const size_type bytes);
static void free(char* const block);
static void free(char* block);
};
struct TORRENT_EXTRA_EXPORT aligned_holder

View File

@ -97,21 +97,45 @@ namespace libtorrent
char* page_aligned_allocator::malloc(size_type bytes)
{
TORRENT_ASSERT(bytes > 0);
// just sanity check (this needs to be pretty high
// for cases where the cache size is several gigabytes)
TORRENT_ASSERT(bytes < 0x30000000);
TORRENT_ASSERT(bytes >= page_size());
#ifdef TORRENT_DEBUG_BUFFERS
int page = page_size();
int num_pages = (bytes + (page-1)) / page + 2;
char* ret = (char*)valloc(num_pages * page);
// make the two surrounding pages non-readable and -writable
alloc_header* h = (alloc_header*)ret;
h->size = bytes;
h->magic = 0x1337;
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
print_backtrace(h->stack, sizeof(h->stack));
int orig_bytes = bytes;
bytes = num_pages * page;
#endif
char* ret;
#if TORRENT_USE_POSIX_MEMALIGN
if (posix_memalign((void**)&ret, page_size(), bytes) != 0) ret = NULL;
#elif TORRENT_USE_MEMALIGN
ret = (char*)memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
ret = (char*)_aligned_malloc(bytes, page_size());
#elif defined TORRENT_BEOS
area_id id = create_area("", &ret, B_ANY_ADDRESS
, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (id < B_OK) return NULL;
ret = (char*)ret;
#else
ret = (char*)valloc(bytes);
#endif
if (ret == NULL) return NULL;
#ifdef TORRENT_DEBUG_BUFFERS
// make the two surrounding pages non-readable and -writable
alloc_header* h = (alloc_header*)ret;
h->size = orig_bytes;
h->magic = 0x1337;
print_backtrace(h->stack, sizeof(h->stack));
#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULL)
#define PROT_READ PAGE_READONLY
#endif
mprotect(ret, page, PROT_READ);
@ -124,35 +148,19 @@ namespace libtorrent
// fprintf(stderr, "malloc: %p head: %p tail: %p size: %d\n", ret + page, ret, ret + page + bytes, int(bytes));
return ret + page;
#else
#if TORRENT_USE_POSIX_MEMALIGN
void* ret;
if (posix_memalign(&ret, page_size(), bytes) != 0) ret = 0;
return (char*)ret;
#elif TORRENT_USE_MEMALIGN
return (char*)memalign(page_size(), bytes);
#elif defined TORRENT_WINDOWS
return (char*)_aligned_malloc(bytes, page_size());
#elif defined TORRENT_BEOS
void* ret = 0;
area_id id = create_area("", &ret, B_ANY_ADDRESS
, (bytes + page_size() - 1) & (page_size()-1), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (id < B_OK) return 0;
return (char*)ret;
#else
return (char*)valloc(bytes);
#endif
#endif // TORRENT_DEBUG_BUFFERS
return ret;
}
void page_aligned_allocator::free(char* const block)
void page_aligned_allocator::free(char* block)
{
if (block == 0) return;
#ifdef TORRENT_DEBUG_BUFFERS
#ifdef TORRENT_WINDOWS
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULK)
#define mprotect(buf, size, prot) VirtualProtect(buf, size, prot, NULL)
#define PROT_READ PAGE_READONLY
#define PROT_WRITE PAGE_READWRITE
#endif
@ -165,6 +173,7 @@ namespace libtorrent
mprotect(block + (num_pages-2) * page, page, PROT_READ | PROT_WRITE);
// fprintf(stderr, "free: %p head: %p tail: %p size: %d\n", block, block - page, block + h->size, int(h->size));
h->magic = 0;
block -= page;
#ifdef TORRENT_WINDOWS
#undef mprotect
@ -175,8 +184,6 @@ namespace libtorrent
#if defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
print_backtrace(h->stack, sizeof(h->stack));
#endif
::free(block - page);
return;
#endif // TORRENT_DEBUG_BUFFERS
#ifdef TORRENT_WINDOWS