diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 88 |
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. */ | ||
| 740 | verify (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 | |||
| 746 | void * | ||
| 747 | xnmalloc (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 | |||
| 759 | void * | ||
| 760 | xnrealloc (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 | |||
| 788 | void * | ||
| 789 | xpalloc (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 | ||
| 738 | char * | 826 | char * |