VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/mempool-generic.cpp@ 20371

Last change on this file since 20371 was 20360, checked in by vboxsync, 16 years ago

IPRT: Memory pool (untested) and string pool stub implementation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/* $Id: mempool-generic.cpp 20360 2009-06-08 00:04:31Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocation Pool.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/mempool.h>
35
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/err.h>
39#include <iprt/mem.h>
40#include <iprt/spinlock.h>
41#include <iprt/string.h>
42
43#include "internal/magics.h"
44
45
46/*******************************************************************************
47* Structures and Typedefs *
48*******************************************************************************/
49/** Pointer to a memory pool instance. */
50typedef struct RTMEMPOOLINT *PRTMEMPOOLINT;
51/** Pointer to a memory pool entry. */
52typedef struct RTMEMPOOLENTRY *PRTMEMPOOLENTRY;
53
54/**
55 * Memory pool entry.
56 */
57typedef struct RTMEMPOOLENTRY
58{
59 /** Pointer to the pool */
60 PRTMEMPOOLINT pMemPool;
61 /** Pointer to the next entry. */
62 PRTMEMPOOLENTRY volatile pNext;
63 /** Pointer to the previous entry. */
64 PRTMEMPOOLENTRY volatile pPrev;
65 /** The number of references to the pool entry. */
66 uint32_t volatile cRefs;
67} RTMEMPOOLENTRY;
68
69
70/**
71 * Memory pool instance data.
72 */
73typedef struct RTMEMPOOLINT
74{
75 /** Magic number (RTMEMPOOL_MAGIC). */
76 uint32_t u32Magic;
77 /** Spinlock protecting the pool entry list updates. */
78 RTSPINLOCK hSpinLock;
79 /** Head entry pointer. */
80 PRTMEMPOOLENTRY volatile pHead;
81 /** The number of entries in the pool (for statistical purposes). */
82 uint32_t volatile cEntries;
83 /** User data assoicated with the pool. */
84 void *pvUser;
85 /** The pool name. (variable length) */
86 char szName[8];
87} RTMEMPOOLINT;
88
89
90/*******************************************************************************
91* Defined Constants And Macros *
92*******************************************************************************/
93/** Validates a memory pool handle, translating RTMEMPOOL_DEFAULT when found,
94 * and returns rc if not valid. */
95#define RTMEMPOOL_VALID_RETURN_RC(pMemPool, rc) \
96 do { \
97 if (pMemPool == RTMEMPOOL_DEFAULT) \
98 pMemPool = &g_rtMemPoolDefault; \
99 else \
100 { \
101 AssertPtrReturn((pMemPool), (rc)); \
102 AssertReturn((pMemPool)->u32Magic == RTMEMPOOL_MAGIC, (rc)); \
103 } \
104 } while (0)
105
106/** Validates a memory pool entry and returns rc if not valid. */
107#define RTMEMPOOL_VALID_ENTRY_RETURN_RC(pEntry, rc) \
108 do { \
109 AssertPtrReturn(pEntry, (rc)); \
110 AssertPtrNullReturn((pEntry)->pMemPool, (rc)); \
111 AssertReturn((pEntry)->pMemPool->u32Magic == RTMEMPOOL_MAGIC, (rc)); \
112 AssertPtrNull((pEntry)->pNext); \
113 AssertPtrNull((pEntry)->pPrev); \
114 } while (0)
115
116
117/*******************************************************************************
118* Global Variables *
119*******************************************************************************/
120/** The */
121static RTMEMPOOLINT g_rtMemPoolDefault =
122{
123 /* .u32Magic = */ RTMEMPOOL_MAGIC,
124 /* .hSpinLock = */ NIL_RTSPINLOCK,
125 /* .pHead = */ NULL,
126 /* .cEntries = */ 0,
127 /* .pvUser = */ NULL,
128 /* .szName = */ "default"
129};
130
131
132
133RTDECL(int) RTMemPoolCreate(PRTMEMPOOL phMemPool, const char *pszName)
134{
135 AssertPtr(phMemPool);
136 AssertPtr(pszName);
137 Assert(*pszName);
138
139 size_t cchName = strlen(pszName);
140 PRTMEMPOOLINT pMemPool = (PRTMEMPOOLINT)RTMemAlloc(RT_OFFSETOF(RTMEMPOOLINT, szName[cchName + 1]));
141 if (!pMemPool)
142 return VERR_NO_MEMORY;
143 int rc = RTSpinlockCreate(&pMemPool->hSpinLock);
144 if (RT_SUCCESS(rc))
145 {
146 pMemPool->u32Magic = RTMEMPOOL_MAGIC;
147 pMemPool->pHead = NULL;
148 pMemPool->cEntries = 0;
149 pMemPool->pvUser = NULL;
150 memcpy(pMemPool->szName, pszName, cchName);
151 *phMemPool = pMemPool;
152 return VINF_SUCCESS;
153 }
154 RTMemFree(pMemPool);
155 return rc;
156}
157
158
159RTDECL(int) RTMemPoolDestroy(RTMEMPOOL hMemPool)
160{
161
162 return VERR_NOT_IMPLEMENTED;
163}
164
165
166
167DECLINLINE(void) rtMemPoolInitAndLink(PRTMEMPOOLINT pMemPool, PRTMEMPOOLENTRY pEntry)
168{
169 pEntry->pMemPool = pMemPool;
170 pEntry->pNext = NULL;
171 pEntry->pPrev = NULL;
172 pEntry->cRefs = 1;
173
174 if (pMemPool->hSpinLock != NIL_RTSPINLOCK)
175 {
176 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
177 RTSpinlockAcquire(pMemPool->hSpinLock, &Tmp);
178
179 PRTMEMPOOLENTRY pHead = pMemPool->pHead;
180 pEntry->pNext = pHead;
181 if (pHead)
182 pHead->pPrev = pEntry;
183 else
184 pMemPool->pHead = pEntry;
185
186 RTSpinlockRelease(pMemPool->hSpinLock, &Tmp);
187 }
188
189 ASMAtomicIncU32(&pMemPool->cEntries);
190}
191
192
193DECLINLINE(void) rtMemPoolUnlink(PRTMEMPOOLENTRY pEntry)
194{
195 PRTMEMPOOLINT pMemPool = pEntry->pMemPool;
196 if (pMemPool->hSpinLock != NIL_RTSPINLOCK)
197 {
198 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
199 RTSpinlockAcquire(pMemPool->hSpinLock, &Tmp);
200
201 if (pEntry->pNext)
202 pEntry->pNext->pPrev = pEntry->pPrev;
203 if (pEntry->pPrev)
204 pEntry->pPrev->pNext = pEntry->pNext;
205 else
206 pMemPool->pHead = pEntry->pNext;
207 pEntry->pMemPool = NULL;
208
209 RTSpinlockRelease(pMemPool->hSpinLock, &Tmp);
210 }
211 else
212 pEntry->pMemPool = NULL;
213
214 ASMAtomicDecU32(&pMemPool->cEntries);
215}
216
217
218RTDECL(void *) RTMemPoolAlloc(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW
219{
220 PRTMEMPOOLINT pMemPool = hMemPool;
221 RTMEMPOOL_VALID_RETURN_RC(pMemPool, NULL);
222
223 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)RTMemAlloc(cb + sizeof(*pEntry));
224 if (!pEntry)
225 return NULL;
226 rtMemPoolInitAndLink(pMemPool, pEntry);
227
228 return pEntry + 1;
229}
230
231
232RTDECL(void *) RTMemPoolAllocZ(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW
233{
234 PRTMEMPOOLINT pMemPool = hMemPool;
235 RTMEMPOOL_VALID_RETURN_RC(pMemPool, NULL);
236
237 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)RTMemAllocZ(cb + sizeof(*pEntry));
238 if (!pEntry)
239 return NULL;
240 rtMemPoolInitAndLink(pMemPool, pEntry);
241
242 return pEntry + 1;
243}
244
245
246RTDECL(void *) RTMemPoolDup(RTMEMPOOL hMemPool, const void *pvSrc, size_t cb) RT_NO_THROW
247{
248 PRTMEMPOOLINT pMemPool = hMemPool;
249 RTMEMPOOL_VALID_RETURN_RC(pMemPool, NULL);
250
251 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)RTMemAlloc(cb + sizeof(*pEntry));
252 if (!pEntry)
253 return NULL;
254 memcpy(pEntry + 1, pvSrc, cb);
255 rtMemPoolInitAndLink(pMemPool, pEntry);
256
257 return pEntry + 1;
258}
259
260
261RTDECL(void *) RTMemPoolDupEx(RTMEMPOOL hMemPool, const void *pvSrc, size_t cbSrc, size_t cbExtra) RT_NO_THROW
262{
263 PRTMEMPOOLINT pMemPool = hMemPool;
264 RTMEMPOOL_VALID_RETURN_RC(pMemPool, NULL);
265
266 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)RTMemAlloc(cbSrc + cbExtra + sizeof(*pEntry));
267 if (!pEntry)
268 return NULL;
269 memcpy(pEntry + 1, pvSrc, cbSrc);
270 memset((uint8_t *)(pEntry + 1) + cbSrc, '\0', cbExtra);
271 rtMemPoolInitAndLink(pMemPool, pEntry);
272
273 return pEntry + 1;
274}
275
276
277
278RTDECL(void *) RTMemPoolRealloc(RTMEMPOOL hMemPool, void *pvOld, size_t cbNew) RT_NO_THROW
279{
280 /*
281 * Fend off the odd cases.
282 */
283 if (!cbNew)
284 {
285 RTMemPoolRelease(hMemPool, pvOld);
286 return NULL;
287 }
288
289 if (!pvOld)
290 return RTMemPoolAlloc(hMemPool, cbNew);
291
292 /*
293 * Real realloc.
294 */
295 PRTMEMPOOLINT pNewMemPool = hMemPool;
296 RTMEMPOOL_VALID_RETURN_RC(pNewMemPool, NULL);
297
298 PRTMEMPOOLENTRY pOldEntry = (PRTMEMPOOLENTRY)pvOld - 1;
299 RTMEMPOOL_VALID_ENTRY_RETURN_RC(pOldEntry, NULL);
300 PRTMEMPOOLINT pOldMemPool = pOldEntry->pMemPool;
301 AssertReturn(pOldEntry->cRefs == 1, NULL);
302
303 /*
304 * Unlink it from the current pool and try reallocate it.
305 */
306 rtMemPoolUnlink(pOldEntry);
307
308 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)RTMemRealloc(pOldEntry, cbNew + sizeof(*pEntry));
309 if (!pEntry)
310 {
311 rtMemPoolInitAndLink(pOldMemPool, pOldEntry);
312 return NULL;
313 }
314 rtMemPoolInitAndLink(pNewMemPool, pEntry);
315
316 return pEntry + 1;
317}
318
319
320RTDECL(void) RTMemPoolFree(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW
321{
322 RTMemPoolRelease(hMemPool, pv);
323}
324
325
326RTDECL(uint32_t) RTMemPoolRetain(void *pv) RT_NO_THROW
327{
328 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)pv - 1;
329 RTMEMPOOL_VALID_ENTRY_RETURN_RC(pEntry, UINT32_MAX);
330
331 uint32_t cRefs = ASMAtomicIncU32(&pEntry->cRefs);
332 Assert(cRefs < UINT32_MAX / 2);
333
334 return cRefs;
335}
336
337
338RTDECL(uint32_t) RTMemPoolRelease(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW
339{
340 if (!pv)
341 return 0;
342
343 PRTMEMPOOLENTRY pEntry = (PRTMEMPOOLENTRY)pv - 1;
344 RTMEMPOOL_VALID_ENTRY_RETURN_RC(pEntry, UINT32_MAX);
345 Assert( hMemPool == NIL_RTMEMPOOL
346 || hMemPool == pEntry->pMemPool
347 || (hMemPool == RTMEMPOOL_DEFAULT && pEntry->pMemPool == &g_rtMemPoolDefault));
348 AssertReturn(pEntry->cRefs > 0, UINT32_MAX);
349
350 uint32_t cRefs = ASMAtomicDecU32(&pEntry->cRefs);
351 Assert(cRefs < UINT32_MAX / 2);
352 if (!cRefs)
353 {
354 rtMemPoolUnlink(pEntry);
355 RTMemFree(pEntry);
356 }
357
358 return cRefs;
359}
360
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette