X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/36a305a723c63fd345be65c536c52fe9765c14be..3bf234fa520ff90db31fae85f306befdadb24532:/src/gmalloc.c diff --git a/src/gmalloc.c b/src/gmalloc.c index dc58495566..ab1dfd07db 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -1,6 +1,6 @@ /* Declarations for `malloc' and friends. - Copyright (C) 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2002, 2003, 2004, - 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2014 Free + Software Foundation, Inc. Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or @@ -14,9 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -40,6 +38,10 @@ Fifth Floor, Boston, MA 02110-1301, USA. #include /* for sbrk */ #endif +#ifdef emacs +extern void emacs_abort (void); +#endif + #ifdef __cplusplus extern "C" { @@ -49,17 +51,18 @@ extern "C" /* Allocate SIZE bytes of memory. */ -extern void *malloc (size_t size); +extern void *malloc (size_t size) ATTRIBUTE_MALLOC_SIZE ((1)); /* Re-allocate the previously allocated block in ptr, making the new block SIZE bytes long. */ -extern void *realloc (void *ptr, size_t size); +extern void *realloc (void *ptr, size_t size) ATTRIBUTE_ALLOC_SIZE ((2)); /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern void *calloc (size_t nmemb, size_t size); +extern void *calloc (size_t nmemb, size_t size) ATTRIBUTE_MALLOC_SIZE ((1,2)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ extern void free (void *ptr); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ #ifdef MSDOS +extern void *aligned_alloc (size_t, size_t); extern void *memalign (size_t, size_t); extern int posix_memalign (void **, size_t, size_t); #endif @@ -69,6 +72,10 @@ extern int posix_memalign (void **, size_t, size_t); extern void malloc_enable_thread (void); #endif +#ifdef emacs +extern void emacs_abort (void); +#endif + /* The allocator divides the heap into blocks of fixed size; large requests receive one or more whole blocks, and small requests receive a fragment of a block. Fragment sizes are powers of two, @@ -145,11 +152,11 @@ struct list /* Free list headers for each fragment size. */ extern struct list _fraghead[]; -/* List of blocks allocated with `memalign' (or `valloc'). */ +/* List of blocks allocated with aligned_alloc and friends. */ struct alignlist { struct alignlist *next; - void *aligned; /* The address that memaligned returned. */ + void *aligned; /* The address that aligned_alloc returned. */ void *exact; /* The address that malloc returned. */ }; extern struct alignlist *_aligned_blocks; @@ -292,9 +299,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -972,9 +977,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -983,7 +986,7 @@ Fifth Floor, Boston, MA 02110-1301, USA. /* Debugging hook for free. */ void (*__free_hook) (void *__ptr); -/* List of blocks allocated by memalign. */ +/* List of blocks allocated by aligned_alloc. */ struct alignlist *_aligned_blocks = NULL; /* Return memory to the heap. @@ -1286,9 +1289,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -1314,8 +1315,8 @@ special_realloc (void *ptr, size_t size) type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE : (size_t) 1 << type; result = _malloc_internal_nolock (size); - if (result != NULL) - memcpy (result, ptr, min (oldsize, size)); + if (result) + return memcpy (result, ptr, min (oldsize, size)); return result; } #endif @@ -1487,9 +1488,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -1497,13 +1496,20 @@ Fifth Floor, Boston, MA 02110-1301, USA. /* Allocate an array of NMEMB elements each SIZE bytes long. The entire array is initialized to zeros. */ void * -calloc (register size_t nmemb, register size_t size) +calloc (size_t nmemb, size_t size) { - register void *result = malloc (nmemb * size); + void *result; + size_t bytes = nmemb * size; - if (result != NULL) - (void) memset (result, 0, nmemb * size); + if (size != 0 && bytes / size != nmemb) + { + errno = ENOMEM; + return NULL; + } + result = malloc (bytes); + if (result) + return memset (result, 0, bytes); return result; } /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. @@ -1520,9 +1526,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with the GNU C Library; see the file COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, -MA 02110-1301, USA. */ +along with the GNU C Library. If not, see . */ /* uClibc defines __GNU_LIBRARY__, but it is not completely compatible. */ @@ -1566,14 +1570,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. */ +License along with this library. If not, see . */ void *(*__memalign_hook) (size_t size, size_t alignment); void * -memalign (size_t alignment, size_t size) +aligned_alloc (size_t alignment, size_t size) { void *result; size_t adj, lastadj; @@ -1584,29 +1586,43 @@ memalign (size_t alignment, size_t size) /* Allocate a block with enough extra space to pad the block with up to (ALIGNMENT - 1) bytes if necessary. */ + if (- size < alignment) + { + errno = ENOMEM; + return NULL; + } result = malloc (size + alignment - 1); if (result == NULL) return NULL; /* Figure out how much we will need to pad this particular block to achieve the required alignment. */ - adj = (uintptr_t) result % alignment; + adj = alignment - (uintptr_t) result % alignment; + if (adj == alignment) + adj = 0; - do + if (adj != alignment - 1) { - /* Reallocate the block with only as much excess as it needs. */ - free (result); - result = malloc (adj + size); - 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 + adj); + if (result == NULL) /* Impossible unless interrupted. */ + return NULL; + + lastadj = adj; + adj = alignment - (uintptr_t) result % alignment; + if (adj == alignment) + adj = 0; + /* 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) { @@ -1632,7 +1648,7 @@ memalign (size_t alignment, size_t size) if (l != NULL) { l->exact = result; - result = l->aligned = (char *) result + alignment - adj; + result = l->aligned = (char *) result + adj; } UNLOCK_ALIGNED_BLOCKS (); if (l == NULL) @@ -1645,13 +1661,14 @@ memalign (size_t alignment, size_t size) return result; } -#ifndef ENOMEM -#define ENOMEM 12 -#endif +/* An obsolete alias for aligned_alloc, for any old libraries that use + this alias. */ -#ifndef EINVAL -#define EINVAL 22 -#endif +void * +memalign (size_t alignment, size_t size) +{ + return aligned_alloc (alignment, size); +} int posix_memalign (void **memptr, size_t alignment, size_t size) @@ -1663,7 +1680,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size) || (alignment & (alignment - 1)) != 0) return EINVAL; - mem = memalign (alignment, size); + mem = aligned_alloc (alignment, size); if (mem == NULL) return ENOMEM; @@ -1686,9 +1703,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -1710,7 +1725,7 @@ valloc (size_t size) if (pagesize == 0) pagesize = getpagesize (); - return memalign (pagesize, size); + return aligned_alloc (pagesize, size); } #ifdef GC_MCHECK @@ -1730,9 +1745,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public -License along with this library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. +License along with this library. If not, see . The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ @@ -1791,6 +1804,22 @@ freehook (void *ptr) if (ptr) { + struct alignlist *l; + + /* If the block was allocated by aligned_alloc, its real pointer + to free is recorded in _aligned_blocks; find that. */ + PROTECT_MALLOC_STATE (0); + LOCK_ALIGNED_BLOCKS (); + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == ptr) + { + l->aligned = NULL; /* Mark the slot in the list as free. */ + ptr = l->exact; + break; + } + UNLOCK_ALIGNED_BLOCKS (); + PROTECT_MALLOC_STATE (1); + hdr = ((struct hdr *) ptr) - 1; checkhdr (hdr); hdr->magic = MAGICFREE; @@ -1818,8 +1847,7 @@ mallochook (size_t size) hdr->size = size; hdr->magic = MAGICWORD; ((char *) &hdr[1])[size] = MAGICBYTE; - memset (hdr + 1, MALLOCFLOOD, size); - return hdr + 1; + return memset (hdr + 1, MALLOCFLOOD, size); } static void * @@ -1883,7 +1911,11 @@ mabort (enum mcheck_status status) #else fprintf (stderr, "mcheck: %s\n", msg); fflush (stderr); +# ifdef emacs + emacs_abort (); +# else abort (); +# endif #endif }