17 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
18 |
02111-1307, USA. */ |
02111-1307, USA. */ |
19 |
|
|
|
#if HAVE_CONFIG_H |
|
20 |
#include <config.h> |
#include <config.h> |
|
#endif |
|
21 |
#include "pool.h" |
#include "pool.h" |
22 |
|
#include "command.h" |
23 |
#include "error.h" |
#include "error.h" |
24 |
#include <stdlib.h> |
#include <stdlib.h> |
25 |
#include "alloc.h" |
#include "alloc.h" |
55 |
This structure is used to keep track of them. */ |
This structure is used to keep track of them. */ |
56 |
struct pool_gizmo |
struct pool_gizmo |
57 |
{ |
{ |
58 |
|
struct pool *pool; |
59 |
struct pool_gizmo *prev; |
struct pool_gizmo *prev; |
60 |
struct pool_gizmo *next; |
struct pool_gizmo *next; |
61 |
|
|
112 |
simplified functionality. */ |
simplified functionality. */ |
113 |
/*#define DISCRETE_BLOCKS 1*/ |
/*#define DISCRETE_BLOCKS 1*/ |
114 |
|
|
|
/* Enable debug code if appropriate. */ |
|
|
#if SELF_TEST |
|
|
#endif |
|
|
|
|
115 |
/* Size of each block allocated in the pool, in bytes. |
/* Size of each block allocated in the pool, in bytes. |
116 |
Should be at least 1k. */ |
Should be at least 1k. */ |
117 |
#ifndef BLOCK_SIZE |
#ifndef BLOCK_SIZE |
138 |
static void free_gizmo (struct pool_gizmo *); |
static void free_gizmo (struct pool_gizmo *); |
139 |
static void free_all_gizmos (struct pool *pool); |
static void free_all_gizmos (struct pool *pool); |
140 |
static void delete_gizmo (struct pool *, struct pool_gizmo *); |
static void delete_gizmo (struct pool *, struct pool_gizmo *); |
141 |
|
static void check_gizmo (struct pool *, struct pool_gizmo *); |
|
#if !PSPP |
|
|
static void *xmalloc (size_t); |
|
|
static void *xrealloc (void *, size_t); |
|
|
#endif |
|
142 |
|
|
143 |
/* General routines. */ |
/* General routines. */ |
144 |
|
|
175 |
|
|
176 |
/* Remove this pool from its parent's list of gizmos. */ |
/* Remove this pool from its parent's list of gizmos. */ |
177 |
if (pool->parent) |
if (pool->parent) |
178 |
delete_gizmo (pool->parent, |
delete_gizmo (pool->parent, (void *) (((char *) pool) + POOL_SIZE)); |
179 |
(void *) (((char *) pool) + POOL_SIZE + POOL_BLOCK_SIZE)); |
|
|
|
|
180 |
free_all_gizmos (pool); |
free_all_gizmos (pool); |
181 |
|
|
182 |
/* Free all the memory. */ |
/* Free all the memory. */ |
208 |
do |
do |
209 |
{ |
{ |
210 |
cur->ofs = POOL_BLOCK_SIZE; |
cur->ofs = POOL_BLOCK_SIZE; |
211 |
if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) |
if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) |
212 |
cur->ofs += POOL_SIZE; |
{ |
213 |
|
cur->ofs += POOL_SIZE; |
214 |
|
if (pool->parent != NULL) |
215 |
|
cur->ofs += POOL_GIZMO_SIZE; |
216 |
|
} |
217 |
cur = cur->next; |
cur = cur->next; |
218 |
} |
} |
219 |
while (cur != pool->blocks); |
while (cur != pool->blocks); |
273 |
return pool_malloc (pool, amt); |
return pool_malloc (pool, amt); |
274 |
} |
} |
275 |
|
|
276 |
|
/* Allocates SIZE bytes in POOL, copies BUFFER into it, and |
277 |
|
returns the new copy. */ |
278 |
|
void * |
279 |
|
pool_clone (struct pool *pool, const void *buffer, size_t size) |
280 |
|
{ |
281 |
|
void *block = pool_alloc (pool, size); |
282 |
|
memcpy (block, buffer, size); |
283 |
|
return block; |
284 |
|
} |
285 |
|
|
286 |
/* Duplicates STRING, which has LENGTH characters, within POOL, |
/* Duplicates STRING, which has LENGTH characters, within POOL, |
287 |
and returns a pointer to the duplicate. LENGTH should not |
and returns a pointer to the duplicate. LENGTH should not |
288 |
include the null terminator, which is always added to the |
include the null terminator, which is always added to the |
369 |
{ |
{ |
370 |
if (amt != 0) |
if (amt != 0) |
371 |
{ |
{ |
372 |
struct pool_gizmo *g; |
struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE); |
373 |
|
check_gizmo (pool, g); |
374 |
|
|
375 |
g = xrealloc (((char *) p) - POOL_GIZMO_SIZE, |
g = xrealloc (g, amt + POOL_GIZMO_SIZE); |
|
amt + POOL_GIZMO_SIZE); |
|
376 |
if (g->next) |
if (g->next) |
377 |
g->next->prev = g; |
g->next->prev = g; |
378 |
if (g->prev) |
if (g->prev) |
379 |
g->prev->next = g; |
g->prev->next = g; |
380 |
else |
else |
381 |
pool->gizmos = g; |
pool->gizmos = g; |
382 |
|
check_gizmo (pool, g); |
383 |
|
|
384 |
return ((char *) g) + POOL_GIZMO_SIZE; |
return ((char *) g) + POOL_GIZMO_SIZE; |
385 |
} |
} |
405 |
if (pool != NULL && p != NULL) |
if (pool != NULL && p != NULL) |
406 |
{ |
{ |
407 |
struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE); |
struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE); |
408 |
|
check_gizmo (pool, g); |
409 |
delete_gizmo (pool, g); |
delete_gizmo (pool, g); |
410 |
free (g); |
free (g); |
411 |
} |
} |
428 |
subpool = pool_create (); |
subpool = pool_create (); |
429 |
subpool->parent = pool; |
subpool->parent = pool; |
430 |
|
|
431 |
g = (void *) (((char *) subpool) + subpool->blocks->ofs); |
g = (void *) (((char *) subpool->blocks) + subpool->blocks->ofs); |
432 |
subpool->blocks->ofs += POOL_GIZMO_SIZE; |
subpool->blocks->ofs += POOL_GIZMO_SIZE; |
433 |
|
|
434 |
g->type = POOL_GIZMO_SUBPOOL; |
g->type = POOL_GIZMO_SUBPOOL; |
573 |
for (cur = pool->blocks; cur != mark->block; cur = cur->next) |
for (cur = pool->blocks; cur != mark->block; cur = cur->next) |
574 |
{ |
{ |
575 |
cur->ofs = POOL_BLOCK_SIZE; |
cur->ofs = POOL_BLOCK_SIZE; |
576 |
if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) |
if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) |
577 |
cur->ofs += POOL_SIZE; |
{ |
578 |
|
cur->ofs += POOL_SIZE; |
579 |
|
if (pool->parent != NULL) |
580 |
|
cur->ofs += POOL_GIZMO_SIZE; |
581 |
|
} |
582 |
} |
} |
583 |
pool->blocks = mark->block; |
pool->blocks = mark->block; |
584 |
pool->blocks->ofs = mark->ofs; |
pool->blocks->ofs = mark->ofs; |
592 |
add_gizmo (struct pool *pool, struct pool_gizmo *gizmo) |
add_gizmo (struct pool *pool, struct pool_gizmo *gizmo) |
593 |
{ |
{ |
594 |
assert (pool && gizmo); |
assert (pool && gizmo); |
595 |
|
|
596 |
|
gizmo->pool = pool; |
597 |
gizmo->next = pool->gizmos; |
gizmo->next = pool->gizmos; |
598 |
gizmo->prev = NULL; |
gizmo->prev = NULL; |
599 |
if (pool->gizmos) |
if (pool->gizmos) |
601 |
pool->gizmos = gizmo; |
pool->gizmos = gizmo; |
602 |
|
|
603 |
gizmo->serial = serial++; |
gizmo->serial = serial++; |
604 |
|
|
605 |
|
check_gizmo (pool, gizmo); |
606 |
} |
} |
607 |
|
|
608 |
/* Removes GIZMO from POOL's gizmo list. */ |
/* Removes GIZMO from POOL's gizmo list. */ |
610 |
delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo) |
delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo) |
611 |
{ |
{ |
612 |
assert (pool && gizmo); |
assert (pool && gizmo); |
613 |
|
|
614 |
|
check_gizmo (pool, gizmo); |
615 |
|
|
616 |
if (gizmo->prev) |
if (gizmo->prev) |
617 |
gizmo->prev->next = gizmo->next; |
gizmo->prev->next = gizmo->next; |
618 |
else |
else |
627 |
free_gizmo (struct pool_gizmo *gizmo) |
free_gizmo (struct pool_gizmo *gizmo) |
628 |
{ |
{ |
629 |
assert (gizmo != NULL); |
assert (gizmo != NULL); |
630 |
|
|
631 |
switch (gizmo->type) |
switch (gizmo->type) |
632 |
{ |
{ |
633 |
case POOL_GIZMO_MALLOC: |
case POOL_GIZMO_MALLOC: |
659 |
next = cur->next; |
next = cur->next; |
660 |
free_gizmo (cur); |
free_gizmo (cur); |
661 |
} |
} |
662 |
pool->gizmos=NULL; |
pool->gizmos = NULL; |
663 |
} |
} |
|
|
|
|
/* Memory allocation. */ |
|
664 |
|
|
665 |
#if !PSPP |
static void |
666 |
/* Allocates SIZE bytes of space using malloc(). Aborts if out of |
check_gizmo (struct pool *p, struct pool_gizmo *g) |
|
memory. */ |
|
|
static void * |
|
|
xmalloc (size_t size) |
|
667 |
{ |
{ |
668 |
void *vp; |
assert (g->pool == p); |
669 |
if (size == 0) |
assert (g->next == NULL || g->next->prev == g); |
670 |
return NULL; |
assert ((g->prev != NULL && g->prev->next == g) |
671 |
vp = malloc (size); |
|| (g->prev == NULL && p->gizmos == g)); |
|
assert (vp != NULL); |
|
|
if (vp == NULL) |
|
|
abort (); |
|
|
return vp; |
|
|
} |
|
672 |
|
|
|
/* Reallocates P to be SIZE bytes long using realloc(). Aborts if out |
|
|
of memory. */ |
|
|
static void * |
|
|
xrealloc (void *p, size_t size) |
|
|
{ |
|
|
if (p == NULL) |
|
|
return xmalloc (size); |
|
|
if (size == 0) |
|
|
{ |
|
|
free (p); |
|
|
return NULL; |
|
|
} |
|
|
p = realloc (p, size); |
|
|
if (p == NULL) |
|
|
abort (); |
|
|
return p; |
|
673 |
} |
} |
|
#endif /* !PSPP */ |
|
674 |
|
|
675 |
/* Self-test routine. */ |
/* Self-test routine. */ |
676 |
|
|
|
#if SELF_TEST |
|
677 |
#include <errno.h> |
#include <errno.h> |
678 |
#include <stdio.h> |
#include <stdio.h> |
679 |
#include <stdlib.h> |
#include <stdlib.h> |
686 |
/* Self-test routine. |
/* Self-test routine. |
687 |
This is not exhaustive, but it can be useful. */ |
This is not exhaustive, but it can be useful. */ |
688 |
int |
int |
689 |
main (int argc, char **argv) |
cmd_debug_pool (void) |
690 |
{ |
{ |
691 |
int seed; |
int seed = time (0) * 257 % 32768; |
|
|
|
|
if (argc == 2) |
|
|
seed = atoi (argv[1]); |
|
|
else |
|
|
seed = time (0) * 257 % 32768; |
|
692 |
|
|
693 |
for (;;) |
for (;;) |
694 |
{ |
{ |
767 |
|
|
768 |
putchar ('\n'); |
putchar ('\n'); |
769 |
} |
} |
|
} |
|
770 |
|
|
771 |
#endif /* SELF_TEST */ |
return CMD_SUCCESS; |
772 |
|
} |
773 |
|
|
|
/* |
|
|
Local variables: |
|
|
compile-command: "gcc -DSELF_TEST=1 -W -Wall -I. -o pool_test pool.c" |
|
|
End: |
|
|
*/ |
|