diff options
| author | Paul Eggert | 2011-09-03 16:03:38 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-09-03 16:03:38 -0700 |
| commit | b49e353d9d01adbe60bc5d0b1658b4ef978b0b06 (patch) | |
| tree | 9f2ffa6f7a6562abf661a4951012b488ad8b1ae7 /src/alloc.c | |
| parent | 74b880cbc18bd0194c7b1fc44c4a983ee05adae2 (diff) | |
| parent | bc3200871917d5c54c8c4299a06bf8f8ba2ea02d (diff) | |
| download | emacs-b49e353d9d01adbe60bc5d0b1658b4ef978b0b06.tar.gz emacs-b49e353d9d01adbe60bc5d0b1658b4ef978b0b06.zip | |
Merge from trunk.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 106 |
1 files changed, 98 insertions, 8 deletions
diff --git a/src/alloc.c b/src/alloc.c index b96fc1f0642..2d256800466 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -24,7 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 24 | 24 | ||
| 25 | #include <signal.h> | 25 | #include <signal.h> |
| 26 | 26 | ||
| 27 | #ifdef HAVE_GTK_AND_PTHREAD | 27 | #ifdef HAVE_PTHREAD |
| 28 | #include <pthread.h> | 28 | #include <pthread.h> |
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| @@ -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. */ |
| @@ -84,13 +85,15 @@ extern size_t __malloc_extra_blocks; | |||
| 84 | #endif /* not DOUG_LEA_MALLOC */ | 85 | #endif /* not DOUG_LEA_MALLOC */ |
| 85 | 86 | ||
| 86 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT | 87 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT |
| 87 | #ifdef HAVE_GTK_AND_PTHREAD | 88 | #ifdef HAVE_PTHREAD |
| 88 | 89 | ||
| 89 | /* When GTK uses the file chooser dialog, different backends can be loaded | 90 | /* When GTK uses the file chooser dialog, different backends can be loaded |
| 90 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | 91 | dynamically. One such a backend is the Gnome VFS backend that gets loaded |
| 91 | if you run Gnome. That backend creates several threads and also allocates | 92 | if you run Gnome. That backend creates several threads and also allocates |
| 92 | memory with malloc. | 93 | memory with malloc. |
| 93 | 94 | ||
| 95 | Also, gconf and gsettings may create several threads. | ||
| 96 | |||
| 94 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | 97 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* |
| 95 | functions below are called from malloc, there is a chance that one | 98 | functions below are called from malloc, there is a chance that one |
| 96 | of these threads preempts the Emacs main thread and the hook variables | 99 | of these threads preempts the Emacs main thread and the hook variables |
| @@ -122,12 +125,12 @@ static pthread_mutex_t alloc_mutex; | |||
| 122 | } \ | 125 | } \ |
| 123 | while (0) | 126 | while (0) |
| 124 | 127 | ||
| 125 | #else /* ! defined HAVE_GTK_AND_PTHREAD */ | 128 | #else /* ! defined HAVE_PTHREAD */ |
| 126 | 129 | ||
| 127 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | 130 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT |
| 128 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | 131 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT |
| 129 | 132 | ||
| 130 | #endif /* ! defined HAVE_GTK_AND_PTHREAD */ | 133 | #endif /* ! defined HAVE_PTHREAD */ |
| 131 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ | 134 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ |
| 132 | 135 | ||
| 133 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer | 136 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| @@ -731,6 +734,93 @@ xfree (POINTER_TYPE *block) | |||
| 731 | } | 734 | } |
| 732 | 735 | ||
| 733 | 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 | |||
| 734 | /* Like strdup, but uses xmalloc. */ | 824 | /* Like strdup, but uses xmalloc. */ |
| 735 | 825 | ||
| 736 | char * | 826 | char * |
| @@ -1265,7 +1355,7 @@ emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) | |||
| 1265 | } | 1355 | } |
| 1266 | 1356 | ||
| 1267 | 1357 | ||
| 1268 | #ifdef HAVE_GTK_AND_PTHREAD | 1358 | #ifdef HAVE_PTHREAD |
| 1269 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | 1359 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a |
| 1270 | normal malloc. Some thread implementations need this as they call | 1360 | normal malloc. Some thread implementations need this as they call |
| 1271 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | 1361 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then |
| @@ -1278,7 +1368,7 @@ reset_malloc_hooks (void) | |||
| 1278 | __malloc_hook = old_malloc_hook; | 1368 | __malloc_hook = old_malloc_hook; |
| 1279 | __realloc_hook = old_realloc_hook; | 1369 | __realloc_hook = old_realloc_hook; |
| 1280 | } | 1370 | } |
| 1281 | #endif /* HAVE_GTK_AND_PTHREAD */ | 1371 | #endif /* HAVE_PTHREAD */ |
| 1282 | 1372 | ||
| 1283 | 1373 | ||
| 1284 | /* Called from main to set up malloc to use our hooks. */ | 1374 | /* Called from main to set up malloc to use our hooks. */ |
| @@ -1286,7 +1376,7 @@ reset_malloc_hooks (void) | |||
| 1286 | void | 1376 | void |
| 1287 | uninterrupt_malloc (void) | 1377 | uninterrupt_malloc (void) |
| 1288 | { | 1378 | { |
| 1289 | #ifdef HAVE_GTK_AND_PTHREAD | 1379 | #ifdef HAVE_PTHREAD |
| 1290 | #ifdef DOUG_LEA_MALLOC | 1380 | #ifdef DOUG_LEA_MALLOC |
| 1291 | pthread_mutexattr_t attr; | 1381 | pthread_mutexattr_t attr; |
| 1292 | 1382 | ||
| @@ -1300,7 +1390,7 @@ uninterrupt_malloc (void) | |||
| 1300 | and the bundled gmalloc.c doesn't require it. */ | 1390 | and the bundled gmalloc.c doesn't require it. */ |
| 1301 | pthread_mutex_init (&alloc_mutex, NULL); | 1391 | pthread_mutex_init (&alloc_mutex, NULL); |
| 1302 | #endif /* !DOUG_LEA_MALLOC */ | 1392 | #endif /* !DOUG_LEA_MALLOC */ |
| 1303 | #endif /* HAVE_GTK_AND_PTHREAD */ | 1393 | #endif /* HAVE_PTHREAD */ |
| 1304 | 1394 | ||
| 1305 | if (__free_hook != emacs_blocked_free) | 1395 | if (__free_hook != emacs_blocked_free) |
| 1306 | old_free_hook = __free_hook; | 1396 | old_free_hook = __free_hook; |