/[ascend]/trunk/base/generic/general/pool.c
ViewVC logotype

Contents of /trunk/base/generic/general/pool.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download) (as text)
Wed Nov 30 05:53:20 2005 UTC (19 years, 5 months ago) by johnpye
File MIME type: text/x-csrc
File size: 21711 byte(s)
My first commit:
Added 'error_reporter' for standardised error reporting
Working on getting external functions running again
Also: issue 130, issue 68, issue 131, issue 89, issue 127, issue 138, issue 94.
1 /*
2 * Ascend Pooled Memory Manager
3 * by Benjamin Andrew Allan
4 * Created: 2/96
5 * Version: $Revision: 1.1 $
6 * Version control file: $RCSfile: pool.c,v $
7 * Date last modified: $Date: 1997/07/18 11:37:01 $
8 * Last modified by: $Author: mthomas $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1996 Benjamin Andrew Allan
13 *
14 * The Ascend Language Interpreter is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * The Ascend Language Interpreter is distributed in hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with the program; if not, write to the Free Software Foundation,
26 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
27 * COPYING.
28 */
29
30 #include <stdlib.h>
31
32 #include "utilities/ascConfig.h"
33 #include "utilities/ascMalloc.h"
34 #include "general/pool.h"
35
36 #ifndef FALSE
37 #define FALSE 0
38 #define TRUE 1
39 #endif
40 #ifdef NULL
41 /* ok, so the machine has a NULL defined. */
42 #ifndef ISNULL
43 /* and we've not got an ISNULL function */
44 #define ISNULL(a) ((a) == NULL)
45 #define NOTNULL(a) ((a) != NULL)
46 #endif /* isnull */
47 #endif /* null */
48 /* get local max and min definitions */
49 #ifdef PMN
50 #undef PMN
51 #undef PMX
52 #endif
53 #define PMN(a,b) ((a) < (b) ? (a) : (b))
54 #define PMX(a,b) ((a) < (b) ? (b) : (a))
55
56 /*********************** pool_store code. BAA 5/16/95 ***********************/
57 /* according to K&R2 char <--> byte and size_t is a byte count.
58 We are coding with those assumptions. (sizeof(char)==1) */
59 #define OK 345676543
60 #define DESTROYED 765434567
61 #if pool_DEBUG
62 /* ground LIGHTENING */
63 #undef pool_LIGHTENING
64 #define pool_LIGHTENING FALSE
65 #endif
66 #define BYPASS_ASCMALLOC FALSE
67 #if (pool_LIGHTENING || BYPASS_ASCMALLOC)
68 /* gonna bypass ascmalloc, eh? ;-) shaame on you! */
69 #define PMEM_calloc(a,b) calloc(a,b)
70 #define PMEM_malloc(a) malloc(a)
71 #define PMEM_free(a) free(a)
72 #define PMEM_realloc(a,b) realloc(a,b)
73 #else
74 #define PMEM_calloc(a,b) asccalloc(a,b)
75 #define PMEM_malloc(a) ascmalloc(a)
76 #define PMEM_free(a) ascfree(a)
77 #define PMEM_realloc(a,b) ascrealloc(a,b)
78 #endif
79
80 /*
81 Don't get caught taking the size of struct pool_element,
82 It is the head for anonymous elements of any size.
83 */
84 struct pool_element {
85 struct pool_element *nextelt;
86 };
87
88 struct pool_store_header {
89 int integrity; /* sanity number. */
90 /* actual data */
91 int maxlen; /* current length of pool, not necessarily w/bars full */
92 char **pool; /* array of pointers to bars */
93 struct pool_element *list; /* pointer to the most recently freed element */
94
95 /* some interesting book keeping quantities */
96 #if !pool_LIGHTENING
97 long active; /* number of elements individually requested, ever */
98 long retned; /* number of elements individually returned, ever */
99 #endif
100 size_t eltsize; /* size of element, often an unsigned (long) */
101 size_t eltsize_req; /* size of element, often an unsigned (long) */
102 size_t barsize; /* size of bar. no point in extra multiplications */
103
104 /* memory management quantities */
105 int len; /* number of bars filled (length of pool filled) */
106 int wid; /* num elements in a bar */
107 int expand; /* number of bars to expand by usually */
108 int growpool; /* expansion increment for pool array */
109 int curbar; /* pool entry from which fresh elements may be had */
110 int curelt; /* number of the next element in the curbar to hand out */
111 int onlist; /* length of recycle list, in elements */
112 #if !pool_LIGHTENING
113 int total; /* total number of elements in this store */
114 int highwater; /* fresh elements turned loose from store */
115 int inuse; /* current elts user has outstanding */
116 #endif
117 };
118 /* notes on header:
119 * list is, as currently coded, null terminated by accident.
120 * The intent of the author is that the counter onlist is the
121 * authoritative list length.
122 */
123
124 #define PMEM_MINBARSIZE 5
125 #define PMEM_MINPOOLSIZE 2
126 #ifdef __alpha
127 #define PMEM_MINPOOLGROW 128
128 /* gotta love those fat pointers. grow by 4k min. */
129 #else
130 #define PMEM_MINPOOLGROW 256
131 #endif
132
133 /*
134 Returns 2 if really bad, 1 if something fishy, 0 otherwise.
135 */
136 static int check_pool_store(const pool_store_t ps)
137 {
138 #if pool_LIGHTENING
139 return 0;
140 #else
141 int i;
142
143 if (ISNULL(ps)) {
144 FPRINTF(ASCERR,"check_pool_store (pool.c): NULL pool_store_t!\n");
145 return 2;
146 }
147 if (ps->integrity != OK) {
148 (ps->integrity == DESTROYED) ?
149 FPRINTF(ASCERR,
150 "check_pool_store (pool.c): pool_store_t recently destroyed!\n")
151 : FPRINTF(ASCERR,
152 "check_pool_store (pool.c): pool_store_t corrupted!\n");
153 return 2;
154 }
155 if (ps->onlist && ISNULL(ps->list)) {
156 FPRINTF(ASCERR, "ERROR: check_pool_store (pool.c): NULL recycle list!\n");
157 return 1;
158 }
159 /* more in than out? */
160 if (ps->retned > ps->active) {
161 FPRINTF(ASCERR, "ERROR: check_pool_store (pool.c): Imbalanced memory.\n");
162 return 1;
163 }
164 if (ps->onlist + ps->inuse != ps->highwater) {
165 FPRINTF(ASCERR,"ERROR: check_pool_store (pool.c): Imbalanced elements.\n");
166 return 1;
167 }
168 /* is pool allocated to ps->len? */
169 for (i=0; i < ps->len; i++) {
170 if (ISNULL(ps->pool[i])) {
171 FPRINTF(ASCERR,
172 "ERROR: check_pool_store (pool.c): Hole found in pool!\n");
173 FPRINTF(ASCERR, " Bar %d is NULL.\n",i);
174 return 2;
175 }
176 }
177 /* do not check for integrity or count of recycle list elements. */
178 return 0;
179 #endif
180 }
181
182 /*
183 This should not be called unless all current store is in use.
184 Returns 0 if ok, 1 for all other insanities.
185 If only partial expansion is possible, we will do it and
186 return 0. If change in ps->len is < the expected incremented value
187 on return, the user knows he should do some garbage removal.
188 incr is provided for times when we know how much we want
189 to expand by.
190
191 This should never be called on a totally empty pool.
192 */
193 static int expand_store(pool_store_t ps, int incr)
194 {
195 static int oldsize, newsize,punt,i;
196 char **newpool = NULL;
197 if (check_pool_store(ps) >1) {
198 FPRINTF(ASCERR,"ERROR: (pool.c) expand_store received bad\n");
199 FPRINTF(ASCERR," pool_store_t. Expansion failed.\n");
200 return 1;
201 }
202
203 #if !pool_LIGHTENING
204 /* do not expand elements or pool if all is not in use */
205 if (ps->inuse < ps->total) {
206 FPRINTF(ASCERR,"ERROR: (pool.c) expand_store called prematurely.\n");
207 FPRINTF(ASCERR," Expansion will be reported as failed.\n");
208 return 1;
209 }
210 #endif
211
212 /* make sure bar expansion is at least the minimum */
213 if (incr < ps->expand) incr = ps->expand;
214 oldsize = ps->len;
215 newsize = oldsize+incr;
216
217 /* expand pool capacity only if all of pool in use */
218 if (newsize > ps->maxlen) {
219 i = ps->maxlen + PMX(ps->growpool,incr);
220 newpool = (char **)PMEM_realloc(ps->pool, i*sizeof(char *));
221 if (ISNULL(newpool)) {
222 FPRINTF(ASCERR,"ERROR: (pool.c) expand_store can't realloc pool.\n");
223 return 1;
224 }
225 /* NULL the new pool */
226 for (punt = ps->maxlen; punt < i; punt++) {
227 newpool[punt] = NULL;
228 }
229 ps->maxlen = i;
230 ps->pool = newpool;
231 }
232 /* end of pool expansion */
233
234 /* expand elements/bars */
235 ps->len = newsize; /* set expanded number of bars filled */
236 punt = -1;
237 for (i = oldsize; i < newsize; i++) {
238 #if pool_DEBUG
239 ps->pool[i] = (char *)PMEM_calloc(ps->barsize,1);
240 #else
241 ps->pool[i] = (char *)PMEM_malloc(ps->barsize);
242 #endif
243 if (ISNULL(ps->pool[i])) {
244 punt = i;
245 /* we will return partially expanded if possible */
246 break;
247 }
248 }
249 if (punt >= 0) {
250 /* incomplete expansion */
251 if (punt == oldsize) {
252 /* unable to add elements at all. fail */
253 FPRINTF(ASCERR,"ERROR: (pool) expand_store: Insufficient memory.\n");
254 ps->len = oldsize;
255 return 1;
256 } else {
257 /* contract pool to the actual expansion size */
258 FPRINTF(ASCERR,"WARNING: (pool) expand_store: Insufficient memory.\n");
259 FPRINTF(ASCERR," Doing partial expansion.\n");
260 ps->len = punt;
261 }
262 }
263 #if !pool_LIGHTENING
264 ps->total = ps->len * ps->wid;
265 #endif
266 return 0;
267 }
268
269 #if !pool_LIGHTENING
270 #if pool_DEBUG
271 /*
272 Returns 1 if pointer is to an elt of the store, 0 otherwise.
273 The case of pointer into store reserved space, but not an elt is checked.
274 */
275 static int from_store( pool_store_t ps, void *elt)
276 {
277 char *data, **pool;
278 int i,lim;
279
280 if (ISNULL(ps) || ISNULL(elt)) return 0;
281 lim = ps->len;
282 pool = ps->pool;
283 data = (char *)elt;
284 for (i=0; i<lim; i++) {
285 /* did the char come from the current bar of chars? */
286 if (*pool <= data && data < *pool + ps->barsize) {
287 /* if so, is it legal? */
288 if ( !((data - (*pool)) % ps->eltsize) ) {
289 return 1;
290 } else {
291 FPRINTF(ASCERR,"ERROR: (pool.c) from_store: Misaligned element\n");
292 FPRINTF(ASCERR," pointer detected.\n");
293 return 0;
294 }
295 }
296 pool++;
297 }
298 return 0;
299 }
300 #endif
301 #endif
302
303 void pool_get_stats(struct pool_statistics *pss, pool_store_t m)
304 {
305 if (ISNULL(pss)) {
306 FPRINTF(ASCERR,"ERROR: (pool_get_stats) Called with NULL struct\n");
307 FPRINTF(ASCERR," pool_statistics.\n");
308 return;
309 }
310 if (check_pool_store(m)>1 ) {
311 ascbzero((void *)pss,(int)sizeof(struct pool_statistics));
312 FPRINTF(ASCERR,"ERROR: (pool_get_stats) Bad pool_store_t given.\n");
313 FPRINTF(ASCERR," Returning 0s.\n");
314 return;
315 }
316 #if !pool_LIGHTENING
317 pss->p_eff = m->inuse*m->eltsize_req/(double)pool_sizeof_store(m);
318 pss->p_recycle =
319 ( (m->highwater > 0) ? m->active/(double)m->highwater : 0.0 );
320 pss->elt_total = m->total;
321 pss->elt_taken = m->highwater;
322 pss->elt_inuse = m->inuse;
323 #else
324 pss->p_eff = 0.0;
325 pss->p_recycle = 0.0;
326 pss->elt_total = m->len*m->wid;
327 pss->elt_taken = m->curelt+m->curbar*m->wid;
328 pss->elt_inuse = 0;
329 #endif
330 pss->elt_onlist = m->onlist;
331 pss->elt_size = m->eltsize;
332 pss->str_len = m->len;
333 pss->str_wid = m->wid;
334 }
335
336 pool_store_t pool_create_store(int length, int width,
337 size_t eltsize, int deltalen, int deltapool)
338 {
339 int i, punt;
340 pool_store_t newps=NULL;
341 size_t uelt;
342
343 if (length < 1 || width < 1 || deltalen < 1 ) {
344 FPRINTF(ASCERR,"ERROR: (pool_create_store) : Bad input detected.\n");
345 return NULL;
346 }
347
348 /* check minsizes */
349 if (length < PMEM_MINPOOLSIZE) length = PMEM_MINPOOLSIZE;
350 if (width < PMEM_MINBARSIZE) width = PMEM_MINBARSIZE;
351 /* maybe the user gave us length = max he knows he needs, so we
352 will not enforce a minimum maxlen on length at creation */
353
354 uelt = eltsize;
355 /* check for elt padding needed */
356 if (eltsize % sizeof(void *)) {
357 int ptrperelt;
358 ptrperelt = eltsize/sizeof(void *) + 1;
359 #if pool_DEBUG
360 FPRINTF(ASCERR,"(pool_create_store) Elts of size %d padded to %d\n",
361 (int)eltsize,(int)(eltsize=ptrperelt*sizeof(void *)));
362 #else
363 eltsize = ptrperelt*sizeof(void *);
364 #endif
365 }
366 /* eltsize is now pointer alignable */
367 /* it could still be user data misalignable, of course, if pointer
368 is not the most restrictive data type for the machine */
369
370
371 newps = (pool_store_t)PMEM_calloc(1,sizeof(struct pool_store_header));
372 if (ISNULL(newps)) {
373 FPRINTF(ASCERR,"ERROR: (pool_create_store) : Insufficient memory.\n");
374 return NULL;
375 }
376 /* the following are all initially 0/NULL by calloc, and should be:
377 newps->list
378 newps->active
379 newps->retned
380 newps->curbar
381 newps->curelt
382 newps->highwater
383 newps->onlist
384 newps->inuse
385 newps->pool
386 */
387 newps->integrity = OK;
388 newps->len = length;
389 newps->maxlen = length;
390 newps->wid = width;
391 newps->expand = deltalen;
392 newps->eltsize = eltsize;
393 newps->barsize = eltsize * width;
394 #if !pool_LIGHTENING
395 newps->total = length * width;
396 #endif
397 newps->growpool = PMX(PMEM_MINPOOLGROW,deltapool);
398 newps->eltsize_req = uelt;
399
400 /* get pool */
401 newps->pool = (char **)PMEM_calloc(length,sizeof(char *));
402 if (ISNULL(newps->pool)) {
403 FPRINTF(ASCERR,"ERROR: (pool_create_store) : Insufficient memory.\n");
404 newps->integrity = DESTROYED;
405 PMEM_free(newps);
406 return NULL;
407 }
408
409 /* fill it */
410 punt = -1;
411 for (i=0; i < length; i++) {
412 newps->pool[i] = (char *)PMEM_malloc(newps->barsize);
413 if (ISNULL(newps->pool[i])) {
414 punt = i; /* we will stop cleanup deallocation at punt-1 */
415 break;
416 }
417 }
418
419 /* drain it if can't fill it */
420 if (punt != -1) {
421 FPRINTF(ASCERR,"ERROR: (pool_create_store) : Insufficient memory.\n");
422 for (i = 0; i < punt; i++) {
423 PMEM_free(newps->pool[i]);
424 }
425 newps->integrity = DESTROYED;
426 PMEM_free(newps->pool);
427 PMEM_free(newps);
428 return NULL;
429 }
430 return newps;
431 }
432
433 void *pool_get_element(pool_store_t ps)
434 {
435 /* no automatic variables please */
436 register struct pool_element *elt;
437 /* in a test on the alpha, though, making elt static global slowed it */
438
439 if (ISNULL(ps)) {
440 FPRINTF(ASCERR,"ERROR: (pool_get_element) Called with NULL store.\n");
441 return NULL;
442 }
443 /* recycling */
444 if (ps->onlist) {
445 elt = ps->list; /* get last element put into list */
446 ps->list = ps->list->nextelt; /* pop list */
447 /* preserves original null if list is empty */
448 ps->onlist--;
449 #if !pool_LIGHTENING
450 ps->inuse++;
451 ps->active++;
452 #endif
453 return (void *)elt;
454 }
455
456 /* fresh element */
457 if (ps->curelt == ps->wid) {
458 /* bump up pool if bar all allocated */
459 ps->curelt = 0;
460 ps->curbar++;
461 }
462 if (ps->curbar == ps->len) {
463 /* attempt to expand pool if all allocated */
464 if ( expand_store(ps,1) ) {
465 FPRINTF(ASCERR,"ERROR: (pool_get_element) Insufficient memory.\n");
466 return NULL;
467 }
468 }
469 /* if we got here, pool is big enough to grab an element from */
470
471 /* get the pointer to an element's worth of char from the pool */
472 elt =
473 (struct pool_element *) &(ps->pool[ps->curbar][ps->curelt * ps->eltsize]);
474 ps->curelt++;
475 #if !pool_LIGHTENING
476 ps->inuse++;
477 ps->highwater++;
478 ps->active++;
479 #endif
480 return (void *)elt;
481 }
482
483 void pool_get_element_list(pool_store_t ps, int nelts, void **ary)
484 {
485 FPRINTF(ASCERR,"ERROR: pool_get_element_list NOT implemented\n");
486 if (ISNULL(ps) || ISNULL(ary)) {
487 FPRINTF(ASCERR,"ERROR: pool_get_element_list Called with NULL\n");
488 FPRINTF(ASCERR," array or pool_store_t");
489 return;
490 }
491 if (nelts <1) {
492 FPRINTF(ASCERR,"WARNING: pool_get_element_list Called with request\n");
493 FPRINTF(ASCERR," for 0 elements.");
494 return;
495 }
496 ary[0]=NULL;
497 }
498
499 void pool_free_elementF(pool_store_t ps, void *ptr
500 #if pool_DEBUG
501 , CONST char *fn
502 #endif
503 )
504 {
505 register struct pool_element *elt;
506
507 if (ISNULL(ptr)) return;
508 elt = (struct pool_element *)ptr;
509
510 #if !pool_LIGHTENING
511 #if pool_DEBUG
512 if (check_pool_store(ps)) {
513 FPRINTF(ASCERR,"ERROR: (pool_free_element) Fishy pool_store_t.\n");
514 FPRINTF(ASCERR," Element not recycled.\n");
515 FPRINTF(ASCERR,"%s\n",fn);
516 return;
517 /* at this point we have no way to get back at the abandoned element */
518 }
519 /* check for belongs to this pool_store_t */
520 if (!from_store(ps,ptr)) {
521 FPRINTF(ASCERR,"ERROR: (pool_free_element) Spurious element detected.\n");
522 FPRINTF(ASCERR," Element ignored.\n");
523 FPRINTF(ASCERR,"%s\n",fn);
524 return;
525 }
526 #endif
527 #endif
528
529 /* recycle him */
530 elt->nextelt = ps->list; /* push onto list */
531 /* first one in will pick up the null list starts as */
532 ps->list = elt;
533 /* ptr now on lifo stack in elt linked list form */
534 ps->onlist++;
535
536 #if !pool_LIGHTENING
537 ps->retned++;
538 ps->inuse--;
539 if (ps->inuse < 0) {
540 FPRINTF(ASCERR,"ERROR: (pool_free_element) More elements freed than\n");
541 FPRINTF(ASCERR," have been handed out. (%d)\n",
542 abs(ps->inuse));
543 #if pool_DEBUG
544 FPRINTF(ASCERR,"%s\n",fn);
545 #endif
546 }
547 #endif
548 return;
549 }
550
551 void pool_clear_storeF(pool_store_t ps
552 #if pool_DEBUG
553 , CONST char *fn
554 #endif
555 ) {
556 if ( check_pool_store(ps) > 1 ) {
557 FPRINTF(ASCERR,"ERROR: (pool_clear_store) Bad pool_store_t given.\n");
558 FPRINTF(ASCERR," Not cleared.\n");
559 #if pool_DEBUG
560 FPRINTF(ASCERR,"%s\n",fn);
561 #endif
562 return;
563 }
564 #if pool_DEBUG
565 if (ps->inuse || ps->highwater - ps->onlist ) {
566 FPRINTF(ASCERR,"WARNING: (pool_clear_store) In use elements in given\n");
567 FPRINTF(ASCERR," pool_store_t are cleared.\n");
568 FPRINTF(ASCERR," Don't refer to them again.\n");
569 FPRINTF(ASCERR,"%s\n",fn);
570 }
571 #endif
572 #if !pool_LIGHTENING
573 ps->retned += ps->inuse;
574 if (ps->active - ps->retned ||
575 ps->onlist + ps->inuse - ps->highwater ||
576 ps->curelt + ps->curbar*ps->wid - ps->highwater) {
577 FPRINTF(ASCERR,"Warning: pool_clear_store: Element imbalance detected.\n");
578 #if pool_DEBUG
579 FPRINTF(ASCERR,"%s\n",fn);
580 #endif
581 }
582 #endif
583 #if !pool_LIGHTENING
584 ps->inuse = 0;
585 ps->highwater = 0;
586 #endif
587 ps->curbar = 0;
588 ps->curelt = 0;
589 ps->onlist = 0;
590 ps->list = NULL;
591 }
592
593 void pool_destroy_store(pool_store_t ps)
594 {
595 int i;
596 #if pool_DEBUG
597 if ( (i=check_pool_store(ps))==2 ) {
598 FPRINTF(ASCERR,"ERROR: (pool_destroy_store) Bad pool_store_t given.\n");
599 FPRINTF(ASCERR," Not destroyed.\n");
600 return;
601 }
602 if ( i ) {
603 FPRINTF(ASCERR,
604 "WARNING: (pool_destroy_store) Suspicious pool_store_t given.\n");
605 FPRINTF(ASCERR," Destroyed anyway.\n");
606 return;
607 }
608 if (ps->inuse || ps->highwater - ps->onlist ) {
609 FPRINTF(ASCERR,"WARNING: (pool_destroy_store) In use elements in given\n");
610 FPRINTF(ASCERR," pool_store_t are cleared.\n");
611 FPRINTF(ASCERR,
612 " Don't refer to them again.\n");
613 }
614 #else
615 if (ISNULL(ps) || ps->integrity != OK) {
616 FPRINTF(ASCERR,"ERROR: (pool_destroy_store) Bad pool_store_t given.\n");
617 FPRINTF(ASCERR," Not destroyed.\n");
618 return;
619 }
620 #endif
621 for (i=0; i < ps->len; i++) {
622 PMEM_free(ps->pool[i]);
623 }
624 PMEM_free(ps->pool);
625 ps->integrity = DESTROYED;
626 PMEM_free(ps);
627 return;
628 }
629
630 void pool_print_store(FILE *fp, pool_store_t ps, unsigned detail)
631 {
632 if (ISNULL(fp) || ISNULL(ps)) {
633 FPRINTF(ASCERR,"ERROR: (pool_print_store) Called with NULL\n");
634 FPRINTF(ASCERR," FILE or pool_store_t\n");
635 return;
636 }
637 if (check_pool_store(ps)>1) {
638 FPRINTF(ASCERR,"ERROR: (pool_print_store) Called with bad pool_store_t\n");
639 return;
640 }
641 FPRINTF(fp,"pool_store_t statistics:\n");
642 if (detail) {
643 FPRINTF(fp,"INTERNAL (integrity OK if = %d):\n",OK);
644 FPRINTF(fp,"%-30s %-20d\n","integrity",ps->integrity);
645 #if !pool_LIGHTENING
646 FPRINTF(fp,"%-30s %-20ld\n","active",ps->active);
647 FPRINTF(fp,"%-30s %-20ld\n","returned",ps->retned);
648 #endif
649 FPRINTF(fp,"%-30s %-20lu\n","eltsize",(unsigned long)ps->eltsize);
650 FPRINTF(fp,"%-30s %-20lu\n","barsize",(unsigned long)ps->barsize);
651 FPRINTF(fp,"%-30s %-20d\n","pool length",ps->len);
652 FPRINTF(fp,"%-30s %-20d\n","pool maxlength",ps->maxlen);
653 FPRINTF(fp,"%-30s %-20d\n","bar width",ps->wid);
654 FPRINTF(fp,"%-30s %-20d\n","pool extension",ps->growpool);
655 FPRINTF(fp,"%-30s %-20d\n","pool fill rate",ps->expand);
656 FPRINTF(fp,"%-30s %-20d\n","current bar",ps->curbar);
657 FPRINTF(fp,"%-30s %-20d\n","current elt",ps->curelt);
658 #if !pool_LIGHTENING
659 FPRINTF(fp,"%-30s %-20d\n","total elts",ps->total);
660 FPRINTF(fp,"%-30s %-20d\n","highwater",ps->highwater);
661 #endif
662 FPRINTF(fp,"%-30s %-20d\n","elt on list",ps->onlist);
663 #if !pool_LIGHTENING
664 FPRINTF(fp,"%-30s %-20d\n","elt in use",ps->inuse);
665 #endif
666 }
667 if (!detail || detail > 1) {
668 FPRINTF(fp,"SUMMARY:\n");
669 FPRINTF(fp,"%-30s %-20d\n","Pointers in pool",ps->maxlen);
670 FPRINTF(fp,"%-30s %-20d\n","Pointers allocated",ps->len);
671 #if !pool_LIGHTENING
672 FPRINTF(fp,"%-30s %-20d\n","Elements in pool",ps->total);
673 FPRINTF(fp,"%-30s %-20d\n","Elements in use",ps->inuse);
674 #endif
675 FPRINTF(fp,"%-30s %-20d\n","Elements waiting recycle",ps->onlist);
676 #if !pool_LIGHTENING
677 FPRINTF(fp,"%-30s %-20d\n","Elements unused",ps->total - ps->highwater);
678 #endif
679 FPRINTF(fp,"%-30s %-20d\n","Working deltapool",ps->growpool);
680 FPRINTF(fp,"%-30s %-20d\n","Working deltalen",ps->expand);
681 FPRINTF(fp,"%-30s %-20g\n","Element efficiency",
682 ps->eltsize_req/(double)ps->eltsize);
683 #if !pool_LIGHTENING
684 FPRINTF(fp,"%-30s %-20g\n","Memory efficiency (w/recycle)",
685 ps->highwater*ps->eltsize_req/(double)pool_sizeof_store(ps));
686 FPRINTF(fp,"%-30s %-20g\n","Memory efficiency (instant)",
687 ps->inuse*ps->eltsize_req/(double)pool_sizeof_store(ps));
688 FPRINTF(fp,"%-30s %-20g\n","Recycle rate",
689 ((ps->highwater > 0) ? ps->active/(double)ps->highwater : 0) );
690 #endif
691 }
692 FPRINTF(fp,"%-30s %-20lu\n","Total bytes in store",
693 (unsigned long)pool_sizeof_store(ps));
694
695 return;
696 }
697
698 size_t pool_sizeof_store(pool_store_t ps)
699 {
700 register size_t siz;
701 if (check_pool_store(ps)>1) return (size_t)0;
702 siz = sizeof(struct pool_store_header); /* header */
703 siz += ps->barsize * ps->len; /* elt data */
704 return (siz += ps->maxlen*sizeof(char*)); /* pool vector */
705 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22