blob: f6f294b775d2779d488b935c5bcdb2f97ac27f6e [file] [log] [blame]
Benny Prijono7d93d4e2006-09-17 19:54:23 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono7d93d4e2006-09-17 19:54:23 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/pool_buf.h>
20#include <pj/assert.h>
21#include <pj/os.h>
22
23struct pj_pool_factory stack_based_factory;
24
25struct creation_param
26{
27 void *stack_buf;
28 pj_size_t size;
29};
30
31static int is_initialized;
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000032static long tls = -1;
Benny Prijono7d93d4e2006-09-17 19:54:23 +000033static void* stack_alloc(pj_pool_factory *factory, pj_size_t size);
34
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000035static void pool_buf_cleanup(void)
Benny Prijono7d93d4e2006-09-17 19:54:23 +000036{
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000037 if (tls != -1) {
38 pj_thread_local_free(tls);
39 tls = -1;
40 }
Benny Prijonof762ee72006-12-01 11:14:37 +000041 if (is_initialized)
42 is_initialized = 0;
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000043}
44
45static pj_status_t pool_buf_initialize()
46{
47 pj_atexit(&pool_buf_cleanup);
48
Benny Prijono7d93d4e2006-09-17 19:54:23 +000049 stack_based_factory.policy.block_alloc = &stack_alloc;
50 return pj_thread_local_alloc(&tls);
51}
52
53static void* stack_alloc(pj_pool_factory *factory, pj_size_t size)
54{
55 struct creation_param *param;
Benny Prijono83217fa2007-02-16 21:44:36 +000056 void *buf;
Benny Prijono7d93d4e2006-09-17 19:54:23 +000057
58 PJ_UNUSED_ARG(factory);
59
60 param = pj_thread_local_get(tls);
Benny Prijono83217fa2007-02-16 21:44:36 +000061 if (param == NULL) {
62 /* Don't assert(), this is normal no-memory situation */
63 return NULL;
64 }
Benny Prijono7d93d4e2006-09-17 19:54:23 +000065
66 pj_thread_local_set(tls, NULL);
67
68 PJ_ASSERT_RETURN(size <= param->size, NULL);
69
Benny Prijono83217fa2007-02-16 21:44:36 +000070 buf = param->stack_buf;
71
72 /* Prevent the buffer from being reused */
73 param->stack_buf = NULL;
74
75 return buf;
Benny Prijono7d93d4e2006-09-17 19:54:23 +000076}
77
78
79PJ_DEF(pj_pool_t*) pj_pool_create_on_buf(const char *name,
80 void *buf,
81 pj_size_t size)
82{
83 struct creation_param param;
84
85 PJ_ASSERT_RETURN(buf && size, NULL);
86
87 if (!is_initialized) {
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000088 if (pool_buf_initialize() != PJ_SUCCESS)
Benny Prijono7d93d4e2006-09-17 19:54:23 +000089 return NULL;
Benny Prijono42e9e5f2006-10-13 17:30:46 +000090 is_initialized = 1;
Benny Prijono7d93d4e2006-09-17 19:54:23 +000091 }
92
93 param.stack_buf = buf;
94 param.size = size;
95 pj_thread_local_set(tls, &param);
96
Benny Prijonofa9e5b12006-10-08 12:39:34 +000097 return pj_pool_create_int(&stack_based_factory, name, size, 0,
98 pj_pool_factory_default_policy.callback);
Benny Prijono7d93d4e2006-09-17 19:54:23 +000099}
100