X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/37d2e431f35492c14510f9960cac94c2f21b6ecb..3bf234fa520ff90db31fae85f306befdadb24532:/src/gmalloc.c diff --git a/src/gmalloc.c b/src/gmalloc.c index bc1d85ac5f..ab1dfd07db 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -1,5 +1,5 @@ /* Declarations for `malloc' and friends. - Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013 Free + Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2014 Free Software Foundation, Inc. Written May 1989 by Mike Haertel. @@ -38,6 +38,10 @@ License along with this library. If not, see . #include /* for sbrk */ #endif +#ifdef emacs +extern void emacs_abort (void); +#endif + #ifdef __cplusplus extern "C" { @@ -47,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 @@ -67,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, @@ -143,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; @@ -977,7 +986,7 @@ License along with this library. If not, see . /* 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. @@ -1306,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,13 +1496,20 @@ License along with this library. If not, see . /* 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. @@ -1559,7 +1575,7 @@ 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; @@ -1570,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) { @@ -1618,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) @@ -1631,6 +1661,15 @@ memalign (size_t alignment, size_t size) return result; } +/* An obsolete alias for aligned_alloc, for any old libraries that use + this alias. */ + +void * +memalign (size_t alignment, size_t size) +{ + return aligned_alloc (alignment, size); +} + int posix_memalign (void **memptr, size_t alignment, size_t size) { @@ -1641,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,7 +1725,7 @@ valloc (size_t size) if (pagesize == 0) pagesize = getpagesize (); - return memalign (pagesize, size); + return aligned_alloc (pagesize, size); } #ifdef GC_MCHECK @@ -1765,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; @@ -1792,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 * @@ -1857,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 }