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 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. */ | ||
| 738 | verify (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 | |||
| 744 | void * | ||
| 745 | xnmalloc (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 | |||
| 757 | void * | ||
| 758 | xnrealloc (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 | |||
| 786 | void * | ||
| 787 | xpalloc (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 | ||
| 736 | char * | 824 | char * |