1/* -----------------------------------------------------------------------------
2 * memory.c
3 *
4 *     This file implements all of DOH's memory management including allocation
5 *     of objects and checking of objects.
6 *
7 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
8 *
9 * Copyright (C) 1999-2000.  The University of Chicago
10 * See the file LICENSE for information on usage and redistribution.
11 * ----------------------------------------------------------------------------- */
12
13char cvsroot_memory_c[] = "$Id: memory.c 9607 2006-12-05 22:11:40Z beazley $";
14
15#include "dohint.h"
16
17#ifndef DOH_POOL_SIZE
18#define DOH_POOL_SIZE         16384
19#endif
20
21static int PoolSize = DOH_POOL_SIZE;
22
23DOH *DohNone = 0;		/* The DOH None object */
24
25typedef struct pool {
26  DohBase *ptr;			/* Start of pool */
27  int len;			/* Length of pool */
28  int blen;			/* Byte length of pool */
29  int current;			/* Current position for next allocation */
30  char *pbeg;			/* Beg of pool */
31  char *pend;			/* End of pool */
32  struct pool *next;		/* Next pool */
33} Pool;
34
35static DohBase *FreeList = 0;	/* List of free objects */
36static Pool *Pools = 0;
37static int pools_initialized = 0;
38
39/* ----------------------------------------------------------------------
40 * CreatePool() - Create a new memory pool
41 * ---------------------------------------------------------------------- */
42
43static void CreatePool() {
44  Pool *p = 0;
45  p = (Pool *) DohMalloc(sizeof(Pool));
46  assert(p);
47  p->ptr = (DohBase *) DohMalloc(sizeof(DohBase) * PoolSize);
48  assert(p->ptr);
49  memset(p->ptr, 0, sizeof(DohBase) * PoolSize);
50  p->len = PoolSize;
51  p->blen = PoolSize * sizeof(DohBase);
52  p->current = 0;
53  p->pbeg = ((char *) p->ptr);
54  p->pend = p->pbeg + p->blen;
55  p->next = Pools;
56  Pools = p;
57}
58
59/* ----------------------------------------------------------------------
60 * InitPools() - Initialize the memory allocator
61 * ---------------------------------------------------------------------- */
62
63static void InitPools() {
64  if (pools_initialized)
65    return;
66  CreatePool();			/* Create initial pool */
67  pools_initialized = 1;
68  DohNone = NewVoid(0, 0);	/* Create the None object */
69  DohIntern(DohNone);
70}
71
72/* ----------------------------------------------------------------------
73 * DohCheck()
74 *
75 * Returns 1 if an arbitrary pointer is a DOH object.
76 * ---------------------------------------------------------------------- */
77
78int DohCheck(const DOH *ptr) {
79  register Pool *p = Pools;
80  register char *cptr = (char *) ptr;
81  while (p) {
82    if ((cptr >= p->pbeg) && (cptr < p->pend))
83      return 1;
84    /*
85       pptr = (char *) p->ptr;
86       if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */
87    p = p->next;
88  }
89  return 0;
90}
91
92/* -----------------------------------------------------------------------------
93 * DohIntern()
94 * ----------------------------------------------------------------------------- */
95
96void DohIntern(DOH *obj) {
97  DohBase *b = (DohBase *) obj;
98  b->flag_intern = 1;
99}
100
101/* ----------------------------------------------------------------------
102 * DohObjMalloc()
103 *
104 * Allocate memory for a new object.
105 * ---------------------------------------------------------------------- */
106
107DOH *DohObjMalloc(DohObjInfo *type, void *data) {
108  DohBase *obj;
109  if (!pools_initialized)
110    InitPools();
111  if (FreeList) {
112    obj = FreeList;
113    FreeList = (DohBase *) obj->data;
114  } else {
115    while (Pools->current == Pools->len) {
116      CreatePool();
117    }
118    obj = Pools->ptr + Pools->current;
119    ++Pools->current;
120  }
121  obj->type = type;
122  obj->data = data;
123  obj->meta = 0;
124  obj->refcount = 1;
125  obj->flag_intern = 0;
126  obj->flag_marked = 0;
127  obj->flag_user = 0;
128  obj->flag_usermark = 0;
129  return (DOH *) obj;
130}
131
132/* ----------------------------------------------------------------------
133 * DohObjFree() - Free a DOH object
134 * ---------------------------------------------------------------------- */
135
136void DohObjFree(DOH *ptr) {
137  DohBase *b, *meta;
138  b = (DohBase *) ptr;
139  if (b->flag_intern)
140    return;
141  meta = (DohBase *) b->meta;
142  b->data = (void *) FreeList;
143  b->meta = 0;
144  b->type = 0;
145  FreeList = b;
146  if (meta) {
147    Delete(meta);
148  }
149}
150
151/* ----------------------------------------------------------------------
152 * DohMemoryDebug()
153 *
154 * Display memory usage statistics
155 * ---------------------------------------------------------------------- */
156
157void DohMemoryDebug(void) {
158  extern DohObjInfo DohStringType;
159  extern DohObjInfo DohListType;
160  extern DohObjInfo DohHashType;
161
162  Pool *p;
163  int totsize = 0;
164  int totused = 0;
165  int totfree = 0;
166
167  int numstring = 0;
168  int numlist = 0;
169  int numhash = 0;
170
171  printf("Memory statistics:\n\n");
172  printf("Pools:\n");
173
174  p = Pools;
175  while (p) {
176    /* Calculate number of used, free items */
177    int i;
178    int nused = 0, nfree = 0;
179    for (i = 0; i < p->len; i++) {
180      if (p->ptr[i].refcount <= 0)
181	nfree++;
182      else {
183	nused++;
184	if (p->ptr[i].type == &DohStringType)
185	  numstring++;
186	else if (p->ptr[i].type == &DohListType)
187	  numlist++;
188	else if (p->ptr[i].type == &DohHashType)
189	  numhash++;
190      }
191    }
192    printf("    Pool %8p: size = %10d. used = %10d. free = %10d\n", (void *) p, p->len, nused, nfree);
193    totsize += p->len;
194    totused += nused;
195    totfree += nfree;
196    p = p->next;
197  }
198  printf("\n    Total:          size = %10d, used = %10d, free = %10d\n", totsize, totused, totfree);
199
200  printf("\nObject types\n");
201  printf("    Strings   : %d\n", numstring);
202  printf("    Lists     : %d\n", numlist);
203  printf("    Hashes    : %d\n", numhash);
204
205#if 0
206  p = Pools;
207  while (p) {
208    int i;
209    for (i = 0; i < p->len; i++) {
210      if (p->ptr[i].refcount > 0) {
211	if (p->ptr[i].type == &DohStringType) {
212	  Printf(stdout, "%s\n", p->ptr + i);
213	}
214      }
215    }
216    p = p->next;
217  }
218#endif
219
220}
221