[Python-checkins] r42755 - python/branches/tim-obmalloc/Objects/obmalloc.c

tim.peters python-checkins at python.org
Wed Mar 1 23:57:24 CET 2006


Author: tim.peters
Date: Wed Mar  1 23:57:23 2006
New Revision: 42755

Modified:
   python/branches/tim-obmalloc/Objects/obmalloc.c
Log:
Fixed a logic error in doubly-linked list fiddling.

Resolved an overlooked XXX.

Code fiddling to reduce the deepest nesting by a level.

This is all I want to do, except to fix the new
Py_ADDRESS_IN_RANGE endcase error.


Modified: python/branches/tim-obmalloc/Objects/obmalloc.c
==============================================================================
--- python/branches/tim-obmalloc/Objects/obmalloc.c	(original)
+++ python/branches/tim-obmalloc/Objects/obmalloc.c	Wed Mar  1 23:57:23 2006
@@ -747,7 +747,6 @@
 
 			/* This moves the arena *towards* the head of the list
 			but it is already at the head of the list: do nothing */
-			/* XXX what did that mean? */
 			--usable_arenas->nfreepools;
 			if (usable_arenas->nfreepools == 0) {
 				/* Unlink the arena: it's completely
@@ -907,10 +906,20 @@
 			ao->freepools = pool;
 			nf = ++ao->nfreepools;
 
+			/* All the rest is arena management.  We just freed
+			 * a pool, and there are 4 cases for arena mgmt:
+			 * 1. If all the pools are free, return the arena to
+			 *    the system free().
+			 * 2. If this is the only free pool in the arena,
+			 *    add the arena back to the `usable_arenas` list.
+			 * 3. If the "next" arena has a smaller count of
+			 *    of free pulls, we have to "push this arena right"
+			 *    to restore that `usable_arenas` is sorted in
+			 *    order of nfreepools.
+			 * 4. Else there's nothing more to do.
+			 */
 			if (nf == ao->ntotalpools) {
-				/* This arena is completely deallocated.
-				 * Unlink it from the partially allocated
-				 * arenas.
+				/* Case 1.  First unlink ao from usable_arenas.
 				 */
 				assert(ao->prevarena == NULL ||
 				       ao->prevarena->address != 0);
@@ -930,14 +939,12 @@
 					ao->prevarena->nextarena =
 						ao->nextarena;
 				}
-
 				/* Fix the pointer in the nextarena. */
 				if (ao->nextarena != NULL) {
 					assert(ao->nextarena->prevarena == ao);
 					ao->nextarena->prevarena =
 						ao->prevarena;
 				}
-
 				/* Record that this arena_object slot is
 				 * available to be reused.
 				 */
@@ -946,23 +953,28 @@
 
 				/* Free the entire arena. */
 				free((void *)ao->address);
-				ao->address = 0;
+				ao->address = 0;	/* mark unassociated */
 				--narenas_currently_allocated;
+
+				UNLOCK();
+				return;
 			}
-			else if (nf == 1) {
-				/* If this arena was completely allocated,
-				 * go link it to the head of the partially
-				 * allocated list.
+
+			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;
-
-				/* Fix the pointer in the nextarena. */
-				if (ao->nextarena != NULL)
-					ao->nextarena->prevarena = 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
@@ -971,57 +983,58 @@
 			 * a few un-scientific tests, it seems like this
 			 * approach allowed a lot more memory to be freed.
 			 */
-			else if (ao->nextarena != NULL &&
-				     nf > ao->nextarena->nfreepools) {
-				/* We have to move the arena towards the end
-				 * of the list.
-				 */
-				struct arena_object** lastPointer;
-				if (ao->prevarena != NULL)
-					lastPointer =
-						&ao->prevarena->nextarena;
-				else
-					lastPointer = &usable_arenas;
-				assert(*lastPointer == ao);
-
-				/* Step one: unlink the arena from the list. */
-				*lastPointer = ao->nextarena;
-				ao->nextarena->prevarena = ao->prevarena;
-
-				/* Step two: 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;
-				}
-
-				/* Step three: insert the arena 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;
-				}
+			if (ao->nextarena == NULL ||
+				     nf <= ao->nextarena->nfreepools) {
+				/* Case 4.  Nothing to do. */
+				UNLOCK();
+				return;
+			}
 
-				/* 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);
+			/* 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;


More information about the Python-checkins mailing list