~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: pool.c 4298 2012-11-22 05:00:01Z 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, pj_size_t 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
 
        pj_size_t 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 */
301