~ubuntu-branches/ubuntu/utopic/sflphone/utopic-proposed

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib/src/pj/pool.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2013-06-30 11:40:56 UTC
  • mfrom: (4.1.18 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130630114056-0np50jkyqo6vnmii
Tags: 1.2.3-2
* changeset_r92d62cfc54732bbbcfff2b1d36c096b120b981a5.diff 
  - fixes automatic endian detection 
* Update Vcs: fixes vcs-field-not-canonical

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: pool.c 3553 2011-05-05 06:14:19Z nanang $ */
 
2
/*
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
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, MA  02111-1307  USA
 
19
 */
 
20
#include <pj/pool.h>
 
21
#include <pj/log.h>
 
22
#include <pj/except.h>
 
23
#include <pj/assert.h>
 
24
#include <pj/os.h>
 
25
 
 
26
#if !PJ_HAS_POOL_ALT_API
 
27
 
 
28
 
 
29
/* Include inline definitions when inlining is disabled. */
 
30
#if !PJ_FUNCTIONS_ARE_INLINED
 
31
#  include <pj/pool_i.h>
 
32
#endif
 
33
 
 
34
#define LOG(expr)                       PJ_LOG(6,expr)
 
35
#define ALIGN_PTR(PTR,ALIGNMENT)        (PTR + (-(long)(PTR) & (ALIGNMENT-1)))
 
36
 
 
37
PJ_DEF_DATA(int) PJ_NO_MEMORY_EXCEPTION;
 
38
 
 
39
PJ_DEF(int) pj_NO_MEMORY_EXCEPTION()
 
40
{
 
41
    return PJ_NO_MEMORY_EXCEPTION;
 
42
}
 
43
 
 
44
/*
 
45
 * Create new block.
 
46
 * Create a new big chunk of memory block, from which user allocation will be
 
47
 * taken from.
 
48
 */
 
49
static pj_pool_block *pj_pool_create_block( pj_pool_t *pool, pj_size_t size)
 
50
{
 
51
    pj_pool_block *block;
 
52
 
 
53
    PJ_CHECK_STACK();
 
54
    pj_assert(size >= sizeof(pj_pool_block));
 
55
 
 
56
    LOG((pool->obj_name, "create_block(sz=%u), cur.cap=%u, cur.used=%u",
 
57
         size, pool->capacity, pj_pool_get_used_size(pool)));
 
58
 
 
59
    /* Request memory from allocator. */
 
60
    block = (pj_pool_block*)
 
61
        (*pool->factory->policy.block_alloc)(pool->factory, size);
 
62
    if (block == NULL) {
 
63
        (*pool->callback)(pool, size);
 
64
        return NULL;
 
65
    }
 
66
 
 
67
    /* Add capacity. */
 
68
    pool->capacity += size;
 
69
 
 
70
    /* Set start and end of buffer. */
 
71
    block->buf = ((unsigned char*)block) + sizeof(pj_pool_block);
 
72
    block->end = ((unsigned char*)block) + size;
 
73
 
 
74
    /* Set the start pointer, aligning it as needed */
 
75
    block->cur = ALIGN_PTR(block->buf, PJ_POOL_ALIGNMENT);
 
76
 
 
77
    /* Insert in the front of the list. */
 
78
    pj_list_insert_after(&pool->block_list, block);
 
79
 
 
80
    LOG((pool->obj_name," block created, buffer=%p-%p",block->buf, block->end));
 
81
 
 
82
    return block;
 
83
}
 
84
 
 
85
/*
 
86
 * Allocate memory chunk for user from available blocks.
 
87
 * This will iterate through block list to find space to allocate the chunk.
 
88
 * If no space is available in all the blocks, a new block might be created
 
89
 * (depending on whether the pool is allowed to resize).
 
90
 */
 
91
PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size)
 
92
{
 
93
    pj_pool_block *block = pool->block_list.next;
 
94
    void *p;
 
95
    unsigned block_size;
 
96
 
 
97
    PJ_CHECK_STACK();
 
98
 
 
99
    while (block != &pool->block_list) {
 
100
        p = pj_pool_alloc_from_block(block, size);
 
101
        if (p != NULL)
 
102
            return p;
 
103
        block = block->next;
 
104
    }
 
105
    /* No available space in all blocks. */
 
106
 
 
107
    /* If pool is configured NOT to expand, return error. */
 
108
    if (pool->increment_size == 0) {
 
109
        LOG((pool->obj_name, "Can't expand pool to allocate %u bytes "
 
110
             "(used=%u, cap=%u)",
 
111
             size, pj_pool_get_used_size(pool), pool->capacity));
 
112
        (*pool->callback)(pool, size);
 
113
        return NULL;
 
114
    }
 
115
 
 
116
    /* If pool is configured to expand, but the increment size
 
117
     * is less than the required size, expand the pool by multiple
 
118
     * increment size. Also count the size wasted due to aligning
 
119
     * the block.
 
120
     */
 
121
    if (pool->increment_size <
 
122
            size + sizeof(pj_pool_block) + PJ_POOL_ALIGNMENT)
 
123
    {
 
124
        unsigned count;
 
125
        count = (size + pool->increment_size + sizeof(pj_pool_block) +
 
126
                 PJ_POOL_ALIGNMENT) /
 
127
                pool->increment_size;
 
128
        block_size = count * pool->increment_size;
 
129
 
 
130
    } else {
 
131
        block_size = pool->increment_size;
 
132
    }
 
133
 
 
134
    LOG((pool->obj_name,
 
135
         "%u bytes requested, resizing pool by %u bytes (used=%u, cap=%u)",
 
136
         size, block_size, pj_pool_get_used_size(pool), pool->capacity));
 
137
 
 
138
    block = pj_pool_create_block(pool, block_size);
 
139
    if (!block)
 
140
        return NULL;
 
141
 
 
142
    p = pj_pool_alloc_from_block(block, size);
 
143
    pj_assert(p != NULL);
 
144
#if PJ_DEBUG
 
145
    if (p == NULL) {
 
146
        p = p;
 
147
    }
 
148
#endif
 
149
    return p;
 
150
}
 
151
 
 
152
/*
 
153
 * Internal function to initialize pool.
 
154
 */
 
155
PJ_DEF(void) pj_pool_init_int(  pj_pool_t *pool,
 
156
                                const char *name,
 
157
                                pj_size_t increment_size,
 
158
                                pj_pool_callback *callback)
 
159
{
 
160
    PJ_CHECK_STACK();
 
161
 
 
162
    pool->increment_size = increment_size;
 
163
    pool->callback = callback;
 
164
 
 
165
    if (name) {
 
166
        if (strchr(name, '%') != NULL) {
 
167
            pj_ansi_snprintf(pool->obj_name, sizeof(pool->obj_name),
 
168
                             name, pool);
 
169
        } else {
 
170
            pj_ansi_strncpy(pool->obj_name, name, PJ_MAX_OBJ_NAME);
 
171
            pool->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
 
172
        }
 
173
    } else {
 
174
        pool->obj_name[0] = '\0';
 
175
    }
 
176
}
 
177
 
 
178
/*
 
179
 * Create new memory pool.
 
180
 */
 
181
PJ_DEF(pj_pool_t*) pj_pool_create_int( pj_pool_factory *f, const char *name,
 
182
                                       pj_size_t initial_size,
 
183
                                       pj_size_t increment_size,
 
184
                                       pj_pool_callback *callback)
 
185
{
 
186
    pj_pool_t *pool;
 
187
    pj_pool_block *block;
 
188
    pj_uint8_t *buffer;
 
189
 
 
190
    PJ_CHECK_STACK();
 
191
 
 
192
    /* Size must be at least sizeof(pj_pool)+sizeof(pj_pool_block) */
 
193
    PJ_ASSERT_RETURN(initial_size >= sizeof(pj_pool_t)+sizeof(pj_pool_block),
 
194
                     NULL);
 
195
 
 
196
    /* If callback is NULL, set calback from the policy */
 
197
    if (callback == NULL)
 
198
        callback = f->policy.callback;
 
199
 
 
200
    /* Allocate initial block */
 
201
    buffer = (pj_uint8_t*) (*f->policy.block_alloc)(f, initial_size);
 
202
    if (!buffer)
 
203
        return NULL;
 
204
 
 
205
    /* Set pool administrative data. */
 
206
    pool = (pj_pool_t*)buffer;
 
207
    pj_bzero(pool, sizeof(*pool));
 
208
 
 
209
    pj_list_init(&pool->block_list);
 
210
    pool->factory = f;
 
211
 
 
212
    /* Create the first block from the memory. */
 
213
    block = (pj_pool_block*) (buffer + sizeof(*pool));
 
214
    block->buf = ((unsigned char*)block) + sizeof(pj_pool_block);
 
215
    block->end = buffer + initial_size;
 
216
 
 
217
    /* Set the start pointer, aligning it as needed */
 
218
    block->cur = ALIGN_PTR(block->buf, PJ_POOL_ALIGNMENT);
 
219
 
 
220
    pj_list_insert_after(&pool->block_list, block);
 
221
 
 
222
    pj_pool_init_int(pool, name, increment_size, callback);
 
223
 
 
224
    /* Pool initial capacity and used size */
 
225
    pool->capacity = initial_size;
 
226
 
 
227
    LOG((pool->obj_name, "pool created, size=%u", pool->capacity));
 
228
    return pool;
 
229
}
 
230
 
 
231
/*
 
232
 * Reset the pool to the state when it was created.
 
233
 * All blocks will be deallocated except the first block. All memory areas
 
234
 * are marked as free.
 
235
 */
 
236
static void reset_pool(pj_pool_t *pool)
 
237
{
 
238
    pj_pool_block *block;
 
239
 
 
240
    PJ_CHECK_STACK();
 
241
 
 
242
    block = pool->block_list.prev;
 
243
    if (block == &pool->block_list)
 
244
        return;
 
245
 
 
246
    /* Skip the first block because it is occupying the same memory
 
247
       as the pool itself.
 
248
    */
 
249
    block = block->prev;
 
250
 
 
251
    while (block != &pool->block_list) {
 
252
        pj_pool_block *prev = block->prev;
 
253
        pj_list_erase(block);
 
254
        (*pool->factory->policy.block_free)(pool->factory, block,
 
255
                                            block->end - (unsigned char*)block);
 
256
        block = prev;
 
257
    }
 
258
 
 
259
    block = pool->block_list.next;
 
260
 
 
261
    /* Set the start pointer, aligning it as needed */
 
262
    block->cur = ALIGN_PTR(block->buf, PJ_POOL_ALIGNMENT);
 
263
 
 
264
    pool->capacity = block->end - (unsigned char*)pool;
 
265
}
 
266
 
 
267
/*
 
268
 * The public function to reset pool.
 
269
 */
 
270
PJ_DEF(void) pj_pool_reset(pj_pool_t *pool)
 
271
{
 
272
    LOG((pool->obj_name, "reset(): cap=%d, used=%d(%d%%)",
 
273
        pool->capacity, pj_pool_get_used_size(pool),
 
274
        pj_pool_get_used_size(pool)*100/pool->capacity));
 
275
 
 
276
    reset_pool(pool);
 
277
}
 
278
 
 
279
/*
 
280
 * Destroy the pool.
 
281
 */
 
282
PJ_DEF(void) pj_pool_destroy_int(pj_pool_t *pool)
 
283
{
 
284
    pj_size_t initial_size;
 
285
 
 
286
    LOG((pool->obj_name, "destroy(): cap=%d, used=%d(%d%%), block0=%p-%p",
 
287
        pool->capacity, pj_pool_get_used_size(pool),
 
288
        pj_pool_get_used_size(pool)*100/pool->capacity,
 
289
        ((pj_pool_block*)pool->block_list.next)->buf,
 
290
        ((pj_pool_block*)pool->block_list.next)->end));
 
291
 
 
292
    reset_pool(pool);
 
293
    initial_size = ((pj_pool_block*)pool->block_list.next)->end -
 
294
                   (unsigned char*)pool;
 
295
    if (pool->factory->policy.block_free)
 
296
        (*pool->factory->policy.block_free)(pool->factory, pool, initial_size);
 
297
}
 
298
 
 
299
 
 
300
#endif  /* PJ_HAS_POOL_ALT_API */