From f6b3144136e5a52e7fd88741e70b7ccdff793acf Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Mon, 30 Nov 2009 08:51:07 -0800 Subject: [PATCH] Bug 530598: If we can't get the preferred address for a poison page, take whatever the OS will give us, rather than giving up --- layout/base/nsPresArena.cpp | 51 +++++++++++++----------- layout/base/tests/TestPoisonArea.cpp | 59 ++++++++++++++++------------ 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/layout/base/nsPresArena.cpp b/layout/base/nsPresArena.cpp index 1618fee142ca..b8f99d6db8ac 100644 --- a/layout/base/nsPresArena.cpp +++ b/layout/base/nsPresArena.cpp @@ -180,33 +180,38 @@ ARENA_POISON_init() return PR_SUCCESS; } else { - // Probe 1024 pages (four megabytes, typically) in both directions from - // the baseline address before giving up. + // First see if we can allocate the preferred poison address from the OS. PRUword candidate = (0xF0DEAFFF & ~(rgnsize-1)); - PRUword step = rgnsize; - int direction = +1; - PRUword limit = candidate + 1024*rgnsize; - while (candidate < limit) { - void *result = ReserveRegion(candidate, rgnsize); - if (result == (void *)candidate) { - // success - inaccessible page allocated - ARENA_POISON = candidate + rgnsize/2 - 1; - return PR_SUCCESS; + void *result = ReserveRegion(candidate, rgnsize); + if (result == (void *)candidate) { + // success - inaccessible page allocated + ARENA_POISON = candidate + rgnsize/2 - 1; + return PR_SUCCESS; + } - } else { - if (result != RESERVE_FAILED) - ReleaseRegion(result, rgnsize); + // That didn't work, so see if the preferred address is within a range + // of permanently inacessible memory. + if (ProbeRegion(candidate, rgnsize)) { + // success - selected page cannot be usable memory + ARENA_POISON = candidate + rgnsize/2 - 1; + if (result != RESERVE_FAILED) + ReleaseRegion(result, rgnsize); + return PR_SUCCESS; + } - if (ProbeRegion(candidate, rgnsize)) { - // success - selected page cannot be usable memory - ARENA_POISON = candidate + rgnsize/2 - 1; - return PR_SUCCESS; - } - } + // The preferred address is already in use. Did the OS give us a + // consolation prize? + if (result != RESERVE_FAILED) { + ARENA_POISON = PRUword(result) + rgnsize/2 - 1; + return PR_SUCCESS; + } - candidate += step*direction; - step = step + rgnsize; - direction = -direction; + // It didn't, so try to allocate again, without any constraint on + // the address. + result = ReserveRegion(0, rgnsize); + if (result != RESERVE_FAILED) { + ARENA_POISON = PRUword(result) + rgnsize/2 - 1; + return PR_SUCCESS; } NS_RUNTIMEABORT("no usable poison region identified"); diff --git a/layout/base/tests/TestPoisonArea.cpp b/layout/base/tests/TestPoisonArea.cpp index e0860054293f..67cb211c5f19 100644 --- a/layout/base/tests/TestPoisonArea.cpp +++ b/layout/base/tests/TestPoisonArea.cpp @@ -303,35 +303,42 @@ ReservePoisonArea() printf("INFO | poison area assumed at 0x%.*"PRIxPTR"\n", SIZxPTR, result); return result; } else { - // Probe 1024 pages (four megabytes, typically) in both directions from - // the baseline address before giving up. - uintptr_t candidate = (0xF0DEAFFF & ~(uintptr_t)(PAGESIZE-1)); - uintptr_t step = PAGESIZE; - intptr_t direction = +1; - uintptr_t limit = candidate + 1024*PAGESIZE; - while (candidate < limit) { - void *result = ReserveRegion(candidate, false); - if (result == (void *)candidate) { - // success - inaccessible page allocated - printf("INFO | poison area allocated at 0x%.*"PRIxPTR"\n", - SIZxPTR, (uintptr_t)result); - return candidate; + // First see if we can allocate the preferred poison address from the OS. + uintptr_t candidate = (0xF0DEAFFF & ~(PAGESIZE-1)); + void *result = ReserveRegion(candidate, false); + if (result == (void *)candidate) { + // success - inaccessible page allocated + printf("INFO | poison area allocated at 0x%.*"PRIxPTR + " (preferred addr)\n", SIZxPTR, (uintptr_t)result); + return candidate; + } - } else { - if (result != MAP_FAILED) - ReleaseRegion(result); + // That didn't work, so see if the preferred address is within a range + // of permanently inacessible memory. + if (ProbeRegion(candidate)) { + // success - selected page cannot be usable memory + if (result != MAP_FAILED) + ReleaseRegion(result); + printf("INFO | poison area assumed at 0x%.*"PRIxPTR + " (preferred addr)\n", SIZxPTR, candidate); + return candidate; + } - if (ProbeRegion(candidate)) { - // success - selected page cannot be usable memory - printf("INFO | poison area probed at 0x%.*"PRIxPTR" | %s\n", - SIZxPTR, candidate, LastErrMsg()); - return candidate; - } - } + // The preferred address is already in use. Did the OS give us a + // consolation prize? + if (result != MAP_FAILED) { + printf("INFO | poison area allocated at 0x%.*"PRIxPTR + " (consolation prize)\n", SIZxPTR, (uintptr_t)result); + return (uintptr_t)result; + } - candidate += step*direction; - step = step + PAGESIZE; - direction = -direction; + // It didn't, so try to allocate again, without any constraint on + // the address. + result = ReserveRegion(0, false); + if (result != MAP_FAILED) { + printf("INFO | poison area allocated at 0x%.*"PRIxPTR + " (fallback)\n", SIZxPTR, (uintptr_t)result); + return (uintptr_t)result; } printf("ERROR | no usable poison area found\n");