diff --git a/include/libtorrent/allocator.hpp b/include/libtorrent/allocator.hpp index fd44d0006..31060a225 100644 --- a/include/libtorrent/allocator.hpp +++ b/include/libtorrent/allocator.hpp @@ -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 diff --git a/src/allocator.cpp b/src/allocator.cpp index 36142b22a..f1c205beb 100644 --- a/src/allocator.cpp +++ b/src/allocator.cpp @@ -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