X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fpool.c;h=41d4e74862cf703bc738039025e17d8818a9c102;hb=29c51e39acf3554a56aa2adc9451cc5fd70318ae;hp=ca05039a7a011e5c3ca39aff172acca6df9ab675;hpb=cb4033020c8a24d573814e6ac9192046bffdccac;p=pspp-builds.git diff --git a/src/pool.c b/src/pool.c index ca05039a..41d4e748 100644 --- a/src/pool.c +++ b/src/pool.c @@ -20,10 +20,10 @@ #if HAVE_CONFIG_H #include #endif -#include +#include "pool.h" +#include "error.h" #include #include "alloc.h" -#include "pool.h" #include "str.h" /* Fast, low-overhead memory block suballocator. */ @@ -113,9 +113,7 @@ union align /*#define DISCRETE_BLOCKS 1*/ /* Enable debug code if appropriate. */ -#undef DEBUGGING #if SELF_TEST -#define DEBUGGING 1 #endif /* Size of each block allocated in the pool, in bytes. @@ -142,6 +140,7 @@ static long serial = 0; /* Prototypes. */ static void add_gizmo (struct pool *, struct pool_gizmo *); static void free_gizmo (struct pool_gizmo *); +static void free_all_gizmos (struct pool *pool); static void delete_gizmo (struct pool *, struct pool_gizmo *); #if !PSPP @@ -182,20 +181,14 @@ pool_destroy (struct pool *pool) if (pool == NULL) return; + /* Remove this pool from its parent's list of gizmos. */ if (pool->parent) - delete_gizmo (pool, + delete_gizmo (pool->parent, (void *) (((char *) pool) + POOL_SIZE + POOL_BLOCK_SIZE)); - { - struct pool_gizmo *cur, *next; + free_all_gizmos (pool); - for (cur = pool->gizmos; cur; cur = next) - { - next = cur->next; - free_gizmo (cur); - } - } - + /* Free all the memory. */ { struct pool_block *cur, *next; @@ -207,6 +200,30 @@ pool_destroy (struct pool *pool) } } } + +/* Release all the memory and gizmos in POOL. + Blocks are not given back with free() but kept for later + allocations. To give back memory, use a subpool instead. */ +void +pool_clear (struct pool *pool) +{ + free_all_gizmos (pool); + + /* Zero out block sizes. */ + { + struct pool_block *cur; + + cur = pool->blocks; + do + { + cur->ofs = POOL_BLOCK_SIZE; + if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) + cur->ofs += POOL_SIZE; + cur = cur->next; + } + while (cur != pool->blocks); + } +} /* Suballocation routines. */ @@ -217,9 +234,10 @@ pool_alloc (struct pool *pool, size_t amt) { assert (pool != NULL); -#if !DISCRETE_BLOCKS /* Help identify source of bugs for Checker users. */ +#ifndef DISCRETE_BLOCKS if (amt <= MAX_SUBALLOC) { + /* If there is space in this block, take it. */ struct pool_block *b = pool->blocks; b->ofs = ROUND_UP (b->ofs, ALIGN_SIZE); if (b->ofs + amt <= BLOCK_SIZE) @@ -229,49 +247,81 @@ pool_alloc (struct pool *pool, size_t amt) return p; } - b = xmalloc (BLOCK_SIZE); - b->next = pool->blocks; - b->prev = pool->blocks->prev; - b->ofs = POOL_BLOCK_SIZE + amt; - - pool->blocks->prev->next = b; - pool->blocks = pool->blocks->prev = b; - - return ((char *) b) + POOL_BLOCK_SIZE; + /* No space in this block, so we must make other + arrangements. */ + if (b->next->ofs == 0) + { + /* The next block is empty. Use it. */ + b = b->next; + b->ofs = POOL_BLOCK_SIZE; + if ((char *) b + POOL_BLOCK_SIZE == (char *) pool) + b->ofs += POOL_SIZE; + } + else + { + /* Create a new block at the start of the list. */ + b = xmalloc (BLOCK_SIZE); + b->next = pool->blocks; + b->prev = pool->blocks->prev; + b->ofs = POOL_BLOCK_SIZE; + pool->blocks->prev->next = b; + pool->blocks->prev = b; + } + pool->blocks = b; + + /* Allocate space from B. */ + b->ofs += amt; + return ((char *) b) + b->ofs - amt; } else -#endif /* !DISCRETE_BLOCKS */ +#endif return pool_malloc (pool, amt); } -/* Duplicates STRING within POOL and returns a pointer to the - duplicate. */ +/* Duplicates STRING, which has LENGTH characters, within POOL, + and returns a pointer to the duplicate. LENGTH should not + include the null terminator, which is always added to the + duplicate. For use only with strings, because the returned + pointere may not be aligned properly for other types. */ char * -pool_strdup (struct pool *pool, const char *string) +pool_strndup (struct pool *pool, const char *string, size_t length) { - size_t amt; - void *p; + size_t size; + char *copy; assert (pool && string); - amt = strlen (string) + 1; + size = length + 1; /* Note that strings need not be aligned on any boundary. */ +#ifndef DISCRETE_BLOCKS { -#if !DISCRETE_BLOCKS struct pool_block *const b = pool->blocks; - if (b->ofs + amt <= BLOCK_SIZE) + if (b->ofs + size <= BLOCK_SIZE) { - p = ((char *) b) + b->ofs; - b->ofs += amt; + copy = ((char *) b) + b->ofs; + b->ofs += size; } else -#endif - p = pool_alloc (pool, amt); + copy = pool_alloc (pool, size); } +#else + copy = pool_alloc (pool, size); +#endif - memcpy (p, string, amt); - return p; + memcpy (copy, string, length); + copy[length] = '\0'; + return copy; +} + +/* Duplicates null-terminated STRING, within POOL, and returns a + pointer to the duplicate. For use only with strings, because + the returned pointere may not be aligned properly for other + types. */ +char * +pool_strdup (struct pool *pool, const char *string) +{ + return pool_strndup (pool, string, strlen (string)); } /* Standard allocation routines. */ @@ -483,7 +533,10 @@ pool_mark (struct pool *pool, struct pool_mark *mark) mark->serial = serial; } -/* Restores to POOL the state recorded in MARK. */ +/* Restores to POOL the state recorded in MARK. + Emptied blocks are not given back with free() but kept for + later allocations. To get that behavior, use a subpool + instead. */ void pool_release (struct pool *pool, const struct pool_mark *mark) { @@ -508,21 +561,16 @@ pool_release (struct pool *pool, const struct pool_mark *mark) } { - struct pool_block *cur, *next, *last; + struct pool_block *cur; - last = pool->blocks->prev; - for (cur = pool->blocks; cur != mark->block; cur = next) + for (cur = pool->blocks; cur != mark->block; cur = cur->next) { - next = cur->next; - assert (next != cur); - - free (cur); + cur->ofs = POOL_BLOCK_SIZE; + if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) + cur->ofs += POOL_SIZE; } - - cur->prev = last; - last->next = pool->blocks = cur; - - cur->ofs = mark->ofs; + pool->blocks = mark->block; + pool->blocks->ofs = mark->ofs; } } @@ -583,6 +631,20 @@ free_gizmo (struct pool_gizmo *gizmo) assert (0); } } + +/* Free all the gizmos in POOL. */ +static void +free_all_gizmos (struct pool *pool) +{ + struct pool_gizmo *cur, *next; + + for (cur = pool->gizmos; cur; cur = next) + { + next = cur->next; + free_gizmo (cur); + } + pool->gizmos=NULL; +} /* Memory allocation. */