diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/src/alloc.c b/src/alloc.c index 054e1ca23ca..e25d91ff8aa 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 20 | 20 | ||
| 21 | #include <config.h> | 21 | #include <config.h> |
| 22 | 22 | ||
| 23 | #include <errno.h> | ||
| 23 | #include <stdio.h> | 24 | #include <stdio.h> |
| 24 | #include <limits.h> /* For CHAR_BIT. */ | 25 | #include <limits.h> /* For CHAR_BIT. */ |
| 25 | #include <signal.h> /* For SIGABRT, SIGDANGER. */ | 26 | #include <signal.h> /* For SIGABRT, SIGDANGER. */ |
| @@ -150,7 +151,8 @@ malloc_initialize_hook (void) | |||
| 150 | } | 151 | } |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | malloc_set_state (malloc_state_ptr); | 154 | if (malloc_set_state (malloc_state_ptr) != 0) |
| 155 | emacs_abort (); | ||
| 154 | # ifndef XMALLOC_OVERRUN_CHECK | 156 | # ifndef XMALLOC_OVERRUN_CHECK |
| 155 | alloc_unexec_post (); | 157 | alloc_unexec_post (); |
| 156 | # endif | 158 | # endif |
| @@ -174,6 +176,8 @@ alloc_unexec_pre (void) | |||
| 174 | { | 176 | { |
| 175 | #ifdef DOUG_LEA_MALLOC | 177 | #ifdef DOUG_LEA_MALLOC |
| 176 | malloc_state_ptr = malloc_get_state (); | 178 | malloc_state_ptr = malloc_get_state (); |
| 179 | if (!malloc_state_ptr) | ||
| 180 | fatal ("malloc_get_state: %s", strerror (errno)); | ||
| 177 | #endif | 181 | #endif |
| 178 | #ifdef HYBRID_MALLOC | 182 | #ifdef HYBRID_MALLOC |
| 179 | bss_sbrk_did_unexec = true; | 183 | bss_sbrk_did_unexec = true; |
| @@ -485,7 +489,7 @@ static void *pure_alloc (size_t, int); | |||
| 485 | /* Return PTR rounded up to the next multiple of ALIGNMENT. */ | 489 | /* Return PTR rounded up to the next multiple of ALIGNMENT. */ |
| 486 | 490 | ||
| 487 | static void * | 491 | static void * |
| 488 | ALIGN (void *ptr, int alignment) | 492 | pointer_align (void *ptr, int alignment) |
| 489 | { | 493 | { |
| 490 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); | 494 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); |
| 491 | } | 495 | } |
| @@ -1174,16 +1178,18 @@ struct ablock | |||
| 1174 | char payload[BLOCK_BYTES]; | 1178 | char payload[BLOCK_BYTES]; |
| 1175 | struct ablock *next_free; | 1179 | struct ablock *next_free; |
| 1176 | } x; | 1180 | } x; |
| 1177 | /* `abase' is the aligned base of the ablocks. */ | 1181 | |
| 1178 | /* It is overloaded to hold the virtual `busy' field that counts | 1182 | /* ABASE is the aligned base of the ablocks. It is overloaded to |
| 1179 | the number of used ablock in the parent ablocks. | 1183 | hold a virtual "busy" field that counts twice the number of used |
| 1180 | The first ablock has the `busy' field, the others have the `abase' | 1184 | ablock values in the parent ablocks, plus one if the real base of |
| 1181 | field. To tell the difference, we assume that pointers will have | 1185 | the parent ablocks is ABASE (if the "busy" field is even, the |
| 1182 | integer values larger than 2 * ABLOCKS_SIZE. The lowest bit of `busy' | 1186 | word before the first ablock holds a pointer to the real base). |
| 1183 | is used to tell whether the real base of the parent ablocks is `abase' | 1187 | The first ablock has a "busy" ABASE, and the others have an |
| 1184 | (if not, the word before the first ablock holds a pointer to the | 1188 | ordinary pointer ABASE. To tell the difference, the code assumes |
| 1185 | real base). */ | 1189 | that pointers, when cast to uintptr_t, are at least 2 * |
| 1190 | ABLOCKS_SIZE + 1. */ | ||
| 1186 | struct ablocks *abase; | 1191 | struct ablocks *abase; |
| 1192 | |||
| 1187 | /* The padding of all but the last ablock is unused. The padding of | 1193 | /* The padding of all but the last ablock is unused. The padding of |
| 1188 | the last ablock in an ablocks is not allocated. */ | 1194 | the last ablock in an ablocks is not allocated. */ |
| 1189 | #if BLOCK_PADDING | 1195 | #if BLOCK_PADDING |
| @@ -1202,18 +1208,18 @@ struct ablocks | |||
| 1202 | 1208 | ||
| 1203 | #define ABLOCK_ABASE(block) \ | 1209 | #define ABLOCK_ABASE(block) \ |
| 1204 | (((uintptr_t) (block)->abase) <= (1 + 2 * ABLOCKS_SIZE) \ | 1210 | (((uintptr_t) (block)->abase) <= (1 + 2 * ABLOCKS_SIZE) \ |
| 1205 | ? (struct ablocks *)(block) \ | 1211 | ? (struct ablocks *) (block) \ |
| 1206 | : (block)->abase) | 1212 | : (block)->abase) |
| 1207 | 1213 | ||
| 1208 | /* Virtual `busy' field. */ | 1214 | /* Virtual `busy' field. */ |
| 1209 | #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) | 1215 | #define ABLOCKS_BUSY(a_base) ((a_base)->blocks[0].abase) |
| 1210 | 1216 | ||
| 1211 | /* Pointer to the (not necessarily aligned) malloc block. */ | 1217 | /* Pointer to the (not necessarily aligned) malloc block. */ |
| 1212 | #ifdef USE_ALIGNED_ALLOC | 1218 | #ifdef USE_ALIGNED_ALLOC |
| 1213 | #define ABLOCKS_BASE(abase) (abase) | 1219 | #define ABLOCKS_BASE(abase) (abase) |
| 1214 | #else | 1220 | #else |
| 1215 | #define ABLOCKS_BASE(abase) \ | 1221 | #define ABLOCKS_BASE(abase) \ |
| 1216 | (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1]) | 1222 | (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1]) |
| 1217 | #endif | 1223 | #endif |
| 1218 | 1224 | ||
| 1219 | /* The list of free ablock. */ | 1225 | /* The list of free ablock. */ |
| @@ -1239,7 +1245,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1239 | if (!free_ablock) | 1245 | if (!free_ablock) |
| 1240 | { | 1246 | { |
| 1241 | int i; | 1247 | int i; |
| 1242 | intptr_t aligned; /* int gets warning casting to 64-bit pointer. */ | 1248 | bool aligned; |
| 1243 | 1249 | ||
| 1244 | #ifdef DOUG_LEA_MALLOC | 1250 | #ifdef DOUG_LEA_MALLOC |
| 1245 | if (!mmap_lisp_allowed_p ()) | 1251 | if (!mmap_lisp_allowed_p ()) |
| @@ -1250,7 +1256,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1250 | abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); | 1256 | abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); |
| 1251 | #else | 1257 | #else |
| 1252 | base = malloc (ABLOCKS_BYTES); | 1258 | base = malloc (ABLOCKS_BYTES); |
| 1253 | abase = ALIGN (base, BLOCK_ALIGN); | 1259 | abase = pointer_align (base, BLOCK_ALIGN); |
| 1254 | #endif | 1260 | #endif |
| 1255 | 1261 | ||
| 1256 | if (base == 0) | 1262 | if (base == 0) |
| @@ -1295,13 +1301,14 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1295 | abase->blocks[i].x.next_free = free_ablock; | 1301 | abase->blocks[i].x.next_free = free_ablock; |
| 1296 | free_ablock = &abase->blocks[i]; | 1302 | free_ablock = &abase->blocks[i]; |
| 1297 | } | 1303 | } |
| 1298 | ABLOCKS_BUSY (abase) = (struct ablocks *) aligned; | 1304 | intptr_t ialigned = aligned; |
| 1305 | ABLOCKS_BUSY (abase) = (struct ablocks *) ialigned; | ||
| 1299 | 1306 | ||
| 1300 | eassert (0 == ((uintptr_t) abase) % BLOCK_ALIGN); | 1307 | eassert ((uintptr_t) abase % BLOCK_ALIGN == 0); |
| 1301 | eassert (ABLOCK_ABASE (&abase->blocks[3]) == abase); /* 3 is arbitrary */ | 1308 | eassert (ABLOCK_ABASE (&abase->blocks[3]) == abase); /* 3 is arbitrary */ |
| 1302 | eassert (ABLOCK_ABASE (&abase->blocks[0]) == abase); | 1309 | eassert (ABLOCK_ABASE (&abase->blocks[0]) == abase); |
| 1303 | eassert (ABLOCKS_BASE (abase) == base); | 1310 | eassert (ABLOCKS_BASE (abase) == base); |
| 1304 | eassert (aligned == (intptr_t) ABLOCKS_BUSY (abase)); | 1311 | eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned); |
| 1305 | } | 1312 | } |
| 1306 | 1313 | ||
| 1307 | abase = ABLOCK_ABASE (free_ablock); | 1314 | abase = ABLOCK_ABASE (free_ablock); |
| @@ -1337,12 +1344,14 @@ lisp_align_free (void *block) | |||
| 1337 | ablock->x.next_free = free_ablock; | 1344 | ablock->x.next_free = free_ablock; |
| 1338 | free_ablock = ablock; | 1345 | free_ablock = ablock; |
| 1339 | /* Update busy count. */ | 1346 | /* Update busy count. */ |
| 1340 | ABLOCKS_BUSY (abase) | 1347 | intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2; |
| 1341 | = (struct ablocks *) (-2 + (intptr_t) ABLOCKS_BUSY (abase)); | 1348 | eassume (0 <= busy && busy <= 2 * ABLOCKS_SIZE - 1); |
| 1349 | ABLOCKS_BUSY (abase) = (struct ablocks *) busy; | ||
| 1342 | 1350 | ||
| 1343 | if (2 > (intptr_t) ABLOCKS_BUSY (abase)) | 1351 | if (busy < 2) |
| 1344 | { /* All the blocks are free. */ | 1352 | { /* All the blocks are free. */ |
| 1345 | int i = 0, aligned = (intptr_t) ABLOCKS_BUSY (abase); | 1353 | int i = 0; |
| 1354 | bool aligned = busy; | ||
| 1346 | struct ablock **tem = &free_ablock; | 1355 | struct ablock **tem = &free_ablock; |
| 1347 | struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1]; | 1356 | struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1]; |
| 1348 | 1357 | ||
| @@ -5169,7 +5178,7 @@ pure_alloc (size_t size, int type) | |||
| 5169 | { | 5178 | { |
| 5170 | /* Allocate space for a Lisp object from the beginning of the free | 5179 | /* Allocate space for a Lisp object from the beginning of the free |
| 5171 | space with taking account of alignment. */ | 5180 | space with taking account of alignment. */ |
| 5172 | result = ALIGN (purebeg + pure_bytes_used_lisp, GCALIGNMENT); | 5181 | result = pointer_align (purebeg + pure_bytes_used_lisp, GCALIGNMENT); |
| 5173 | pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size; | 5182 | pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size; |
| 5174 | } | 5183 | } |
| 5175 | else | 5184 | else |
| @@ -6126,7 +6135,7 @@ mark_face_cache (struct face_cache *c) | |||
| 6126 | int i, j; | 6135 | int i, j; |
| 6127 | for (i = 0; i < c->used; ++i) | 6136 | for (i = 0; i < c->used; ++i) |
| 6128 | { | 6137 | { |
| 6129 | struct face *face = FACE_OPT_FROM_ID (c->f, i); | 6138 | struct face *face = FACE_FROM_ID_OR_NULL (c->f, i); |
| 6130 | 6139 | ||
| 6131 | if (face) | 6140 | if (face) |
| 6132 | { | 6141 | { |