X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fpool.c;h=dbdd71b6cbbf250fbb91248e6c8cc820da13e4f0;hb=75a80e71a0d3a08f4bc561f16702c36d45e32c31;hp=0e6c9358fc828cd10f027c32d9f5750c7ffd5c23;hpb=e7bafb24d29d2370665c02e070f90fa180ad8056;p=pspp-builds.git diff --git a/src/libpspp/pool.c b/src/libpspp/pool.c index 0e6c9358..dbdd71b6 100644 --- a/src/libpspp/pool.c +++ b/src/libpspp/pool.c @@ -1,30 +1,29 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include #include "pool.h" +#include #include -#include "alloc.h" +#include #include "message.h" -#include "size_max.h" #include "str.h" +#include "xalloc.h" + /* Fast, low-overhead memory block suballocator. */ struct pool { @@ -34,7 +33,7 @@ struct pool }; /* Pool block. */ -struct pool_block +struct pool_block { struct pool_block *prev; struct pool_block *next; @@ -51,7 +50,7 @@ enum }; /* Pool routines can maintain objects (`gizmos') as well as doing - suballocation. + suballocation. This structure is used to keep track of them. */ struct pool_gizmo { @@ -100,8 +99,8 @@ union align /* DISCRETE_BLOCKS may be declared as nonzero to prevent suballocation of blocks. This is useful under memory - debuggers like Checker or valgrind because it allows the - source location of bugs to be more accurately pinpointed. + debuggers like valgrind because it allows the source location + of bugs to be more accurately pinpointed. On the other hand, if we're testing the library, then we want to test the library's real functionality, not its crippled, slow, @@ -147,7 +146,7 @@ pool_create (void) block = xmalloc (BLOCK_SIZE); block->prev = block->next = block; block->ofs = POOL_BLOCK_SIZE + POOL_SIZE; - + pool = (struct pool *) (((char *) block) + POOL_BLOCK_SIZE); pool->parent = NULL; pool->blocks = block; @@ -163,7 +162,7 @@ pool_create (void) Meant for use indirectly via pool_create_container(). */ void * -pool_create_at_offset (size_t struct_size, size_t pool_member_offset) +pool_create_at_offset (size_t struct_size, size_t pool_member_offset) { struct pool *pool; char *struct_; @@ -185,9 +184,9 @@ pool_destroy (struct pool *pool) return; /* Remove this pool from its parent's list of gizmos. */ - if (pool->parent) + if (pool->parent) delete_gizmo (pool->parent, (void *) (((char *) pool) + POOL_SIZE)); - + free_all_gizmos (pool); /* Free all the memory. */ @@ -205,25 +204,25 @@ 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. */ + allocations. To give back memory, use a subpool instead. */ void -pool_clear (struct pool *pool) +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) + if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) { cur->ofs += POOL_SIZE; if (pool->parent != NULL) - cur->ofs += POOL_GIZMO_SIZE; + cur->ofs += POOL_GIZMO_SIZE; } cur = cur->next; } @@ -243,7 +242,7 @@ pool_alloc (struct pool *pool, size_t amt) if (amt == 0) return NULL; - + #ifndef DISCRETE_BLOCKS if (amt <= MAX_SUBALLOC) { @@ -259,7 +258,7 @@ pool_alloc (struct pool *pool, size_t amt) /* No space in this block, so we must make other arrangements. */ - if (b->next->ofs == 0) + if (b->next->ofs == 0) { /* The next block is empty. Use it. */ b = b->next; @@ -267,7 +266,7 @@ pool_alloc (struct pool *pool, size_t amt) if ((char *) b + POOL_BLOCK_SIZE == (char *) pool) b->ofs += POOL_SIZE; } - else + else { /* Create a new block at the start of the list. */ b = xmalloc (BLOCK_SIZE); @@ -301,7 +300,7 @@ pool_alloc_unaligned (struct pool *pool, size_t amt) /* Strings need not be aligned on any boundary, but some operations may be more efficient when they are. However, that's only going to help with reasonably long strings. */ - if (amt < ALIGN_SIZE) + if (amt < ALIGN_SIZE) { if (amt == 0) return NULL; @@ -328,7 +327,7 @@ pool_alloc_unaligned (struct pool *pool, size_t amt) Terminates the program if the memory cannot be obtained, including the case where N * S overflows the range of size_t. */ void * -pool_nalloc (struct pool *pool, size_t n, size_t s) +pool_nalloc (struct pool *pool, size_t n, size_t s) { if (xalloc_oversized (n, s)) xalloc_die (); @@ -360,11 +359,24 @@ pool_clone_unaligned (struct pool *pool, const void *buffer, size_t size) the returned pointere may not be aligned properly for other types. */ char * -pool_strdup (struct pool *pool, const char *string) +pool_strdup (struct pool *pool, const char *string) { return pool_clone_unaligned (pool, string, strlen (string) + 1); } +/* Duplicates the SIZE bytes of STRING, plus a trailing 0 byte, + 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_strdup0 (struct pool *pool, const char *string, size_t size) +{ + char *new_string = pool_alloc_unaligned (pool, size + 1); + memcpy (new_string, string, size); + new_string[size] = '\0'; + return new_string; +} + /* Formats FORMAT with the given ARGS in memory allocated from POOL and returns the formatted string. */ char * @@ -382,9 +394,9 @@ pool_vasprintf (struct pool *pool, const char *format, va_list args_) needed = vsnprintf (s, avail, format, args); va_end (args); - if (needed >= 0) + if (needed >= 0) { - if (needed < avail) + if (needed < avail) { /* Success. Reserve the space that was actually used. */ b->ofs += needed + 1; @@ -400,7 +412,7 @@ pool_vasprintf (struct pool *pool, const char *format, va_list args_) va_end (args); } } - else + else { /* Some old libc's returned -1 when the destination string was too short. This should be uncommon these days and @@ -423,7 +435,7 @@ pool_asprintf (struct pool *pool, const char *format, ...) { va_list args; char *string; - + va_start (args, format); string = pool_vasprintf (pool, format, args); va_end (args); @@ -465,13 +477,41 @@ pool_malloc (struct pool *pool, size_t amt) Terminates the program if the memory cannot be obtained, including the case where N * S overflows the range of size_t. */ void * -pool_nmalloc (struct pool *pool, size_t n, size_t s) +pool_nmalloc (struct pool *pool, size_t n, size_t s) { if (xalloc_oversized (n, s)) xalloc_die (); return pool_malloc (pool, n * s); } +/* Allocates AMT bytes using malloc(), to be managed by POOL, + zeros the block, and returns a pointer to the beginning of the + block. + If POOL is a null pointer, then allocates a normal memory block + with xmalloc(). */ +void * +pool_zalloc (struct pool *pool, size_t amt) +{ + void *p = pool_malloc (pool, amt); + memset (p, 0, amt); + return p; +} + +/* Allocates and returns N elements of S bytes each, to be + managed by POOL, and zeros the block. + If POOL is a null pointer, then allocates a normal memory block + with malloc(). + N must be nonnegative, S must be positive. + Terminates the program if the memory cannot be obtained, + including the case where N * S overflows the range of size_t. */ +void * +pool_calloc (struct pool *pool, size_t n, size_t s) +{ + void *p = pool_nmalloc (pool, n, s); + memset (p, 0, n * s); + return p; +} + /* Changes the allocation size of the specified memory block P managed by POOL to AMT bytes and returns a pointer to the beginning of the block. @@ -657,7 +697,7 @@ pool_create_subpool (struct pool *pool) g = (void *) (((char *) subpool->blocks) + subpool->blocks->ofs); subpool->blocks->ofs += POOL_GIZMO_SIZE; - + g->type = POOL_GIZMO_SUBPOOL; g->p.subpool = subpool; @@ -671,14 +711,14 @@ pool_create_subpool (struct pool *pool) The subpool will be destroyed automatically when POOL is destroyed. It may also be destroyed explicitly in advance. */ void -pool_add_subpool (struct pool *pool, struct pool *subpool) +pool_add_subpool (struct pool *pool, struct pool *subpool) { struct pool_gizmo *g; assert (pool != NULL); assert (subpool != NULL); assert (subpool->parent == NULL); - + g = pool_alloc (subpool, sizeof *g); g->type = POOL_GIZMO_SUBPOOL; g->p.subpool = subpool; @@ -699,8 +739,8 @@ pool_fopen (struct pool *pool, const char *file_name, const char *mode) assert (pool && file_name && mode); f = fopen (file_name, mode); - if (f == NULL) - return NULL; + if (f != NULL) + pool_attach_file (pool, f); return f; } @@ -721,7 +761,7 @@ pool_fclose (struct pool *pool, FILE *file) may be closed explicitly in advance using pool_fclose(), or detached from the pool with pool_detach_file(). */ FILE * -pool_tmpfile (struct pool *pool) +pool_tmpfile (struct pool *pool) { FILE *file = tmpfile (); if (file != NULL) @@ -776,12 +816,12 @@ pool_register (struct pool *pool, void (*free) (void *), void *p) } /* Unregisters previously registered P from POOL. - Returns nonzero only if P was found to be registered in POOL. */ -int + Returns true only if P was found to be registered in POOL. */ +bool pool_unregister (struct pool *pool, void *p) { assert (pool && p); - + { struct pool_gizmo *g; @@ -789,11 +829,11 @@ pool_unregister (struct pool *pool, void *p) if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p) { delete_gizmo (pool, g); - return 1; + return true; } } - - return 0; + + return false; } /* Partial freeing. */ @@ -814,12 +854,12 @@ pool_mark (struct pool *pool, struct pool_mark *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. */ + instead. */ void pool_release (struct pool *pool, const struct pool_mark *mark) { assert (pool && mark); - + { struct pool_gizmo *cur, *next; @@ -837,18 +877,18 @@ pool_release (struct pool *pool, const struct pool_mark *mark) else pool->gizmos = NULL; } - + { struct pool_block *cur; - for (cur = pool->blocks; cur != mark->block; cur = cur->next) + for (cur = pool->blocks; cur != mark->block; cur = cur->next) { cur->ofs = POOL_BLOCK_SIZE; - if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) + if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) { cur->ofs += POOL_SIZE; if (pool->parent != NULL) - cur->ofs += POOL_GIZMO_SIZE; + cur->ofs += POOL_GIZMO_SIZE; } } pool->blocks = mark->block; @@ -875,7 +915,7 @@ add_gizmo (struct pool *pool, struct pool_gizmo *gizmo) check_gizmo (pool, gizmo); } - + /* Removes GIZMO from POOL's gizmo list. */ static void delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo) @@ -915,13 +955,13 @@ free_gizmo (struct pool_gizmo *gizmo) gizmo->p.registered.free (gizmo->p.registered.p); break; default: - assert (0); + NOT_REACHED (); } } /* Free all the gizmos in POOL. */ static void -free_all_gizmos (struct pool *pool) +free_all_gizmos (struct pool *pool) { struct pool_gizmo *cur, *next; @@ -934,7 +974,7 @@ free_all_gizmos (struct pool *pool) } static void -check_gizmo (struct pool *p, struct pool_gizmo *g) +check_gizmo (struct pool *p, struct pool_gizmo *g) { assert (g->pool == p); assert (g->next == NULL || g->next->prev == g);