diff options
| author | Eli Zaretskii | 2014-03-04 19:35:15 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2014-03-04 19:35:15 +0200 |
| commit | 201572eca80ea77d8e1c25099b4aa2d98bc4d402 (patch) | |
| tree | b2aedb9d508729a1b3b30bfe23c2bb13fc42d54f /src/gmalloc.c | |
| parent | 3106d59bce024deba9d6b2193531c09b6a6d3c91 (diff) | |
| download | emacs-201572eca80ea77d8e1c25099b4aa2d98bc4d402.tar.gz emacs-201572eca80ea77d8e1c25099b4aa2d98bc4d402.zip | |
Follow-up improvements for last change in gmalloc.c.
src/gmalloc.c (aligned_alloc): Don't allocate more memory than
needed, and don't reallocate if the initial allocation already
fits the bill. Suggested by Ken Brown <kbrown@cornell.edu>.
Fixes: debbugs:16901
Diffstat (limited to 'src/gmalloc.c')
| -rw-r--r-- | src/gmalloc.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c index f8d0cfdc30a..9fd62407285 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c | |||
| @@ -38,6 +38,10 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 38 | #include <w32heap.h> /* for sbrk */ | 38 | #include <w32heap.h> /* for sbrk */ |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | #ifdef emacs | ||
| 42 | extern void emacs_abort (void); | ||
| 43 | #endif | ||
| 44 | |||
| 41 | #ifdef __cplusplus | 45 | #ifdef __cplusplus |
| 42 | extern "C" | 46 | extern "C" |
| 43 | { | 47 | { |
| @@ -1594,24 +1598,33 @@ aligned_alloc (size_t alignment, size_t size) | |||
| 1594 | /* Figure out how much we will need to pad this particular block | 1598 | /* Figure out how much we will need to pad this particular block |
| 1595 | to achieve the required alignment. */ | 1599 | to achieve the required alignment. */ |
| 1596 | adj = (uintptr_t) result % alignment; | 1600 | adj = (uintptr_t) result % alignment; |
| 1601 | if (adj == 0) | ||
| 1602 | adj = alignment; | ||
| 1597 | 1603 | ||
| 1598 | do | 1604 | if (adj != 1) |
| 1599 | { | 1605 | { |
| 1600 | /* Reallocate the block with only as much excess as it needs. */ | 1606 | do |
| 1601 | free (result); | 1607 | { |
| 1602 | result = malloc (size + alignment - adj); | 1608 | /* Reallocate the block with only as much excess as it |
| 1603 | if (result == NULL) /* Impossible unless interrupted. */ | 1609 | needs. */ |
| 1604 | return NULL; | 1610 | free (result); |
| 1605 | 1611 | result = malloc (size + alignment - adj); | |
| 1606 | lastadj = adj; | 1612 | if (result == NULL) /* Impossible unless interrupted. */ |
| 1607 | adj = (uintptr_t) result % alignment; | 1613 | return NULL; |
| 1608 | /* It's conceivable we might have been so unlucky as to get a | 1614 | |
| 1609 | different block with weaker alignment. If so, this block is too | 1615 | lastadj = adj; |
| 1610 | short to contain SIZE after alignment correction. So we must | 1616 | adj = (uintptr_t) result % alignment; |
| 1611 | try again and get another block, slightly larger. */ | 1617 | if (adj == 0) |
| 1612 | } while (adj < lastadj); | 1618 | adj = alignment; |
| 1619 | /* It's conceivable we might have been so unlucky as to get | ||
| 1620 | a different block with weaker alignment. If so, this | ||
| 1621 | block is too short to contain SIZE after alignment | ||
| 1622 | correction. So we must try again and get another block, | ||
| 1623 | slightly larger. */ | ||
| 1624 | } while (adj < lastadj); | ||
| 1625 | } | ||
| 1613 | 1626 | ||
| 1614 | if (adj != 0) | 1627 | if (adj != alignment) |
| 1615 | { | 1628 | { |
| 1616 | /* Record this block in the list of aligned blocks, so that `free' | 1629 | /* Record this block in the list of aligned blocks, so that `free' |
| 1617 | can identify the pointer it is passed, which will be in the middle | 1630 | can identify the pointer it is passed, which will be in the middle |