From 48e6e92f838e67ef77eccb801b236620a732d56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 23 Jul 2012 14:49:06 -0400 Subject: [PATCH] Bug 773903 - ~1s shutdown delay in xpcshell in xpcom shutdown. r=ted. This just updates mach_override.c to a version that has a faster search for an available spot to put the branch island. --- xpcom/build/mach_override.c | 142 +++++++++++++++--------------------- 1 file changed, 60 insertions(+), 82 deletions(-) diff --git a/xpcom/build/mach_override.c b/xpcom/build/mach_override.c index 8382bfcc6c0..bbb21b107f2 100644 --- a/xpcom/build/mach_override.c +++ b/xpcom/build/mach_override.c @@ -1,4 +1,5 @@ -/* copied from https://github.com/rentzsch/mach_star */ +/* Copied from https://github.com/rentzsch/mach_star at revision + * 498e0ba31461ac6bada7fa75ce1a7009734d5a4c */ /******************************************************************************* mach_override.c @@ -25,6 +26,7 @@ #pragma mark - #pragma mark (Constants) +#define kPageSize 4096 #if defined(__ppc__) || defined(__POWERPC__) long kIslandTemplate[] = { @@ -78,9 +80,6 @@ char kIslandTemplate[] = { #endif -#define kAllocateHigh 1 -#define kAllocateNormal 0 - /************************** * * Data Types @@ -91,7 +90,6 @@ char kIslandTemplate[] = { typedef struct { char instructions[sizeof(kIslandTemplate)]; - int allocatedHigh; } BranchIsland; /************************** @@ -105,7 +103,6 @@ typedef struct { mach_error_t allocateBranchIsland( BranchIsland **island, - int allocateHigh, void *originalFunctionAddress); mach_error_t @@ -160,12 +157,10 @@ fixupInstructions( #if defined(__i386__) || defined(__x86_64__) mach_error_t makeIslandExecutable(void *address) { mach_error_t err = err_none; - vm_size_t pageSize; - host_page_size( mach_host_self(), &pageSize ); - uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); + uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1); int e = err_none; - e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE); - e |= msync((void *)page, pageSize, MS_INVALIDATE ); + e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE); + e |= msync((void *)page, kPageSize, MS_INVALIDATE ); if (e) { err = err_cannot_override; } @@ -243,7 +238,7 @@ mach_override_ptr( // Allocate and target the escape island to the overriding function. BranchIsland *escapeIsland = NULL; if( !err ) - err = allocateBranchIsland( &escapeIsland, kAllocateHigh, originalFunctionAddress ); + err = allocateBranchIsland( &escapeIsland, originalFunctionAddress ); if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); @@ -285,7 +280,7 @@ mach_override_ptr( // technically our original function. BranchIsland *reentryIsland = NULL; if( !err && originalFunctionReentryIsland ) { - err = allocateBranchIsland( &reentryIsland, kAllocateHigh, escapeIsland); + err = allocateBranchIsland( &reentryIsland, escapeIsland); if( !err ) *originalFunctionReentryIsland = reentryIsland; } @@ -369,9 +364,6 @@ mach_override_ptr( Implementation: Allocates memory for a branch island. @param island <- The allocated island. - @param allocateHigh -> Whether to allocate the island at the end of the - address space (for use with the branch absolute - instruction). @result <- mach_error_t ***************************************************************************/ @@ -379,63 +371,63 @@ mach_override_ptr( mach_error_t allocateBranchIsland( BranchIsland **island, - int allocateHigh, void *originalFunctionAddress) { assert( island ); - - mach_error_t err = err_none; - - if( allocateHigh ) { - vm_size_t pageSize; - err = host_page_size( mach_host_self(), &pageSize ); - if( !err ) { - assert( sizeof( BranchIsland ) <= pageSize ); -#if defined(__ppc__) || defined(__POWERPC__) - vm_address_t first = 0xfeffffff; - vm_address_t last = 0xfe000000 + pageSize; -#elif defined(__x86_64__) - vm_address_t first = (uint64_t)originalFunctionAddress & ~(uint64_t)(((uint64_t)1 << 31) - 1) | ((uint64_t)1 << 31); // start in the middle of the page? - vm_address_t last = 0x0; -#else - vm_address_t first = 0xffc00000; - vm_address_t last = 0xfffe0000; -#endif + assert( sizeof( BranchIsland ) <= kPageSize ); - vm_address_t page = first; - int allocated = 0; - vm_map_t task_self = mach_task_self(); - - while( !err && !allocated && page != last ) { + vm_map_t task_self = mach_task_self(); + vm_address_t original_address = (vm_address_t) originalFunctionAddress; + static vm_address_t last_allocated = 0; + vm_address_t address = + last_allocated ? last_allocated : original_address; - err = vm_allocate( task_self, &page, pageSize, 0 ); - if( err == err_none ) - allocated = 1; - else if( err == KERN_NO_SPACE ) { -#if defined(__x86_64__) - page -= pageSize; + for (;;) { + vm_size_t vmsize = 0; + memory_object_name_t object = 0; + kern_return_t kr = 0; + vm_region_flavor_t flavor = VM_REGION_BASIC_INFO; + // Find the page the address is in. +#if __WORDSIZE == 32 + vm_region_basic_info_data_t info; + mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; + kr = vm_region(task_self, &address, &vmsize, flavor, + (vm_region_info_t)&info, &info_count, &object); #else - page += pageSize; + vm_region_basic_info_data_64_t info; + mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; + kr = vm_region_64(task_self, &address, &vmsize, flavor, + (vm_region_info_t)&info, &info_count, &object); #endif - err = err_none; - } - } - if( allocated ) - *island = (BranchIsland*) page; - else if( !allocated && !err ) - err = KERN_NO_SPACE; + if (kr != KERN_SUCCESS) + return kr; + + // Don't underflow. This could be made to work, but this is a + // convenient place to give up. + assert((address & (kPageSize - 1)) == 0); + if (address == 0) + break; + + // Go back one page. + vm_address_t new_address = address - kPageSize; +#if __WORDSIZE == 64 + if(original_address - new_address - 5 > INT32_MAX) + break; +#endif + address = new_address; + + // Try to allocate this page. + kr = vm_allocate(task_self, &address, kPageSize, 0); + if (kr == KERN_SUCCESS) { + *island = (BranchIsland*) address; + last_allocated = address; + return err_none; } - } else { - void *block = malloc( sizeof( BranchIsland ) ); - if( block ) - *island = block; - else - err = KERN_NO_SPACE; + if (kr != KERN_NO_SPACE) + return kr; } - if( !err ) - (**island).allocatedHigh = allocateHigh; - - return err; + + return KERN_NO_SPACE; } /***************************************************************************//** @@ -452,24 +444,9 @@ freeBranchIsland( { assert( island ); assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); - assert( island->allocatedHigh ); - - mach_error_t err = err_none; - - if( island->allocatedHigh ) { - vm_size_t pageSize; - err = host_page_size( mach_host_self(), &pageSize ); - if( !err ) { - assert( sizeof( BranchIsland ) <= pageSize ); - err = vm_deallocate( - mach_task_self(), - (vm_address_t) island, pageSize ); - } - } else { - free( island ); - } - - return err; + assert( sizeof( BranchIsland ) <= kPageSize ); + return vm_deallocate( mach_task_self(), (vm_address_t) island, + kPageSize ); } /***************************************************************************//** @@ -601,6 +578,7 @@ static AsmInstructionMatch possibleInstructions[] = { { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi) { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax + { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %eax { 0x0 } }; #endif