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 b96fc1f0642..a1af0df11f0 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. */
@@ -731,6 +732,93 @@ xfree (POINTER_TYPE *block)
731} 732}
732 733
733 734
735/* Other parts of Emacs pass large int values to allocator functions
736 expecting ptrdiff_t. This is portable in practice, but check it to
737 be safe. */
738verify (INT_MAX <= PTRDIFF_MAX);
739
740
741/* Allocate an array of NITEMS items, each of size ITEM_SIZE.
742 Signal an error on memory exhaustion, and block interrupt input. */
743
744void *
745xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
746{
747 xassert (0 <= nitems && 0 < item_size);
748 if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
749 memory_full (SIZE_MAX);
750 return xmalloc (nitems * item_size);
751}
752
753
754/* Reallocate an array PA to make it of NITEMS items, each of size ITEM_SIZE.
755 Signal an error on memory exhaustion, and block interrupt input. */
756
757void *
758xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
759{
760 xassert (0 <= nitems && 0 < item_size);
761 if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
762 memory_full (SIZE_MAX);
763 return xrealloc (pa, nitems * item_size);
764}
765
766
767/* Grow PA, which points to an array of *NITEMS items, and return the
768 location of the reallocated array, updating *NITEMS to reflect its
769 new size. The new array will contain at least NITEMS_INCR_MIN more
770 items, but will not contain more than NITEMS_MAX items total.
771 ITEM_SIZE is the size of each item, in bytes.
772
773 ITEM_SIZE and NITEMS_INCR_MIN must be positive. *NITEMS must be
774 nonnegative. If NITEMS_MAX is -1, it is treated as if it were
775 infinity.
776
777 If PA is null, then allocate a new array instead of reallocating
778 the old one. Thus, to grow an array A without saving its old
779 contents, invoke xfree (A) immediately followed by xgrowalloc (0,
780 &NITEMS, ...).
781
782 Block interrupt input as needed. If memory exhaustion occurs, set
783 *NITEMS to zero if PA is null, and signal an error (i.e., do not
784 return). */
785
786void *
787xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
788 ptrdiff_t nitems_max, ptrdiff_t item_size)
789{
790 /* The approximate size to use for initial small allocation
791 requests. This is the largest "small" request for the GNU C
792 library malloc. */
793 enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
794
795 /* If the array is tiny, grow it to about (but no greater than)
796 DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
797 ptrdiff_t n = *nitems;
798 ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
799 ptrdiff_t half_again = n >> 1;
800 ptrdiff_t incr_estimate = max (tiny_max, half_again);
801
802 /* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
803 NITEMS_MAX, and what the C language can represent safely. */
804 ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
805 ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
806 ? nitems_max : C_language_max);
807 ptrdiff_t nitems_incr_max = n_max - n;
808 ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
809
810 xassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
811 if (! pa)
812 *nitems = 0;
813 if (nitems_incr_max < incr)
814 memory_full (SIZE_MAX);
815 n += incr;
816 pa = xrealloc (pa, n * item_size);
817 *nitems = n;
818 return pa;
819}
820
821
734/* Like strdup, but uses xmalloc. */ 822/* Like strdup, but uses xmalloc. */
735 823
736char * 824char *