diff options
author | Eli Zaretskii <eliz@gnu.org> | 2014-03-04 19:35:15 +0200 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2014-03-04 19:35:15 +0200 |
commit | 201572eca80ea77d8e1c25099b4aa2d98bc4d402 (patch) | |
tree | b2aedb9d508729a1b3b30bfe23c2bb13fc42d54f /src/gmalloc.c | |
parent | 3106d59bce024deba9d6b2193531c09b6a6d3c91 (diff) | |
download | emacs-201572eca80ea77d8e1c25099b4aa2d98bc4d402.tar.gz |
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/>. #include <w32heap.h> /* for sbrk */ #endif +#ifdef emacs +extern void emacs_abort (void); +#endif + #ifdef __cplusplus extern "C" { @@ -1594,24 +1598,33 @@ aligned_alloc (size_t alignment, size_t size) /* Figure out how much we will need to pad this particular block to achieve the required alignment. */ adj = (uintptr_t) result % alignment; + if (adj == 0) + adj = alignment; - do + if (adj != 1) { - /* Reallocate the block with only as much excess as it needs. */ - free (result); - result = malloc (size + alignment - adj); - if (result == NULL) /* Impossible unless interrupted. */ - return NULL; - - lastadj = adj; - adj = (uintptr_t) result % alignment; - /* It's conceivable we might have been so unlucky as to get a - different block with weaker alignment. If so, this block is too - short to contain SIZE after alignment correction. So we must - try again and get another block, slightly larger. */ - } while (adj < lastadj); + do + { + /* Reallocate the block with only as much excess as it + needs. */ + free (result); + result = malloc (size + alignment - adj); + if (result == NULL) /* Impossible unless interrupted. */ + return NULL; + + lastadj = adj; + adj = (uintptr_t) result % alignment; + if (adj == 0) + adj = alignment; + /* It's conceivable we might have been so unlucky as to get + a different block with weaker alignment. If so, this + block is too short to contain SIZE after alignment + correction. So we must try again and get another block, + slightly larger. */ + } while (adj < lastadj); + } - if (adj != 0) + if (adj != alignment) { /* Record this block in the list of aligned blocks, so that `free' can identify the pointer it is passed, which will be in the middle |