cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1745 lines · 56.8 KB · C
RawDownload
				/* Record that this arena_object slot is				 * available to be reused.				 */				ao->nextarena = unused_arena_objects;				unused_arena_objects = ao; 				/* Free the entire arena. */				free((void *)ao->address);				ao->address = 0;	/* mark unassociated */				--narenas_currently_allocated; 				UNLOCK();				return;			}			if (nf == 1) {				/* Case 2.  Put ao at the head of				 * usable_arenas.  Note that because				 * ao->nfreepools was 0 before, ao isn't				 * currently on the usable_arenas list.				 */				ao->nextarena = usable_arenas;				ao->prevarena = NULL;				if (usable_arenas)					usable_arenas->prevarena = ao;				usable_arenas = ao;				assert(usable_arenas->address != 0); 				UNLOCK();				return;			}			/* If this arena is now out of order, we need to keep			 * the list sorted.  The list is kept sorted so that			 * the "most full" arenas are used first, which allows			 * the nearly empty arenas to be completely freed.  In			 * a few un-scientific tests, it seems like this			 * approach allowed a lot more memory to be freed.			 */			if (ao->nextarena == NULL ||				     nf <= ao->nextarena->nfreepools) {				/* Case 4.  Nothing to do. */				UNLOCK();				return;			}			/* Case 3:  We have to move the arena towards the end			 * of the list, because it has more free pools than			 * the arena to its right.			 * First unlink ao from usable_arenas.			 */			if (ao->prevarena != NULL) {				/* ao isn't at the head of the list */				assert(ao->prevarena->nextarena == ao);				ao->prevarena->nextarena = ao->nextarena;			}			else {				/* ao is at the head of the list */				assert(usable_arenas == ao);				usable_arenas = ao->nextarena;			}			ao->nextarena->prevarena = ao->prevarena; 			/* Locate the new insertion point by iterating over			 * the list, using our nextarena pointer.			 */			while (ao->nextarena != NULL &&					nf > ao->nextarena->nfreepools) {				ao->prevarena = ao->nextarena;				ao->nextarena = ao->nextarena->nextarena;			} 			/* Insert ao at this point. */			assert(ao->nextarena == NULL ||				ao->prevarena == ao->nextarena->prevarena);			assert(ao->prevarena->nextarena == ao->nextarena); 			ao->prevarena->nextarena = ao;			if (ao->nextarena != NULL)				ao->nextarena->prevarena = ao; 			/* Verify that the swaps worked. */			assert(ao->nextarena == NULL ||				  nf <= ao->nextarena->nfreepools);			assert(ao->prevarena == NULL ||				  nf > ao->prevarena->nfreepools);			assert(ao->nextarena == NULL ||				ao->nextarena->prevarena == ao);			assert((usable_arenas == ao &&				ao->prevarena == NULL) ||				ao->prevarena->nextarena == ao); 			UNLOCK();			return;		}		/* Pool was full, so doesn't currently live in any list:		 * link it to the front of the appropriate usedpools[] list.		 * This mimics LRU pool usage for new allocations and		 * targets optimal filling when several pools contain		 * blocks of the same size class.		 */		--pool->ref.count;		assert(pool->ref.count > 0);	/* else the pool is empty */		size = pool->szidx;		next = usedpools[size + size];		prev = next->prevpool;		/* insert pool before next:   prev <-> pool <-> next */		pool->nextpool = next;		pool->prevpool = prev;		next->prevpool = pool;		prev->nextpool = pool;		UNLOCK();		return;	} 	/* We didn't allocate this address. */	free(p);} /* realloc.  If p is NULL, this acts like malloc(nbytes).  Else if nbytes==0, * then as the Python docs promise, we do not treat this like free(p), and * return a non-NULL result. */ #undef PyObject_Reallocvoid *PyObject_Realloc(void *p, size_t nbytes){	void *bp;	poolp pool;	size_t size; 	if (p == NULL)		return PyObject_Malloc(nbytes); 	pool = POOL_ADDR(p);	if (Py_ADDRESS_IN_RANGE(p, pool)) {		/* We're in charge of this block */		size = INDEX2SIZE(pool->szidx);		if (nbytes <= size) {			/* The block is staying the same or shrinking.  If			 * it's shrinking, there's a tradeoff:  it costs			 * cycles to copy the block to a smaller size class,			 * but it wastes memory not to copy it.  The			 * compromise here is to copy on shrink only if at			 * least 25% of size can be shaved off.			 */			if (4 * nbytes > 3 * size) {				/* It's the same,				 * or shrinking and new/old > 3/4.				 */				return p;			}			size = nbytes;		}		bp = PyObject_Malloc(nbytes);		if (bp != NULL) {			memcpy(bp, p, size);			PyObject_Free(p);		}		return bp;	}	/* We're not managing this block.  If nbytes <=	 * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this	 * block.  However, if we do, we need to copy the valid data from	 * the C-managed block to one of our blocks, and there's no portable	 * way to know how much of the memory space starting at p is valid.	 * As bug 1185883 pointed out the hard way, it's possible that the	 * C-managed block is "at the end" of allocated VM space, so that	 * a memory fault can occur if we try to copy nbytes bytes starting	 * at p.  Instead we punt:  let C continue to manage this block.         */	if (nbytes)		return realloc(p, nbytes);	/* C doesn't define the result of realloc(p, 0) (it may or may not	 * return NULL then), but Python's docs promise that nbytes==0 never	 * returns NULL.  We don't pass 0 to realloc(), to avoid that endcase	 * to begin with.  Even then, we can't be sure that realloc() won't	 * return NULL.	 */	bp = realloc(p, 1);   	return bp ? bp : p;} #else	/* ! WITH_PYMALLOC */ /*==========================================================================*//* pymalloc not enabled:  Redirect the entry points to malloc.  These will * only be used by extensions that are compiled with pymalloc enabled. */ void *PyObject_Malloc(size_t n){	return PyMem_MALLOC(n);} void *PyObject_Realloc(void *p, size_t n){	return PyMem_REALLOC(p, n);} voidPyObject_Free(void *p){	PyMem_FREE(p);}#endif /* WITH_PYMALLOC */ #ifdef PYMALLOC_DEBUG/*==========================================================================*//* A x-platform debugging allocator.  This doesn't manage memory directly, * it wraps a real allocator, adding extra debugging info to the memory blocks. */ /* Special bytes broadcast into debug memory blocks at appropriate times. * Strings of these are unlikely to be valid addresses, floats, ints or * 7-bit ASCII. */#undef CLEANBYTE#undef DEADBYTE#undef FORBIDDENBYTE#define CLEANBYTE      0xCB    /* clean (newly allocated) memory */#define DEADBYTE       0xDB    /* dead (newly freed) memory */#define FORBIDDENBYTE  0xFB    /* untouchable bytes at each end of a block */ static size_t serialno = 0;	/* incremented on each debug {m,re}alloc */ /* serialno is always incremented via calling this routine.  The point is * to supply a single place to set a breakpoint. */static voidbumpserialno(void){	++serialno;} #define SST SIZEOF_SIZE_T /* Read sizeof(size_t) bytes at p as a big-endian size_t. */static size_tread_size_t(const void *p){	const uchar *q = (const uchar *)p;	size_t result = *q++;	int i; 	for (i = SST; --i > 0; ++q)		result = (result << 8) | *q;	return result;} /* Write n as a big-endian size_t, MSB at address p, LSB at * p + sizeof(size_t) - 1. */static voidwrite_size_t(void *p, size_t n){	uchar *q = (uchar *)p + SST - 1;	int i; 	for (i = SST; --i >= 0; --q) {		*q = (uchar)(n & 0xff);		n >>= 8;	}} #ifdef Py_DEBUG/* Is target in the list?  The list is traversed via the nextpool pointers. * The list may be NULL-terminated, or circular.  Return 1 if target is in * list, else 0. */static intpool_is_in_list(const poolp target, poolp list){	poolp origlist = list;	assert(target != NULL);	if (list == NULL)		return 0;	do {		if (target == list)			return 1;		list = list->nextpool;	} while (list != NULL && list != origlist);	return 0;} #else#define pool_is_in_list(X, Y) 1 #endif	/* Py_DEBUG */ /* Let S = sizeof(size_t).  The debug malloc asks for 4*S extra bytes and   fills them with useful stuff, here calling the underlying malloc's result p: p[0: S]    Number of bytes originally asked for.  This is a size_t, big-endian (easier    to read in a memory dump).p[S: 2*S]    Copies of FORBIDDENBYTE.  Used to catch under- writes and reads.p[2*S: 2*S+n]    The requested memory, filled with copies of CLEANBYTE.    Used to catch reference to uninitialized memory.    &p[2*S] is returned.  Note that this is 8-byte aligned if pymalloc    handled the request itself.p[2*S+n: 2*S+n+S]    Copies of FORBIDDENBYTE.  Used to catch over- writes and reads.p[2*S+n+S: 2*S+n+2*S]    A serial number, incremented by 1 on each call to _PyObject_DebugMalloc    and _PyObject_DebugRealloc.    This is a big-endian size_t.    If "bad memory" is detected later, the serial number gives an    excellent way to set a breakpoint on the next run, to capture the    instant at which this block was passed out.*/ void *_PyObject_DebugMalloc(size_t nbytes){	uchar *p;	/* base address of malloc'ed block */	uchar *tail;	/* p + 2*SST + nbytes == pointer to tail pad bytes */	size_t total;	/* nbytes + 4*SST */ 	bumpserialno();	total = nbytes + 4*SST;	if (total < nbytes)		/* overflow:  can't represent total as a size_t */		return NULL; 	p = (uchar *)PyObject_Malloc(total);	if (p == NULL)		return NULL; 	write_size_t(p, nbytes);	memset(p + SST, FORBIDDENBYTE, SST); 	if (nbytes > 0)		memset(p + 2*SST, CLEANBYTE, nbytes); 	tail = p + 2*SST + nbytes;	memset(tail, FORBIDDENBYTE, SST);	write_size_t(tail + SST, serialno); 	return p + 2*SST;} /* The debug free first checks the 2*SST bytes on each end for sanity (in   particular, that the FORBIDDENBYTEs are still intact).   Then fills the original bytes with DEADBYTE.   Then calls the underlying free.*/void_PyObject_DebugFree(void *p){	uchar *q = (uchar *)p - 2*SST;  /* address returned from malloc */	size_t nbytes; 	if (p == NULL)		return;	_PyObject_DebugCheckAddress(p);	nbytes = read_size_t(q);	if (nbytes > 0)		memset(q, DEADBYTE, nbytes);	PyObject_Free(q);} void *_PyObject_DebugRealloc(void *p, size_t nbytes){	uchar *q = (uchar *)p;	uchar *tail;	size_t total;	/* nbytes + 4*SST */	size_t original_nbytes;	int i; 	if (p == NULL)		return _PyObject_DebugMalloc(nbytes); 	_PyObject_DebugCheckAddress(p);	bumpserialno();	original_nbytes = read_size_t(q - 2*SST);	total = nbytes + 4*SST;	if (total < nbytes)		/* overflow:  can't represent total as a size_t */		return NULL; 	if (nbytes < original_nbytes) {		/* shrinking:  mark old extra memory dead */		memset(q + nbytes, DEADBYTE, original_nbytes - nbytes);	} 	/* Resize and add decorations. */	q = (uchar *)PyObject_Realloc(q - 2*SST, total);	if (q == NULL)		return NULL; 	write_size_t(q, nbytes);	for (i = 0; i < SST; ++i)		assert(q[SST + i] == FORBIDDENBYTE);	q += 2*SST;	tail = q + nbytes;	memset(tail, FORBIDDENBYTE, SST);	write_size_t(tail + SST, serialno); 	if (nbytes > original_nbytes) {		/* growing:  mark new extra memory clean */		memset(q + original_nbytes, CLEANBYTE,			nbytes - original_nbytes);	} 	return q;} /* Check the forbidden bytes on both ends of the memory allocated for p. * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress, * and call Py_FatalError to kill the program. */ void_PyObject_DebugCheckAddress(const void *p){	const uchar *q = (const uchar *)p;	char *msg;	size_t nbytes;	const uchar *tail;	int i; 	if (p == NULL) {		msg = "didn't expect a NULL pointer";		goto error;	} 	/* Check the stuff at the start of p first:  if there's underwrite	 * corruption, the number-of-bytes field may be nuts, and checking	 * the tail could lead to a segfault then.	 */	for (i = SST; i >= 1; --i) {		if (*(q-i) != FORBIDDENBYTE) {			msg = "bad leading pad byte";			goto error;		}	} 	nbytes = read_size_t(q - 2*SST);	tail = q + nbytes;	for (i = 0; i < SST; ++i) {		if (tail[i] != FORBIDDENBYTE) {			msg = "bad trailing pad byte";			goto error;		}	} 	return; error:	_PyObject_DebugDumpAddress(p);	Py_FatalError(msg);} /* Display info to stderr about the memory block at p. */void_PyObject_DebugDumpAddress(const void *p){	const uchar *q = (const uchar *)p;	const uchar *tail;	size_t nbytes, serial;	int i;	int ok; 	fprintf(stderr, "Debug memory block at address p=%p:\n", p);	if (p == NULL)		return; 	nbytes = read_size_t(q - 2*SST);	fprintf(stderr, "    %" PY_FORMAT_SIZE_T "u bytes originally "	                "requested\n", nbytes); 	/* In case this is nuts, check the leading pad bytes first. */	fprintf(stderr, "    The %d pad bytes at p-%d are ", SST, SST);	ok = 1;	for (i = 1; i <= SST; ++i) {		if (*(q-i) != FORBIDDENBYTE) {			ok = 0;			break;		}	}	if (ok)		fputs("FORBIDDENBYTE, as expected.\n", stderr);	else {		fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",			FORBIDDENBYTE);		for (i = SST; i >= 1; --i) {			const uchar byte = *(q-i);			fprintf(stderr, "        at p-%d: 0x%02x", i, byte);			if (byte != FORBIDDENBYTE)				fputs(" *** OUCH", stderr);			fputc('\n', stderr);		} 		fputs("    Because memory is corrupted at the start, the "		      "count of bytes requested\n"		      "       may be bogus, and checking the trailing pad "		      "bytes may segfault.\n", stderr);	}

Lines 1001–1500 of 1745. Previous lines