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

This commit is contained in:
Zack Weinberg 2009-11-30 08:51:07 -08:00
parent 78bf5c8cea
commit f6b3144136
2 changed files with 61 additions and 49 deletions

View File

@ -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;
}
} 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;
}
// 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");

View File

@ -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) {
// 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"\n",
SIZxPTR, (uintptr_t)result);
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
printf("INFO | poison area probed at 0x%.*"PRIxPTR" | %s\n",
SIZxPTR, candidate, LastErrMsg());
if (result != MAP_FAILED)
ReleaseRegion(result);
printf("INFO | poison area assumed at 0x%.*"PRIxPTR
" (preferred addr)\n", SIZxPTR, candidate);
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");