/[ascend]/trunk/ascend/utilities/mem.c
ViewVC logotype

Contents of /trunk/ascend/utilities/mem.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2011 - (show annotations) (download) (as text)
Tue Apr 28 08:58:48 2009 UTC (15 years, 8 months ago) by jpye
File MIME type: text/x-csrc
File size: 23205 byte(s)
Moving libascend components from #/base/generic into #/ascend
1 /*
2 * Memory module
3 * by Karl Westerberg, Ben Allan
4 * Created: 6/90
5 * Version: $Revision: 1.7 $
6 * Version control file: $RCSfile: mem.c,v $
7 * Date last modified: $Date: 1998/01/10 18:00:06 $
8 * Last modified by: $Author: ballan $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1997 Carnegie Mellon University
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 "ascConfig.h"
31 #include "ascMalloc.h"
32 #include "mem.h"
33 #include <general/mathmacros.h>
34
35 static void move_fwd(POINTER from, POINTER too, size_t nbytes)
36 /**
37 *** Copies bytes from --> too in forward direction.
38 **/
39 {
40 while( nbytes-- > 0 )
41 *(too++) = *(from++);
42 }
43
44 static void move_bwd(POINTER from, POINTER too, size_t nbytes)
45 /**
46 *** Copies bytes from --> too in backward direction.
47 **/
48 {
49 from += nbytes;
50 too += nbytes;
51 while( nbytes-- > 0 )
52 *(--too) = *(--from);
53 }
54
55 void mem_move_disjoint(POINTER from, POINTER too, size_t nbytes)
56 {
57 ascbcopy((char *)from,(char *)too,nbytes);
58 }
59
60 void mem_move(POINTER from, POINTER too,size_t nbytes)
61 {
62 if( from < too )
63 move_bwd(from,too,nbytes);
64 else
65 move_fwd(from,too,nbytes);
66 }
67
68 /* zeroes nbytes of memory pointed at by too. byte is ignored but
69 * there for interchangability with mem_repl_byte
70 */
71 void mem_zero_byte(POINTER too, unsigned byte, size_t nbytes)
72 {
73 (void)byte;
74 ascbzero((void *)too,(size_t)nbytes);
75 /*
76 * while( nbytes-- > 0 )
77 * *(too++) = 0;
78 */
79 }
80
81 void mem_repl_byte(POINTER too, unsigned byte, size_t nbytes)
82 {
83 while( nbytes-- > 0 )
84 *(too++) = (char)byte;
85 }
86
87 void mem_repl_word(POINTER too,unsigned word, size_t nwords)
88 {
89 unsigned *pw = (unsigned *)too;
90 while( nwords-- > 0 )
91 *(pw++) = word;
92 }
93
94 #define mv_get(too,from,nbytes) move_fwd((POINTER)(from),(POINTER)(too),nbytes)
95 #define mv_set(from,too,nbytes) move_fwd((POINTER)(from),(POINTER)(too),nbytes)
96
97 #if 0
98 int mem_get_byte(long from)
99 {
100 char c;
101 mv_get(&c,from,1);
102 return( ((int)c) & mask_I_L(BYTESIZE) );
103 }
104 #endif /* 0 */
105 unsigned char mem_get_byte(long from)
106 {
107 unsigned char c;
108 mv_get(&c, from, 1);
109 return(c);
110 }
111
112 int mem_get_int(long from)
113 {
114 int i;
115 mv_get(&i,from,sizeof(int));
116 return(i);
117 }
118
119 long mem_get_long(long from)
120 {
121 long l;
122 mv_get(&l,from,sizeof(long));
123 return(l);
124 }
125
126 double mem_get_float(long from)
127 {
128 float f;
129 mv_get(&f,from,sizeof(float));
130 return((double)f);
131 }
132
133 double mem_get_double(long from)
134 {
135 double d;
136 mv_get(&d,from,sizeof(double));
137 return(d);
138 }
139
140 void mem_set_byte(long from, int b)
141 {
142 char c = (char)b;
143 mv_set(&c,from,1);
144 }
145
146 void mem_set_int(long from, int i)
147 {
148 mv_set(&i,from,sizeof(int));
149 }
150
151 void mem_set_long(long from, long l)
152 {
153 mv_set(&l,from,sizeof(long));
154 }
155
156 void mem_set_float(long from, double f)
157 {
158 float ff = (float)f;
159 mv_set(&ff,from,sizeof(float));
160 }
161
162 void mem_set_double(long from, double d)
163 {
164 mv_set(&d,from,sizeof(double));
165 }
166
167 /*********************** mem_store code. BAA 5/16/95 ***********************/
168 /* according to K&R2 char <--> byte and size_t is a byte count.
169 We are coding with those assumptions. (sizeof(char)==1) */
170 #define OK 345676543
171 #define DESTROYED 765434567
172 #if mem_DEBUG
173 /* ground LIGHTENING */
174 #undef mem_LIGHTENING
175 #define mem_LIGHTENING FALSE
176 #endif
177 #define BYPASS_ASCMALLOC FALSE
178 #if (mem_LIGHTENING || BYPASS_ASCMALLOC)
179 /* gonna bypass ascmalloc, eh? ;-) shaame on you! */
180 #define AMEM_calloc(a,b) calloc(a,b)
181 #define AMEM_malloc(a) malloc(a)
182 #define AMEM_free(a) free(a)
183 #define AMEM_realloc(a,b) realloc(a,b)
184 #else
185 #define AMEM_calloc(a,b) asccalloc(a,b)
186 #define AMEM_malloc(a) ascmalloc(a)
187 #define AMEM_free(a) ascfree(a)
188 #define AMEM_realloc(a,b) ascrealloc(a,b)
189 #endif
190
191 /*
192 Don't get caught taking the size of struct mem_element,
193 It is the head for anonymous elements of any size.
194 */
195 struct mem_element {
196 struct mem_element *nextelt;
197 };
198
199 struct mem_store_header {
200 int integrity; /* sanity number. */
201 /* actual data */
202 int maxlen; /* current length of pool, not necessarily w/bars full */
203 char **pool; /* array of pointers to bars */
204 struct mem_element *list; /* pointer to the most recently freed element */
205
206 /* some interesting book keeping quantities */
207 #if !mem_LIGHTENING
208 long active; /* number of elements individually requested, ever */
209 long retned; /* number of elements individually returned, ever */
210 #endif
211 size_t eltsize; /* size of element, often an unsigned (long) */
212 size_t eltsize_req; /* size of element, often an unsigned (long) */
213 size_t barsize; /* size of bar. no point in extra multiplications */
214
215 /* memory management quantities */
216 int len; /* number of bars filled (length of pool filled) */
217 int wid; /* num elements in a bar */
218 int expand; /* number of bars to expand by usually */
219 int growpool; /* expansion increment for pool array */
220 int curbar; /* pool entry from which fresh elements may be had */
221 int curelt; /* number of the next element in the curbar to hand out */
222 int onlist; /* length of recycle list, in elements */
223 #if !mem_LIGHTENING
224 int total; /* total number of elements in this store */
225 int highwater; /* fresh elements turned loose from store */
226 int inuse; /* current elts user has outstanding */
227 #endif
228 };
229 /* notes on header:
230 * list is, as currently coded, null terminated by accident.
231 * The intent of the author is that the counter onlist is the
232 * authoritative list length.
233 */
234
235 #define AMEM_MINBARSIZE 5
236 #define AMEM_MINPOOLSIZE 2
237 #ifdef __alpha
238 #define AMEM_MINPOOLGROW 512
239 /* gotta love those fat pointers. grow by 4k min. */
240 #else
241 #define AMEM_MINPOOLGROW 1024
242 #endif
243
244 /*
245 Returns 2 if really bad, 1 if something fishy, 0 otherwise.
246 */
247 static int check_mem_store(const mem_store_t ms)
248 {
249 #if mem_LIGHTENING
250 return 0;
251 #else
252 int i;
253
254 if (ISNULL(ms)) {
255 FPRINTF(stderr,"check_mem_store (mem.c): NULL mem_store_t!\n");
256 return 2;
257 }
258 if (ms->integrity != OK) {
259 (ms->integrity == DESTROYED) ?
260 FPRINTF(stderr,
261 "check_mem_store (mem.c): mem_store_t recently destroyed!\n")
262 : FPRINTF(stderr,
263 "check_mem_store (mem.c): mem_store_t corrupted!\n");
264 return 2;
265 }
266 if (ms->onlist && ISNULL(ms->list)) {
267 FPRINTF(stderr, "ERROR: check_mem_store (mem.c): NULL recycle list!\n");
268 return 1;
269 }
270 /* more in than out? */
271 if (ms->retned > ms->active) {
272 FPRINTF(stderr, "ERROR: check_mem_store (mem.c): Imbalanced memory.\n");
273 return 1;
274 }
275 if (ms->onlist + ms->inuse != ms->highwater) {
276 FPRINTF(stderr, "ERROR: check_mem_store (mem.c): Imbalanced elements.\n");
277 return 1;
278 }
279 /* is pool allocated to ms->len? */
280 for (i=0; i < ms->len; i++) {
281 if (ISNULL(ms->pool[i])) {
282 FPRINTF(stderr, "ERROR: check_mem_store (mem.c): Hole found in pool!\n");
283 FPRINTF(stderr, " Bar %d is NULL.\n",i);
284 return 2;
285 }
286 }
287 /* do not check for integrity or count of recycle list elements. */
288 return 0;
289 #endif
290 }
291
292 /*
293 This should not be called unless all current store is in use.
294 Returns 0 if ok, 1 for all other insanities.
295 If only partial expansion is possible, we will do it and
296 return 0. If change in ms->len is < the expected incremented value
297 on return, the user knows he should do some garbage removal.
298 incr is provided for times when we know how much we want
299 to expand by.
300 */
301 static int expand_store(mem_store_t ms, int incr)
302 {
303 static int oldsize, newsize,punt,i;
304 char **newpool = NULL;
305 if (check_mem_store(ms) >1) {
306 FPRINTF(stderr,"ERROR: (mem.c) expand_store received bad\n");
307 FPRINTF(stderr," mem_store_t. Expansion failed.\n");
308 return 1;
309 }
310
311 #if !mem_LIGHTENING
312 /* do not expand elements or pool if all is not in use */
313 if (ms->inuse < ms->total) {
314 FPRINTF(stderr,"ERROR: (mem.c) expand_store called prematurely.\n");
315 FPRINTF(stderr," Expansion will be reported as failed.\n");
316 return 1;
317 }
318 #endif
319
320 /* make sure bar expansion is at least the minimum */
321 if (incr < ms->expand) incr = ms->expand;
322 oldsize = ms->len;
323 newsize = oldsize+incr;
324
325 /* expand pool capacity only if all of pool in use */
326 if (newsize > ms->maxlen) {
327 i = ms->maxlen + MAX(ms->growpool,incr);
328 newpool = (char **)AMEM_realloc(ms->pool, i*sizeof(char *));
329 if (ISNULL(newpool)) {
330 FPRINTF(stderr,"ERROR: (mem.c) expand_store can't realloc pool.\n");
331 return 1;
332 }
333 /* NULL the new pool */
334 for (punt = ms->maxlen; punt < i; punt++) {
335 newpool[punt] = NULL;
336 }
337 ms->maxlen = i;
338 ms->pool = newpool;
339 }
340 /* end of pool expansion */
341
342 /* expand elements/bars */
343 ms->len = newsize; /* set expanded number of bars filled */
344 punt = -1;
345 for (i = oldsize; i < newsize; i++) {
346 #if mem_DEBUG
347 ms->pool[i] = (char *)AMEM_calloc(ms->barsize,1);
348 #else
349 ms->pool[i] = (char *)AMEM_malloc(ms->barsize);
350 #endif
351 if (ISNULL(ms->pool[i])) {
352 punt = i;
353 /* we will return partially expanded if possible */
354 break;
355 }
356 }
357 if (punt >= 0) {
358 /* incomplete expansion */
359 if (punt == oldsize) {
360 /* unable to add elements at all. fail */
361 FPRINTF(stderr,"ERROR: (mem) expand_store: Insufficient memory.\n");
362 ms->len = oldsize;
363 return 1;
364 } else {
365 /* contract pool to the actual expansion size */
366 FPRINTF(stderr,"WARNING: (mem) expand_store: Insufficient memory.\n");
367 FPRINTF(stderr," Doing partial expansion.\n");
368 ms->len = punt;
369 }
370 }
371 #if !mem_LIGHTENING
372 ms->total = ms->len * ms->wid;
373 #endif
374 return 0;
375 }
376
377 #if !mem_LIGHTENING
378 #if mem_DEBUG
379 /*
380 Returns 1 if pointer is to an elt of the store, 0 otherwise.
381 The case of pointer into store reserved space, but not an elt is checked.
382 */
383 static int from_store( mem_store_t ms, void *elt)
384 {
385 char *data;
386 char **pool;
387 int i;
388 int lim;
389
390 if (ISNULL(ms) || ISNULL(elt)) return 0;
391 lim = ms->len;
392 pool = ms->pool;
393 data = (char *)elt;
394 for (i=0; i<lim; i++) {
395 /* did the char come from the current bar of chars? */
396 if (*pool <= data && data < *pool + ms->barsize) {
397 /* if so, is it legal? */
398 if ( !((data - (*pool)) % ms->eltsize) ) {
399 return 1;
400 } else {
401 FPRINTF(stderr,"ERROR: (mem.c) from_store: Misaligned element\n");
402 FPRINTF(stderr," pointer detected.\n");
403 return 0;
404 }
405 }
406 pool++;
407 }
408 return 0;
409 }
410 #endif
411 #endif
412
413 void mem_get_stats(struct mem_statistics *mss, mem_store_t m)
414 {
415 if (ISNULL(mss)) {
416 FPRINTF(stderr,"ERROR: (mem_get_stats) Called with NULL struct\n");
417 FPRINTF(stderr," mem_statistics.\n");
418 return;
419 }
420 if (check_mem_store(m)>1 ) {
421 ascbzero((void *)mss,(size_t)sizeof(struct mem_statistics));
422 FPRINTF(stderr,"ERROR: (mem_get_stats) Bad mem_store_t given.\n");
423 FPRINTF(stderr," Returning 0s.\n");
424 return;
425 }
426 #if !mem_LIGHTENING
427 mss->m_eff = (double)(m->inuse * m->eltsize_req)/(double)mem_sizeof_store(m);
428 mss->m_recycle =
429 ( (m->highwater > 0) ? (double)m->active/(double)m->highwater : 0.0 );
430 mss->elt_total = m->total;
431 mss->elt_taken = m->highwater;
432 mss->elt_inuse = m->inuse;
433 #else
434 mss->m_eff = 0.0;
435 mss->m_recycle = 0.0;
436 mss->elt_total = m->len*m->wid;
437 mss->elt_taken = m->curelt+m->curbar*m->wid;
438 mss->elt_inuse = 0;
439 #endif
440 mss->elt_onlist = m->onlist;
441 mss->elt_size = (int)m->eltsize;
442 mss->str_len = m->len;
443 mss->str_wid = m->wid;
444 }
445
446 mem_store_t mem_create_store(int length, int width,
447 size_t eltsize, int deltalen, int deltapool)
448 {
449 int i, punt;
450 mem_store_t newms=NULL;
451 size_t uelt;
452
453 if (length < 1 || width < 1 || deltalen < 1 ) {
454 FPRINTF(stderr,"ERROR: (mem_create_store) : Bad input detected.\n");
455 return NULL;
456 }
457
458 /* check minsizes */
459 if (length < AMEM_MINPOOLSIZE) length = AMEM_MINPOOLSIZE;
460 if (width < AMEM_MINBARSIZE) width = AMEM_MINBARSIZE;
461 /* maybe the user gave us length = max he knows he needs, so we
462 will not enforce a minimum maxlen on length at creation */
463
464 uelt = eltsize;
465 /* check for elt padding needed */
466 if (eltsize % sizeof(void *)) {
467 size_t ptrperelt;
468 ptrperelt = eltsize/sizeof(void *) + 1;
469 #if mem_DEBUG
470 FPRINTF(stderr,"(mem_create_store) Elts of size %d padded to %d\n",
471 eltsize,(eltsize=ptrperelt*sizeof(void *)));
472 #else
473 eltsize = ptrperelt*sizeof(void *);
474 #endif
475 }
476 /* eltsize is now pointer alignable */
477 /* it could still be user data misalignable, of course, if pointer
478 is not the most restrictive data type for the machine */
479
480
481 newms = (mem_store_t)AMEM_calloc(1,sizeof(struct mem_store_header));
482 if (ISNULL(newms)) {
483 FPRINTF(stderr,"ERROR: (mem_create_store) : Insufficient memory.\n");
484 return NULL;
485 }
486 /* the following are all initially 0/NULL by calloc, and should be:
487 newms->list
488 newms->active
489 newms->retned
490 newms->curbar
491 newms->curelt
492 newms->highwater
493 newms->onlist
494 newms->inuse
495 newms->pool
496 */
497 newms->integrity = OK;
498 newms->len = length;
499 newms->maxlen = length;
500 newms->wid = width;
501 newms->expand = deltalen;
502 newms->eltsize = eltsize;
503 newms->barsize = eltsize * width;
504 #if !mem_LIGHTENING
505 newms->total = length * width;
506 #endif
507 newms->growpool = MAX(AMEM_MINPOOLGROW,deltapool);
508 newms->eltsize_req = uelt;
509
510 /* get pool */
511 newms->pool = (char **)AMEM_calloc((size_t)length,sizeof(char *));
512 if (ISNULL(newms->pool)) {
513 FPRINTF(stderr,"ERROR: (mem_create_store) : Insufficient memory.\n");
514 newms->integrity = DESTROYED;
515 AMEM_free(newms);
516 return NULL;
517 }
518
519 /* fill it */
520 punt = -1;
521 for (i=0; i < length; i++) {
522 newms->pool[i] = (char *)AMEM_malloc(newms->barsize);
523 if (ISNULL(newms->pool[i])) {
524 punt = i; /* we will stop cleanup deallocation at punt-1 */
525 break;
526 }
527 }
528
529 /* drain it if can't fill it */
530 if (punt != -1) {
531 FPRINTF(stderr,"ERROR: (mem_create_store) : Insufficient memory.\n");
532 for (i = 0; i < punt; i++) {
533 AMEM_free(newms->pool[i]);
534 }
535 newms->integrity = DESTROYED;
536 AMEM_free(newms->pool);
537 AMEM_free(newms);
538 return NULL;
539 }
540 return newms;
541 }
542
543 void *mem_get_element(mem_store_t ms)
544 {
545 /* no automatic variables please */
546 register struct mem_element *elt;
547 /* in a test on the alpha, though, making elt static global slowed it */
548
549 if (ISNULL(ms)) {
550 FPRINTF(stderr,"ERROR: (mem_get_element) Called with NULL store.\n");
551 return NULL;
552 }
553 /* recycling */
554 if (ms->onlist) {
555 elt = ms->list; /* get last element put into list */
556 ms->list = ms->list->nextelt; /* pop list */
557 /* preserves original null if list is empty */
558 ms->onlist--;
559 #if !mem_LIGHTENING
560 ms->inuse++;
561 ms->active++;
562 #endif
563 return (void *)elt;
564 }
565
566 /* fresh element */
567 if (ms->curelt == ms->wid) {
568 /* bump up pool if bar all allocated */
569 ms->curelt = 0;
570 ms->curbar++;
571 }
572 if (ms->curbar == ms->len) {
573 /* attempt to expand pool if all allocated */
574 if ( expand_store(ms,1) ) {
575 FPRINTF(stderr,"ERROR: (mem_get_element) Insufficient memory.\n");
576 return NULL;
577 }
578 }
579 /* if we got here, pool is big enough to grab an element from */
580
581 /* get the pointer to an element's worth of char from the pool */
582 elt =
583 (struct mem_element *) &(ms->pool[ms->curbar][ms->curelt * ms->eltsize]);
584 ms->curelt++;
585 #if !mem_LIGHTENING
586 ms->inuse++;
587 ms->highwater++;
588 ms->active++;
589 #endif
590 return (void *)elt;
591 }
592
593 void mem_get_element_list(mem_store_t ms, int nelts, void **ary)
594 {
595 FPRINTF(stderr,"ERROR: mem_get_element_list NOT implemented\n");
596 if (ISNULL(ms) || ISNULL(ary)) {
597 FPRINTF(stderr,"ERROR: mem_get_element_list Called with NULL\n");
598 FPRINTF(stderr," array or mem_store_t");
599 return;
600 }
601 if (nelts <1) {
602 FPRINTF(stderr,"WARNING: mem_get_element_list Called with request\n");
603 FPRINTF(stderr," for 0 elements.");
604 return;
605 }
606 ary[0]=NULL;
607 }
608
609 void mem_free_element(mem_store_t ms, void *ptr)
610 {
611 register struct mem_element *elt;
612
613 if (ISNULL(ptr)) return;
614 elt = (struct mem_element *)ptr;
615
616 #if !mem_LIGHTENING
617 #if mem_DEBUG
618 if (check_mem_store(ms)) {
619 FPRINTF(stderr,"ERROR: (mem_free_element) Fishy mem_store_t.\n");
620 FPRINTF(stderr," Element not recycled.\n");
621 return;
622 /* at this point we have no way to get back at the abandoned element */
623 }
624 /* check for belongs to this mem_store_t */
625 if (!from_store(ms,ptr)) {
626 FPRINTF(stderr,"ERROR: (mem_free_element) Spurious element detected.\n");
627 FPRINTF(stderr," Element ignored.\n");
628 return;
629 }
630 #endif
631 #endif
632
633 /* recycle him */
634 elt->nextelt = ms->list; /* push onto list */
635 /* first one in will pick up the null list starts as */
636 ms->list = elt;
637 /* ptr now on lifo stack in elt linked list form */
638 ms->onlist++;
639
640 #if !mem_LIGHTENING
641 ms->retned++;
642 ms->inuse--;
643 if (ms->inuse < 0) {
644 FPRINTF(stderr,"ERROR: (mem_free_element) More elements freed than\n");
645 FPRINTF(stderr," have been handed out. (%d)\n",
646 abs(ms->inuse));
647 }
648 #endif
649 return;
650 }
651
652 void mem_clear_store(mem_store_t ms) {
653 if ( check_mem_store(ms) > 1 ) {
654 FPRINTF(stderr,"ERROR: (mem_clear_store) Bad mem_store_t given.\n");
655 FPRINTF(stderr," Not cleared.\n");
656 return;
657 }
658 #if mem_DEBUG
659 if (ms->inuse || ms->highwater - ms->onlist ) {
660 FPRINTF(stderr,"WARNING: (mem_clear_store) In use elements in given\n");
661 FPRINTF(stderr," mem_store_t are cleared.\n");
662 FPRINTF(stderr," Don't refer to them again.\n");
663 }
664 #endif
665 ms->retned += ms->inuse;
666 if (ms->active - ms->retned ||
667 ms->onlist + ms->inuse - ms->highwater ||
668 ms->curelt + ms->curbar*ms->wid - ms->highwater) {
669 FPRINTF(stderr,"Warning: mem_clear_store: Element imbalance detected.\n");
670 }
671 ms->inuse = 0;
672 ms->curbar = 0;
673 ms->curelt = 0;
674 ms->highwater = 0;
675 ms->onlist = 0;
676 ms->list = NULL;
677 }
678
679 void mem_destroy_store(mem_store_t ms)
680 {
681 int i;
682 #if mem_DEBUG
683 if ( (i=check_mem_store(ms))==2 ) {
684 FPRINTF(stderr,"ERROR: (mem_destroy_store) Bad mem_store_t given.\n");
685 FPRINTF(stderr," Not destroyed.\n");
686 return;
687 }
688 if ( i ) {
689 FPRINTF(stderr,
690 "WARNING: (mem_destroy_store) Suspicious mem_store_t given.\n");
691 FPRINTF(stderr," Destroyed anyway.\n");
692 return;
693 }
694 if (ms->inuse || ms->highwater - ms->onlist ) {
695 FPRINTF(stderr,"WARNING: (mem_destroy_store) In use elements in given\n");
696 FPRINTF(stderr," mem_store_t are cleared.\n");
697 FPRINTF(stderr," Don't refer to them again.\n");
698 }
699 #else
700 if (ISNULL(ms) || ms->integrity != OK) {
701 FPRINTF(stderr,"ERROR: (mem_destroy_store) Bad mem_store_t given.\n");
702 FPRINTF(stderr," Not destroyed.\n");
703 return;
704 }
705 #endif
706 for (i=0; i < ms->len; i++) {
707 AMEM_free(ms->pool[i]);
708 }
709 AMEM_free(ms->pool);
710 ms->integrity = DESTROYED;
711 AMEM_free(ms);
712 return;
713 }
714
715 void mem_print_store(FILE *fp, mem_store_t ms, unsigned detail)
716 {
717 if (ISNULL(fp) || ISNULL(ms)) {
718 FPRINTF(stderr,"ERROR: (mem_print_store) Called with NULL\n");
719 FPRINTF(stderr," FILE or mem_store_t\n");
720 return;
721 }
722 if (check_mem_store(ms)>1) {
723 FPRINTF(stderr,"ERROR: (mem_print_store) Called with bad mem_store_t\n");
724 return;
725 }
726 FPRINTF(fp,"mem_store_t statistics:\n");
727 if (detail) {
728 FPRINTF(fp,"INTERNAL (integrity OK if = %d):\n",OK);
729 FPRINTF(fp,"%-30s %-20ld\n","integrity", (long)ms->integrity);
730 #if !mem_LIGHTENING
731 FPRINTF(fp,"%-30s %-20ld\n","active",ms->active);
732 FPRINTF(fp,"%-30s %-20ld\n","returned",ms->retned);
733 #endif
734 FPRINTF(fp,"%-30s %-20lu\n","eltsize",(unsigned long)ms->eltsize);
735 FPRINTF(fp,"%-30s %-20lu\n","barsize",(unsigned long)ms->barsize);
736 FPRINTF(fp,"%-30s %-20d\n","pool length",ms->len);
737 FPRINTF(fp,"%-30s %-20d\n","pool maxlength",ms->maxlen);
738 FPRINTF(fp,"%-30s %-20d\n","bar width",ms->wid);
739 FPRINTF(fp,"%-30s %-20d\n","pool extension",ms->growpool);
740 FPRINTF(fp,"%-30s %-20d\n","pool fill rate",ms->expand);
741 FPRINTF(fp,"%-30s %-20d\n","current bar",ms->curbar);
742 FPRINTF(fp,"%-30s %-20d\n","current elt",ms->curelt);
743 #if !mem_LIGHTENING
744 FPRINTF(fp,"%-30s %-20d\n","total elts",ms->total);
745 FPRINTF(fp,"%-30s %-20d\n","highwater",ms->highwater);
746 #endif
747 FPRINTF(fp,"%-30s %-20d\n","elt on list",ms->onlist);
748 #if !mem_LIGHTENING
749 FPRINTF(fp,"%-30s %-20d\n","elt in use",ms->inuse);
750 #endif
751 }
752 if (!detail || detail > 1) {
753 FPRINTF(fp,"SUMMARY:\n");
754 FPRINTF(fp,"%-30s %-20d\n","Pointers in pool",ms->maxlen);
755 FPRINTF(fp,"%-30s %-20d\n","Pointers allocated",ms->len);
756 #if !mem_LIGHTENING
757 FPRINTF(fp,"%-30s %-20d\n","Elements in pool",ms->total);
758 FPRINTF(fp,"%-30s %-20d\n","Elements in use",ms->inuse);
759 #endif
760 FPRINTF(fp,"%-30s %-20d\n","Elements waiting recycle",ms->onlist);
761 #if !mem_LIGHTENING
762 FPRINTF(fp,"%-30s %-20d\n","Elements unused",ms->total - ms->highwater);
763 #endif
764 FPRINTF(fp,"%-30s %-20d\n","Working deltapool",ms->growpool);
765 FPRINTF(fp,"%-30s %-20d\n","Working deltalen",ms->expand);
766 FPRINTF(fp,"%-30s %-20g\n","Element efficiency",
767 ms->eltsize_req/(double)ms->eltsize);
768 #if !mem_LIGHTENING
769 FPRINTF(fp,"%-30s %-20g\n","Memory efficiency (w/recycle)",
770 ms->highwater*ms->eltsize_req/(double)mem_sizeof_store(ms));
771 FPRINTF(fp,"%-30s %-20g\n","Memory efficiency (instant)",
772 ms->inuse*ms->eltsize_req/(double)mem_sizeof_store(ms));
773 FPRINTF(fp,"%-30s %-20g\n","Recycle rate",
774 ((ms->highwater > 0) ? ms->active/(double)ms->highwater : 0) );
775 #endif
776 }
777 FPRINTF(fp,"%-30s %-20lu\n","Total bytes in store",
778 (unsigned long)mem_sizeof_store(ms));
779
780 return;
781 }
782
783 size_t mem_sizeof_store(mem_store_t ms)
784 {
785 register size_t siz;
786 if (check_mem_store(ms)>1) return (size_t)0;
787 siz = sizeof(struct mem_store_header); /* header */
788 siz += ms->barsize * ms->len; /* elt data */
789 return (siz += ms->maxlen*sizeof(char*)); /* pool vector */
790 }

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