jabberd2  2.6.1
pool.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "util.h"
22 #include "pool.h"
23 
24 #ifdef POOL_DEBUG
25 int pool__total = 0;
26 int pool__ltotal = 0;
27 xht pool__disturbed = NULL;
28 void *_pool__malloc(size_t size)
29 {
30  pool__total++;
31  return malloc(size);
32 }
33 void _pool__free(void *block)
34 {
35  pool__total--;
36  free(block);
37 }
38 #else
39 #define _pool__malloc malloc
40 #define _pool__free free
41 #endif
42 
43 
45 pool_t _pool_new(const char *zone, int line)
46 {
47  pool_t p;
48  while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
49  p->cleanup = NULL;
50  p->heap = NULL;
51  p->size = 0;
52 
53 #ifdef POOL_DEBUG
54  p->lsize = -1;
55  p->zone[0] = '\0';
56  snprintf(p->zone, sizeof(p->zone), "%s:%i", zone, line);
57  sprintf(p->name,"%X",(int)p);
58 
59  if(pool__disturbed == NULL)
60  {
61  pool__disturbed = (xht)1; /* reentrancy flag! */
62  pool__disturbed = xhash_new(POOL_NUM);
63  }
64  if(pool__disturbed != (xht)1)
65  xhash_put(pool__disturbed,p->name,p);
66 #endif
67 
68  return p;
69 }
70 
72 static void _pool_heap_free(void *arg)
73 {
74  struct pheap *h = (struct pheap *)arg;
75 
76  _pool__free(h->block);
77  _pool__free(h);
78 }
79 
81 static void _pool_cleanup_append(pool_t p, struct pfree *pf)
82 {
83  struct pfree *cur;
84 
85  if(p->cleanup == NULL)
86  {
87  p->cleanup = pf;
88  p->cleanup_tail = pf;
89  return;
90  }
91 
92  /* append at end of list */
93  cur = p->cleanup_tail;
94  cur->next = pf;
95  p->cleanup_tail = pf;
96 }
97 
99 static struct pfree *_pool_free(pool_t p, pool_cleanup_t f, void *arg)
100 {
101  struct pfree *ret;
102 
103  /* make the storage for the tracker */
104  while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
105  ret->f = f;
106  ret->arg = arg;
107  ret->next = NULL;
108 
109  return ret;
110 }
111 
113 static struct pheap *_pool_heap(pool_t p, int size)
114 {
115  struct pheap *ret;
116  struct pfree *clean;
117 
118  /* make the return heap */
119  while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1);
120  while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
121  ret->size = size;
122  p->size += size;
123  ret->used = 0;
124 
125  /* append to the cleanup list */
126  clean = _pool_free(p, _pool_heap_free, (void *)ret);
127  clean->heap = ret; /* for future use in finding used mem for pstrdup */
128  _pool_cleanup_append(p, clean);
129 
130  return ret;
131 }
132 
133 pool_t _pool_new_heap(int size, const char *zone, int line)
134 {
135  pool_t p;
136  p = _pool_new(zone, line);
137  p->heap = _pool_heap(p,size);
138  return p;
139 }
140 
141 void *pmalloc(pool_t p, int size)
142 {
143  void *block;
144 
145  if(p == NULL)
146  {
147  fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
148  abort();
149  }
150 
151  /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */
152  if(p->heap == NULL || size > (p->heap->size / 2))
153  {
154  while((block = _pool__malloc(size)) == NULL) sleep(1);
155  p->size += size;
157  return block;
158  }
159 
160  /* we have to preserve boundaries, long story :) */
161  if(size >= 4)
162  while(p->heap->used&7) p->heap->used++;
163 
164  /* if we don't fit in the old heap, replace it */
165  if(size > (p->heap->size - p->heap->used))
166  p->heap = _pool_heap(p, p->heap->size);
167 
168  /* the current heap has room */
169  block = (char *)p->heap->block + p->heap->used;
170  p->heap->used += size;
171  return block;
172 }
173 
174 void *pmalloc_x(pool_t p, int size, char c)
175 {
176  void* result = pmalloc(p, size);
177  if (result != NULL)
178  memset(result, c, size);
179  return result;
180 }
181 
183 void *pmalloco(pool_t p, int size)
184 {
185  void *block = pmalloc(p, size);
186  memset(block, 0, size);
187  return block;
188 }
189 
191 char *pstrdup(pool_t p, const char *src)
192 {
193  char *ret;
194 
195  if(src == NULL)
196  return NULL;
197 
198  ret = pmalloc(p,strlen(src) + 1);
199  strcpy(ret,src);
200 
201  return ret;
202 }
203 
205 char *pstrdupx(pool_t p, const char *src, int len)
206 {
207  char *ret;
208 
209  if(src == NULL || len <= 0)
210  return NULL;
211 
212  ret = pmalloc(p,len + 1);
213  memcpy(ret,src,len);
214  ret[len] = '\0';
215 
216  return ret;
217 }
218 
220 {
221  if(p == NULL) return 0;
222 
223  return p->size;
224 }
225 
227 {
228  struct pfree *cur, *stub;
229 
230  if(p == NULL) return;
231 
232  cur = p->cleanup;
233  while(cur != NULL)
234  {
235  (*cur->f)(cur->arg);
236  stub = cur->next;
237  _pool__free(cur);
238  cur = stub;
239  }
240 
241 #ifdef POOL_DEBUG
242  if (pool__disturbed != NULL && pool__disturbed != (xht)1)
243  xhash_zap(pool__disturbed,p->name);
244 #endif
245 
246  _pool__free(p);
247 
248 }
249 
252 {
253  struct pfree *clean;
254 
255  clean = _pool_free(p, f, arg);
256  clean->next = p->cleanup;
257  p->cleanup = clean;
258 }
259 
260 #ifdef POOL_DEBUG
261 void _pool_stat(const char *key, int keylen, void *val, void *arg)
262 {
263  pool_t p = (pool_t)val;
264 
265  if(p->lsize == -1)
266  fprintf(stderr, "POOL: %s: %s is a new pool\n",p->zone,p->name);
267  else if(p->size > p->lsize)
268  fprintf(stderr, "POOL: %s: %s grew %d\n",p->zone,p->name, p->size - p->lsize);
269  else if((int)arg)
270  fprintf(stderr, "POOL: %s: %s exists %d\n",p->zone,p->name, p->size);
271  p->lsize = p->size;
272 }
273 
274 void pool_stat(int full)
275 {
276  if (pool__disturbed == NULL || pool__disturbed == (xht)1)
277  return;
278  xhash_walk(pool__disturbed,_pool_stat,(void *)full);
279  if(pool__total != pool__ltotal)
280  fprintf(stderr, "POOL: %d total missed mallocs\n",pool__total);
281  pool__ltotal = pool__total;
282  return;
283 }
284 #else
285 void pool_stat(int full)
286 {
287  return;
288 }
289 #endif
struct xht_struct * xht
void pool_free(pool_t p)
Definition: pool.c:226
void * block
Definition: pool.h:60
void * pmalloc(pool_t p, int size)
Definition: pool.c:141
#define _pool__free
Definition: pool.c:40
int size
Definition: pool.h:61
pool_t _pool_new(const char *zone, int line)
make an empty pool
Definition: pool.c:45
pool_cleanup_t f
Definition: pool.h:70
pfree - a linked list node which stores an allocation chunk, plus a callback
Definition: pool.h:68
void pool_cleanup(pool_t p, pool_cleanup_t f, void *arg)
public cleanup utils, insert in a way that they are run FIFO, before mem frees
Definition: pool.c:251
int pool_size(pool_t p)
Definition: pool.c:219
static void _pool_heap_free(void *arg)
free a heap
Definition: pool.c:72
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
Definition: pool.c:183
char * pstrdupx(pool_t p, const char *src, int len)
use given size
Definition: pool.c:205
void pool_stat(int full)
Definition: pool.c:285
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
struct pool_struct * pool_t
struct pfree * cleanup
Definition: pool.h:83
int size
Definition: pool.h:82
struct pfree * cleanup_tail
Definition: pool.h:84
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
static struct pfree * _pool_free(pool_t p, pool_cleanup_t f, void *arg)
create a cleanup tracker
Definition: pool.c:99
struct pheap * heap
Definition: pool.h:85
struct pheap * heap
Definition: pool.h:72
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
struct pfree * next
Definition: pool.h:73
int used
Definition: pool.h:61
void(* pool_cleanup_t)(void *arg)
pool_cleanup_t - callback type which is associated with a pool entry; invoked when the pool entry is ...
Definition: pool.h:53
static void _pool_cleanup_append(pool_t p, struct pfree *pf)
mem should always be freed last
Definition: pool.c:81
pheap - singular allocation of memory
Definition: pool.h:58
char * pstrdup(pool_t p, const char *src)
XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is wit...
Definition: pool.c:191
pool_t _pool_new_heap(int size, const char *zone, int line)
Definition: pool.c:133
void * arg
Definition: pool.h:71
xht xhash_new(int prime)
Definition: xhash.c:96
void * pmalloc_x(pool_t p, int size, char c)
Definition: pool.c:174
pool - base node for a pool.
Definition: pool.h:80
static struct pheap * _pool_heap(pool_t p, int size)
create a heap and make sure it get&#39;s cleaned up
Definition: pool.c:113
#define _pool__malloc
Definition: pool.c:39