00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "dbus-mempool.h"
00025
#include "dbus-internals.h"
00026
00052 typedef struct DBusFreedElement DBusFreedElement;
00053
00059 struct DBusFreedElement
00060 {
00061 DBusFreedElement *
next;
00062 };
00063
00068 #define ELEMENT_PADDING 4
00069
00074 typedef struct DBusMemBlock DBusMemBlock;
00075
00080 struct DBusMemBlock
00081 {
00082 DBusMemBlock *
next;
00087
00088 long used_so_far;
00090 unsigned char elements[
ELEMENT_PADDING];
00091 };
00092
00096 struct DBusMemPool
00097 {
00098 int element_size;
00099 int block_size;
00100 unsigned int zero_elements : 1;
00102 DBusFreedElement *
free_elements;
00103 DBusMemBlock *
blocks;
00104 int allocated_elements;
00105 };
00106
00135
DBusMemPool*
00136 _dbus_mem_pool_new (
int element_size,
00137 dbus_bool_t zero_elements)
00138 {
00139
DBusMemPool *pool;
00140
00141 pool =
dbus_new0 (
DBusMemPool, 1);
00142
if (pool ==
NULL)
00143
return NULL;
00144
00145
00146
if (element_size < 8)
00147 element_size = 8;
00148
00149
00150
00151
00152
_dbus_assert (element_size >= (
int)
sizeof (
void*));
00153
_dbus_assert (element_size >= (
int)
sizeof (
DBusFreedElement));
00154
00155
00156
00157
00158 pool->
element_size = _DBUS_ALIGN_VALUE (element_size,
sizeof (
void *));
00159
00160 pool->
zero_elements = zero_elements !=
FALSE;
00161
00162 pool->
allocated_elements = 0;
00163
00164
00165
00166
00167
00168
00169 pool->
block_size = pool->
element_size * 8;
00170
00171
_dbus_assert ((pool->
block_size %
00172 pool->
element_size) == 0);
00173
00174
return pool;
00175 }
00176
00182
void
00183 _dbus_mem_pool_free (
DBusMemPool *pool)
00184 {
00185
DBusMemBlock *block;
00186
00187 block = pool->
blocks;
00188
while (block !=
NULL)
00189 {
00190
DBusMemBlock *next = block->
next;
00191
00192
dbus_free (block);
00193
00194 block = next;
00195 }
00196
00197
dbus_free (pool);
00198 }
00199
00207
void*
00208 _dbus_mem_pool_alloc (
DBusMemPool *pool)
00209 {
00210
#ifdef DBUS_BUILD_TESTS
00211
if (_dbus_disable_mem_pools ())
00212 {
00213
DBusMemBlock *block;
00214
int alloc_size;
00215
00216
00217
00218
00219
00220
00221
00222
00223 alloc_size =
sizeof (
DBusMemBlock) -
ELEMENT_PADDING +
00224 pool->
element_size;
00225
00226
if (pool->
zero_elements)
00227 block =
dbus_malloc0 (alloc_size);
00228
else
00229 block =
dbus_malloc (alloc_size);
00230
00231
if (block !=
NULL)
00232 {
00233 block->
next = pool->
blocks;
00234 pool->
blocks = block;
00235 pool->
allocated_elements += 1;
00236
00237
return (
void*) &block->
elements[0];
00238 }
00239
else
00240
return NULL;
00241 }
00242
else
00243
#endif
00244
{
00245
if (_dbus_decrement_fail_alloc_counter ())
00246 {
00247 _dbus_verbose (
" FAILING mempool alloc\n");
00248
return NULL;
00249 }
00250
else if (pool->
free_elements)
00251 {
00252
DBusFreedElement *element = pool->
free_elements;
00253
00254 pool->
free_elements = pool->
free_elements->
next;
00255
00256
if (pool->
zero_elements)
00257 memset (element,
'\0', pool->
element_size);
00258
00259 pool->
allocated_elements += 1;
00260
00261
return element;
00262 }
00263
else
00264 {
00265
void *element;
00266
00267
if (pool->
blocks ==
NULL ||
00268 pool->
blocks->
used_so_far == pool->
block_size)
00269 {
00270
00271
DBusMemBlock *block;
00272
int alloc_size;
00273
#ifdef DBUS_BUILD_TESTS
00274
int saved_counter;
00275
#endif
00276
00277
if (pool->
block_size <=
_DBUS_INT_MAX / 4)
00278 {
00279
00280 pool->
block_size *= 2;
00281
_dbus_assert ((pool->
block_size %
00282 pool->
element_size) == 0);
00283 }
00284
00285 alloc_size =
sizeof (
DBusMemBlock) -
ELEMENT_PADDING + pool->
block_size;
00286
00287
#ifdef DBUS_BUILD_TESTS
00288
00289
00290
00291
00292
00293
00294 saved_counter = _dbus_get_fail_alloc_counter ();
00295 _dbus_set_fail_alloc_counter (
_DBUS_INT_MAX);
00296
#endif
00297
00298
if (pool->
zero_elements)
00299 block =
dbus_malloc0 (alloc_size);
00300
else
00301 block =
dbus_malloc (alloc_size);
00302
00303
#ifdef DBUS_BUILD_TESTS
00304
_dbus_set_fail_alloc_counter (saved_counter);
00305
_dbus_assert (saved_counter == _dbus_get_fail_alloc_counter ());
00306
#endif
00307
00308
if (block ==
NULL)
00309
return NULL;
00310
00311 block->
used_so_far = 0;
00312 block->
next = pool->
blocks;
00313 pool->
blocks = block;
00314 }
00315
00316 element = &pool->
blocks->
elements[pool->
blocks->
used_so_far];
00317
00318 pool->
blocks->
used_so_far += pool->
element_size;
00319
00320 pool->
allocated_elements += 1;
00321
00322
return element;
00323 }
00324 }
00325 }
00326
00335
dbus_bool_t
00336 _dbus_mem_pool_dealloc (
DBusMemPool *pool,
00337
void *element)
00338 {
00339
#ifdef DBUS_BUILD_TESTS
00340
if (_dbus_disable_mem_pools ())
00341 {
00342
DBusMemBlock *block;
00343
DBusMemBlock *prev;
00344
00345
00346
00347 prev =
NULL;
00348 block = pool->
blocks;
00349
00350
while (block !=
NULL)
00351 {
00352
if (block->
elements == (
unsigned char*) element)
00353 {
00354
if (prev)
00355 prev->
next = block->
next;
00356
else
00357 pool->
blocks = block->
next;
00358
00359
dbus_free (block);
00360
00361
_dbus_assert (pool->
allocated_elements > 0);
00362 pool->
allocated_elements -= 1;
00363
00364
if (pool->
allocated_elements == 0)
00365
_dbus_assert (pool->
blocks ==
NULL);
00366
00367
return pool->
blocks ==
NULL;
00368 }
00369 prev = block;
00370 block = block->
next;
00371 }
00372
00373
_dbus_assert_not_reached (
"freed nonexistent block");
00374
return FALSE;
00375 }
00376
else
00377
#endif
00378
{
00379
DBusFreedElement *freed;
00380
00381 freed = element;
00382 freed->
next = pool->
free_elements;
00383 pool->
free_elements = freed;
00384
00385
_dbus_assert (pool->
allocated_elements > 0);
00386 pool->
allocated_elements -= 1;
00387
00388
return pool->
allocated_elements == 0;
00389 }
00390 }
00391
00394
#ifdef DBUS_BUILD_TESTS
00395
#include "dbus-test.h"
00396
#include <stdio.h>
00397
#include <time.h>
00398
00399
static void
00400 time_for_size (
int size)
00401 {
00402
int i;
00403
int j;
00404 clock_t start;
00405 clock_t end;
00406
#define FREE_ARRAY_SIZE 512
00407
#define N_ITERATIONS FREE_ARRAY_SIZE * 512
00408
void *to_free[FREE_ARRAY_SIZE];
00409
DBusMemPool *pool;
00410
00411 _dbus_verbose (
"Timings for size %d\n", size);
00412
00413 _dbus_verbose (
" malloc\n");
00414
00415 start = clock ();
00416
00417 i = 0;
00418 j = 0;
00419
while (i < N_ITERATIONS)
00420 {
00421 to_free[j] =
dbus_malloc (size);
00422
_dbus_assert (to_free[j] != NULL);
00423
00424 ++j;
00425
00426
if (j == FREE_ARRAY_SIZE)
00427 {
00428 j = 0;
00429
while (j < FREE_ARRAY_SIZE)
00430 {
00431
dbus_free (to_free[j]);
00432 ++j;
00433 }
00434
00435 j = 0;
00436 }
00437
00438 ++i;
00439 }
00440
00441 end = clock ();
00442
00443 _dbus_verbose (
" created/destroyed %d elements in %g seconds\n",
00444 N_ITERATIONS, (end - start) / (
double) CLOCKS_PER_SEC);
00445
00446
00447
00448 _dbus_verbose (
" mempools\n");
00449
00450 start = clock ();
00451
00452 pool =
_dbus_mem_pool_new (size, FALSE);
00453
00454 i = 0;
00455 j = 0;
00456
while (i < N_ITERATIONS)
00457 {
00458 to_free[j] =
_dbus_mem_pool_alloc (pool);
00459
_dbus_assert (to_free[j] != NULL);
00460
00461 ++j;
00462
00463
if (j == FREE_ARRAY_SIZE)
00464 {
00465 j = 0;
00466
while (j < FREE_ARRAY_SIZE)
00467 {
00468
_dbus_mem_pool_dealloc (pool, to_free[j]);
00469 ++j;
00470 }
00471
00472 j = 0;
00473 }
00474
00475 ++i;
00476 }
00477
00478
_dbus_mem_pool_free (pool);
00479
00480 end = clock ();
00481
00482 _dbus_verbose (
" created/destroyed %d elements in %g seconds\n",
00483 N_ITERATIONS, (end - start) / (
double) CLOCKS_PER_SEC);
00484
00485 _dbus_verbose (
" zeroed malloc\n");
00486
00487 start = clock ();
00488
00489 i = 0;
00490 j = 0;
00491
while (i < N_ITERATIONS)
00492 {
00493 to_free[j] =
dbus_malloc0 (size);
00494
_dbus_assert (to_free[j] != NULL);
00495
00496 ++j;
00497
00498
if (j == FREE_ARRAY_SIZE)
00499 {
00500 j = 0;
00501
while (j < FREE_ARRAY_SIZE)
00502 {
00503
dbus_free (to_free[j]);
00504 ++j;
00505 }
00506
00507 j = 0;
00508 }
00509
00510 ++i;
00511 }
00512
00513 end = clock ();
00514
00515 _dbus_verbose (
" created/destroyed %d elements in %g seconds\n",
00516 N_ITERATIONS, (end - start) / (
double) CLOCKS_PER_SEC);
00517
00518 _dbus_verbose (
" zeroed mempools\n");
00519
00520 start = clock ();
00521
00522 pool =
_dbus_mem_pool_new (size, TRUE);
00523
00524 i = 0;
00525 j = 0;
00526
while (i < N_ITERATIONS)
00527 {
00528 to_free[j] =
_dbus_mem_pool_alloc (pool);
00529
_dbus_assert (to_free[j] != NULL);
00530
00531 ++j;
00532
00533
if (j == FREE_ARRAY_SIZE)
00534 {
00535 j = 0;
00536
while (j < FREE_ARRAY_SIZE)
00537 {
00538
_dbus_mem_pool_dealloc (pool, to_free[j]);
00539 ++j;
00540 }
00541
00542 j = 0;
00543 }
00544
00545 ++i;
00546 }
00547
00548
_dbus_mem_pool_free (pool);
00549
00550 end = clock ();
00551
00552 _dbus_verbose (
" created/destroyed %d elements in %g seconds\n",
00553 N_ITERATIONS, (end - start) / (
double) CLOCKS_PER_SEC);
00554 }
00555
00561
dbus_bool_t
00562 _dbus_mem_pool_test (
void)
00563 {
00564
int i;
00565
int element_sizes[] = { 4, 8, 16, 50, 124 };
00566
00567 i = 0;
00568
while (i <
_DBUS_N_ELEMENTS (element_sizes))
00569 {
00570 time_for_size (element_sizes[i]);
00571 ++i;
00572 }
00573
00574
return TRUE;
00575 }
00576
00577
#endif