blob: c741e695a29035640a81db39a56fcb6a29286867 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <cc++/config.h>
40#include <cc++/export.h>
41#include <cc++/slog.h>
42#include <cc++/thread.h>
43#include <cc++/misc.h>
44#include <cstdlib>
45#include "private.h"
46
47#ifdef CCXX_NAMESPACES
48namespace ost {
49using std::endl;
50#endif
51
52const static size_t palign = __BYTE_ALIGNMENT;
53
54#if defined(HAVE_POSIX_MEMALIGN) && __BYTE_ALIGNMENT < 2
55#undef HAVE_POSIX_MEMALIGN
56#endif
57
58#ifdef HAVE_POSIX_MEMALIGN
59static volatile size_t malign = 0;
60#endif
61
62MemPager::MemPager(size_t pg)
63{
64 pagesize = ((pg + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
65 pages = 1;
66
67#ifdef COMMON_MEMORY_AUDIT
68 slog(Slog::levelDebug) << "MemPager: creating pool, id=" << this << endl;
69 slog(Slog::levelDebug) << "MemPager: alloc, id="
70 << this << " page=" << page << endl;
71#endif
72#if defined(HAVE_POSIX_MEMALIGN)
73 unsigned p2 = 2;
74 if(!malign) {
75 while(p2 < sizeof(void *))
76 p2 *= 2;
77 while(((p2 / sizeof(void *)) * sizeof(void *)) != p2)
78 p2 *= 2;
79 malign = p2;
80 }
81 posix_memalign((void **)&page, malign, pagesize);
82#else
83 page = (struct _page *)::new void *[pagesize / sizeof(void *)];
84#endif
85 page->next = NULL;
86 page->used = sizeof(struct _page);
87}
88
89MemPager::~MemPager()
90{
91 clean();
92}
93
94void MemPager::clean(void)
95{
96 struct _page *root = page;
97
98 while(root) {
99 page = page->next;
100#ifdef COMMON_MEMORY_AUDIT
101 slog(Slog::levelDebug) << "MemPager: delete, id="
102 << this << " page=" << root << endl;
103#endif
104#ifdef HAVE_POSIX_MEMALIGN
105 ::free(root);
106#else
107 delete[] root;
108#endif
109 root = page;
110 }
111#ifdef COMMON_MEMORY_AUDIT
112 slog(Slog::levelDebug) << "Mempager: destroy pool, id=" << this << endl;
113#endif
114}
115
116void MemPager::purge(void)
117{
118 struct _page *root = page;
119
120 while(root->next) {
121 page = root->next;
122#ifdef COMMON_MEMORY_AUDIT
123 slog(Slog::levelDebug) << "Mempager: delete, id="
124 << this << " page=" << root << endl;
125#endif
126#ifdef HAVE_POSIX_MEMALIGN
127 ::free(root);
128#else
129 delete[] root;
130#endif
131 --pages;
132 root = page;
133 }
134 page->used = sizeof(struct _page);
135}
136
137
138void *MemPager::alloc(size_t size)
139{
140 char *ptr;
141 struct _page *npage;
142
143#if __BYTE_ALIGNMENT > 1
144 size_t align = size % palign;
145 if (align)
146 size += palign - align;
147#endif
148
149 if(size > pagesize - sizeof(struct _page)) {
150 slog.critical("mempager overflow");
151#ifdef CCXX_EXCEPTIONS
152 if(Thread::getException() == Thread::throwObject)
153 throw this;
154#ifdef COMMON_STD_EXCEPTION
155 else if(Thread;:getException() == Thread::throwException)
156 Throw Exception("Mempager::alloc(): Memory Overflow");
157#endif
158#else
159 abort();
160#endif
161 }
162
163 if(page->used + size > pagesize) {
164#if defined(HAVE_POSIX_MEMALIGN)
165 posix_memalign((void **)&npage, malign, pagesize);
166#else
167 npage = (struct _page *) ::new void *[pagesize / sizeof(void *)];
168#endif
169
170#ifdef COMMON_MEMORY_AUDIT
171 slog(Slog::levelDebug) << "MemPager: alloc, id="
172 << this << " page=" << npage << endl;
173#endif
174 npage->next = page;
175 npage->used = sizeof(struct _page);
176 page = npage;
177 ++pages;
178 }
179 ptr = (char *)page;
180 ptr += page->used;
181 page->used += size;
182 return (void *)ptr;
183}
184
185void *MemPager::first(size_t size)
186{
187 struct _page *npage = page;
188 char *ptr;
189
190#if __BYTE_ALIGNMENT > 1
191 size_t align = size % palign;
192
193 if (align)
194 size += palign - align;
195#endif
196
197 while(npage) {
198 if(npage->used + size <= pagesize)
199 break;
200
201 npage = npage->next;
202 }
203 if(!npage)
204 return alloc(size);
205
206 ptr = (char *)npage;
207 ptr += npage->used;
208 npage->used += size;
209 return (void *)ptr;
210}
211
212char *MemPager::alloc(const char *str)
213{
214 size_t len = strlen(str) + 1;
215 char *cp = (char *)alloc(len);
216 return setString(cp, len, str);
217}
218
219char *MemPager::first(char *str)
220{
221 size_t len = strlen(str) + 1;
222 char *cp = (char *)first(len);
223 return setString(cp, len, str);
224}
225
226StackPager::StackPager(size_t pg) :
227MemPager(pg)
228{
229 stack = NULL;
230}
231
232void StackPager::purge(void)
233{
234 MemPager::purge();
235 stack = NULL;
236}
237
238void *StackPager::pull(void)
239{
240 frame_t *object = stack;
241
242 if(!stack) {
243 purge();
244 return NULL;
245 }
246
247 stack = object->next;
248 return object->data;
249}
250
251void *StackPager::push(const void* object, size_t len)
252{
253 frame_t *frame = (frame_t *)alloc(len + sizeof(frame_t) - 1);
254
255 if(!frame)
256 return NULL;
257
258 frame->next = stack;
259 stack = frame;
260 memcpy(frame->data, object, len);
261 return (void *)frame->data;
262}
263
264void *StackPager::push(const char *string)
265{
266 return push(string, strlen(string) + 1);
267}
268
269SharedMemPager::SharedMemPager(size_t pg, const char *name) :
270MemPager(pg), Mutex(name)
271{}
272
273void SharedMemPager::purge(void)
274{
275 enterMutex();
276 MemPager::purge();
277 leaveMutex();
278}
279
280void *SharedMemPager::first(size_t size)
281{
282 void *mem;
283
284 enterMutex();
285 mem = MemPager::first(size);
286 leaveMutex();
287 return mem;
288}
289
290void *SharedMemPager::alloc(size_t size)
291{
292 void *mem;
293
294 enterMutex();
295 mem = MemPager::alloc(size);
296 leaveMutex();
297 return mem;
298}
299
300#ifdef CCXX_NAMESPACES
301}
302#endif
303
304/** EMACS **
305 * Local variables:
306 * mode: c++
307 * c-basic-offset: 4
308 * End:
309 */