File: xpool.c

package info (click to toggle)
kamailio 4.2.0-2%2Bdeb8u3
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 56,276 kB
  • sloc: ansic: 552,836; xml: 166,484; sh: 8,659; makefile: 7,676; sql: 6,235; perl: 3,487; yacc: 3,428; python: 1,457; cpp: 1,219; php: 1,047; java: 449; pascal: 194; cs: 40; awk: 27
file content (252 lines) | stat: -rw-r--r-- 6,540 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
 * $Id$
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 *  Jabber
 *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
 *  
 *  2/27/00:3am, random plans by jer
 *  
 *  ok based on gprof, we really need some innovation here... my thoughs are this:
 *  
 *  most things are strings, so have a string-based true-blue garbage collector
 *  one big global hash containing all the strings created by any pstrdup, returning const char *
 *  a refcount on each string block
 *  when a pool is freed, it moves down the refcount
 *  garbage collector collects pools on the free stack, and runs through the hash for unused strings
 *  j_strcmp can check for == (if they are both from a pstrdup)
 *  
 *  let's see... this would change:
 *  pstrdup: do a hash lookup, success=return, fail=pmalloc & hash put
 *  pool_free: 
 *  
 */

/*! \file
 * \ingroup xmpp
 */


#include "xode.h"
//#include "config.h"

#define _xode_pool__malloc malloc
#define _xode_pool__free   free

/* xode_pfree - a linked list node which stores an
   allocation chunk, plus a callback */
struct xode_pool_free
{
    xode_pool_cleaner f;
    void *arg;
    struct xode_pool_heap *heap;
    struct xode_pool_free *next;
};

/* make an empty pool */
xode_pool _xode_pool_new(void)
{
    xode_pool p;
    while((p = _xode_pool__malloc(sizeof(_xode_pool))) == NULL) sleep(1);
    p->cleanup = NULL;
    p->heap = NULL;
    p->size = 0;

    return p;
}

/* free a heap */
void _xode_pool_heapfree(void *arg)
{
    struct xode_pool_heap *h = (struct xode_pool_heap *)arg;

    _xode_pool__free(h->block);
    _xode_pool__free(h);
}

/* mem should always be freed last */
void _xode_pool_cleanup_append(xode_pool p, struct xode_pool_free *pf)
{
    struct xode_pool_free *cur;

    if(p->cleanup == NULL)
    {
        p->cleanup = pf;
        return;
    }

    /* fast forward to end of list */
    for(cur = p->cleanup; cur->next != NULL; cur = cur->next);

    cur->next = pf;
}

/* create a cleanup tracker */
struct xode_pool_free *_xode_pool_free(xode_pool p, xode_pool_cleaner f, void *arg)
{
    struct xode_pool_free *ret;

    /* make the storage for the tracker */
    while((ret = _xode_pool__malloc(sizeof(struct xode_pool_free))) == NULL) sleep(1);
    ret->f = f;
    ret->arg = arg;
    ret->next = NULL;

    return ret;
}

/* create a heap and make sure it get's cleaned up */
struct xode_pool_heap *_xode_pool_heap(xode_pool p, int size)
{
    struct xode_pool_heap *ret;
    struct xode_pool_free *clean;

    /* make the return heap */
    while((ret = _xode_pool__malloc(sizeof(struct xode_pool_heap))) == NULL) sleep(1);
    while((ret->block = _xode_pool__malloc(size)) == NULL) sleep(1);
    ret->size = size;
    p->size += size;
    ret->used = 0;

    /* append to the cleanup list */
    clean = _xode_pool_free(p, _xode_pool_heapfree, (void *)ret);
    clean->heap = ret; /* for future use in finding used mem for pstrdup */
    _xode_pool_cleanup_append(p, clean);

    return ret;
}

xode_pool _xode_pool_newheap(int bytes)
{
    xode_pool p;
    p = _xode_pool_new();
    p->heap = _xode_pool_heap(p,bytes);
    return p;
}

void *xode_pool_malloc(xode_pool p, int size)
{
    void *block;

    if(p == NULL)
    {
        fprintf(stderr,"Memory Leak! xode_pmalloc received NULL pool, unable to track allocation, exiting]\n");
        abort();
    }

    /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */
    if(p->heap == NULL || size > (p->heap->size / 2))
    {
        while((block = _xode_pool__malloc(size)) == NULL) sleep(1);
        p->size += size;
        _xode_pool_cleanup_append(p, _xode_pool_free(p, _xode_pool__free, block));
        return block;
    }

    /* we have to preserve boundaries, long story :) */
    if(size >= 4)
        while(p->heap->used&7) p->heap->used++;

    /* if we don't fit in the old heap, replace it */
    if(size > (p->heap->size - p->heap->used))
        p->heap = _xode_pool_heap(p, p->heap->size);

    /* the current heap has room */
    block = (char *)p->heap->block + p->heap->used;
    p->heap->used += size;
    return block;
}

void *xode_pool_mallocx(xode_pool p, int size, char c)
{
   void* result = xode_pool_malloc(p, size);
   if (result != NULL)
           memset(result, c, size);
   return result;
}  

/* easy safety utility (for creating blank mem for structs, etc) */
void *xode_pool_malloco(xode_pool p, int size)
{
    void *block = xode_pool_malloc(p, size);
    memset(block, 0, size);
    return block;
}  

/* XXX efficient: move this to const char * and then loop through the existing heaps to see if src is within a block in this pool */
char *xode_pool_strdup(xode_pool p, const char *src)
{
    char *ret;

    if(src == NULL)
        return NULL;

    ret = xode_pool_malloc(p,strlen(src) + 1);
    strcpy(ret,src);

    return ret;
}

/* when move above, this one would actually return a new block */
char *xode_pool_strdupx(xode_pool p, const char *src)
{
    return xode_pool_strdup(p, src);
}

int xode_pool_size(xode_pool p)
{
    if(p == NULL) return 0;

    return p->size;
}

void xode_pool_free(xode_pool p)
{
    struct xode_pool_free *cur, *stub;

    if(p == NULL) return;

    cur = p->cleanup;
    while(cur != NULL)
    {
        (*cur->f)(cur->arg);
        stub = cur->next;
        _xode_pool__free(cur);
        cur = stub;
    }

    _xode_pool__free(p);
}

/* public cleanup utils, insert in a way that they are run FIFO, before mem frees */
void xode_pool_cleanup(xode_pool p, xode_pool_cleaner f, void *arg)
{
    struct xode_pool_free *clean;

    clean = _xode_pool_free(p, f, arg);
    clean->next = p->cleanup;
    p->cleanup = clean;
}

xode_pool xode_pool_new(void)
{
    return _xode_pool_new();
}

xode_pool xode_pool_heap(const int bytes)
{
    return _xode_pool_newheap(bytes);
}