aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 36ad645612d..2d256800466 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -46,6 +46,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
46#include "syssignal.h" 46#include "syssignal.h"
47#include "termhooks.h" /* For struct terminal. */ 47#include "termhooks.h" /* For struct terminal. */
48#include <setjmp.h> 48#include <setjmp.h>
49#include <verify.h>
49 50
50/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd 51/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
51 memory. Can do this only if using gmalloc.c. */ 52 memory. Can do this only if using gmalloc.c. */
@@ -733,6 +734,93 @@ xfree (POINTER_TYPE *block)
733} 734}
734 735
735 736
737/* Other parts of Emacs pass large int values to allocator functions
738 expecting ptrdiff_t. This is portable in practice, but check it to
739 be safe. */
740verify (INT_MAX <= PTRDIFF_MAX);
741
742
743/* Allocate an array of NITEMS items, each of size ITEM_SIZE.
744 Signal an error on memory exhaustion, and block interrupt input. */
745
746void *
747xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
748{
749 xassert (0 <= nitems && 0 < item_size);
750 if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
751 memory_full (SIZE_MAX);
752 return xmalloc (nitems * item_size);
753}
754
755
756/* Reallocate an array PA to make it of NITEMS items, each of size ITEM_SIZE.
757 Signal an error on memory exhaustion, and block interrupt input. */
758
759void *
760xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
761{
762 xassert (0 <= nitems && 0 < item_size);
763 if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
764 memory_full (SIZE_MAX);
765 return xrealloc (pa, nitems * item_size);
766}
767
768
769/* Grow PA, which points to an array of *NITEMS items, and return the
770 location of the reallocated array, updating *NITEMS to reflect its
771 new size. The new array will contain at least NITEMS_INCR_MIN more
772 items, but will not contain more than NITEMS_MAX items total.
773 ITEM_SIZE is the size of each item, in bytes.
774
775 ITEM_SIZE and NITEMS_INCR_MIN must be positive. *NITEMS must be
776 nonnegative. If NITEMS_MAX is -1, it is treated as if it were
777 infinity.
778
779 If PA is null, then allocate a new array instead of reallocating
780 the old one. Thus, to grow an array A without saving its old
781 contents, invoke xfree (A) immediately followed by xgrowalloc (0,
782 &NITEMS, ...).
783
784 Block interrupt input as needed. If memory exhaustion occurs, set
785 *NITEMS to zero if PA is null, and signal an error (i.e., do not
786 return). */
787
788void *
789xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
790 ptrdiff_t nitems_max, ptrdiff_t item_size)
791{
792 /* The approximate size to use for initial small allocation
793 requests. This is the largest "small" request for the GNU C
794 library malloc. */
795 enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
796
797 /* If the array is tiny, grow it to about (but no greater than)
798 DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
799 ptrdiff_t n = *nitems;
800 ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
801 ptrdiff_t half_again = n >> 1;
802 ptrdiff_t incr_estimate = max (tiny_max, half_again);
803
804 /* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
805 NITEMS_MAX, and what the C language can represent safely. */
806 ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
807 ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
808 ? nitems_max : C_language_max);
809 ptrdiff_t nitems_incr_max = n_max - n;
810 ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
811
812 xassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
813 if (! pa)
814 *nitems = 0;
815 if (nitems_incr_max < incr)
816 memory_full (SIZE_MAX);
817 n += incr;
818 pa = xrealloc (pa, n * item_size);
819 *nitems = n;
820 return pa;
821}
822
823
736/* Like strdup, but uses xmalloc. */ 824/* Like strdup, but uses xmalloc. */
737 825
738char * 826char *