From: Gurusamy Sarathy Date: Fri, 27 Nov 1998 14:46:18 +0000 (+0000) Subject: malloc bugfix and documentation from Ilya Zakharevich X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e93972868551f65a3c55f75eec9e71a0cd42d790;p=p5sagit%2Fp5-mst-13.2.git malloc bugfix and documentation from Ilya Zakharevich Date: Tue, 24 Nov 1998 17:24:55 -0500 (EST) Message-Id: <199811242224.RAA22618@monk.mps.ohio-state.edu> Subject: [PATCH 5.005_*] Re: Internal coredump -- Date: Thu, 26 Nov 1998 03:06:10 -0500 (EST) Message-Id: <199811260806.DAA28913@monk.mps.ohio-state.edu> Subject: [PATCH 5.005_*] malloc.c documentation p4raw-id: //depot/perl@2325 --- diff --git a/malloc.c b/malloc.c index 2006e3f..ba4aac2 100644 --- a/malloc.c +++ b/malloc.c @@ -290,6 +290,69 @@ # define DEBUG_m(a) if (PL_debug & 128) a #endif +/* + * Layout of memory: + * ~~~~~~~~~~~~~~~~ + * The memory is broken into "blocks" which occupy multiples of 2K (and + * generally speaking, have size "close" to a power of 2). The addresses + * of such *unused* blocks are kept in nextf[i] with big enough i. (nextf + * is an array of linked lists.) (Addresses of used blocks are not known.) + * + * Moreover, since the algorithm may try to "bite" smaller blocks of out + * of unused bigger ones, there are also regions of "irregular" size, + * managed separately, by a linked list chunk_chain. + * + * The third type of storage is the sbrk()ed-but-not-yet-used space, its + * end and size are kept in last_sbrk_top and sbrked_remains. + * + * Growing blocks "in place": + * ~~~~~~~~~~~~~~~~~~~~~~~~~ + * The address of the block with the greatest address is kept in last_op + * (if not known, last_op is 0). If it is known that the memory above + * last_op is not continuous, or contains a chunk from chunk_chain, + * last_op is set to 0. + * + * The chunk with address last_op may be grown by expanding into + * sbrk()ed-but-not-yet-used space, or trying to sbrk() more continuous + * memory. + * + * Management of last_op: + * ~~~~~~~~~~~~~~~~~~~~~ + * + * free() never changes the boundaries of blocks, so is not relevant. + * + * The only way realloc() may change the boundaries of blocks is if it + * grows a block "in place". However, in the case of success such a + * chunk is automatically last_op, and it remains last_op. In the case + * of failure getpages_adjacent() clears last_op. + * + * malloc() may change blocks by calling morecore() only. + * + * morecore() may create new blocks by: + * a) biting pieces from chunk_chain (cannot create one above last_op); + * b) biting a piece from an unused block (if block was last_op, this + * may create a chunk from chain above last_op, thus last_op is + * invalidated in such a case). + * c) biting of sbrk()ed-but-not-yet-used space. This creates + * a block which is last_op. + * d) Allocating new pages by calling getpages(); + * + * getpages() creates a new block. It marks last_op at the bottom of + * the chunk of memory it returns. + * + * Active pages footprint: + * ~~~~~~~~~~~~~~~~~~~~~~ + * Note that we do not need to traverse the lists in nextf[i], just take + * the first element of this list. However, we *need* to traverse the + * list in chunk_chain, but most the time it should be a very short one, + * so we do not step on a lot of pages we are not going to use. + * + * Flaws: + * ~~~~~ + * get_from_bigger_buckets(): forget to increment price => Quite + * aggressive. + */ + /* I don't much care whether these are defined in sys/types.h--LAW */ #define u_char unsigned char @@ -990,11 +1053,15 @@ getpages(int needed, int *nblksp, int bucket) /* Common case, anything is fine. */ sbrk_good++; ovp = (union overhead *) (cp - sbrked_remains); + last_op = cp - sbrked_remains; sbrked_remains = require - (needed - sbrked_remains); } else if (cp == (char *)-1) { /* no more room! */ ovp = (union overhead *)emergency_sbrk(needed); if (ovp == (union overhead *)-1) return 0; + if (((char*)ovp) > last_op) { /* Cannot happen with current emergency_sbrk() */ + last_op = 0; + } return ovp; } else { /* Non-continuous or first sbrk(). */ long add = sbrked_remains; @@ -1089,9 +1156,9 @@ getpages(int needed, int *nblksp, int bucket) } #endif sbrked_remains = require - needed; + last_op = cp; } last_sbrk_top = cp + require; - last_op = (char*) cp; #ifdef DEBUGGING_MSTATS goodsbrk += require; #endif