00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 static const char* dont_use_envstring = "SYSTEMC_MEMPOOL_DONT_USE";
00061 static bool use_default_new = false;
00062
00063
00064 #include <stdio.h>
00065 #include <cstdlib>
00066 #include "sysc/utils/sc_mempool.h"
00067
00068 namespace sc_core {
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 class sc_allocator {
00084 friend class sc_mempool;
00085
00086 public:
00087 sc_allocator( int blksz, int cellsz );
00088 ~sc_allocator();
00089 void* allocate();
00090 void release(void* p);
00091
00092 void display_statistics();
00093
00094 private:
00095 union link {
00096 link* next;
00097 double align;
00098 };
00099
00100 int block_size;
00101
00102 int cell_size;
00103
00104 char* block_list;
00105 link* free_list;
00106 char* next_avail;
00107
00108 int total_alloc;
00109 int total_freed;
00110 int free_list_alloc;
00111 };
00112
00113 sc_allocator::sc_allocator( int blksz, int cellsz )
00114 {
00115 cell_size = cellsz;
00116 block_size = sizeof(link) + (((blksz - 1) / cellsz) + 1) * cellsz;
00117 block_list = 0;
00118 free_list = 0;
00119 next_avail = 0;
00120
00121 total_alloc = 0;
00122 total_freed = 0;
00123 free_list_alloc = 0;
00124 }
00125
00126 sc_allocator::~sc_allocator()
00127 {
00128
00129
00130
00131 }
00132
00133 void*
00134 sc_allocator::allocate()
00135 {
00136 void* result = 0;
00137 total_alloc++;
00138 if (free_list != 0) {
00139 free_list_alloc++;
00140 result = free_list;
00141 free_list = free_list->next;
00142 return result;
00143 }
00144 else if (next_avail != 0) {
00145 result = next_avail;
00146 next_avail += cell_size;
00147
00148 if (next_avail >= block_list + block_size)
00149 next_avail = 0;
00150 return result;
00151 }
00152 else {
00153 link* new_block = (link*) malloc(block_size);
00154 new_block->next = (link*) block_list;
00155 block_list = (char*) new_block;
00156 result = (block_list + sizeof(link));
00157
00158
00159 next_avail = ((char*) result) + cell_size;
00160 return result;
00161 }
00162 }
00163
00164 void
00165 sc_allocator::release(void* p)
00166 {
00167 total_freed++;
00168 ((link*) p)->next = free_list;
00169 free_list = (link*) p;
00170 }
00171
00172 void
00173 sc_allocator::display_statistics()
00174 {
00175 int nblocks = 0;
00176 for (link* b = (link*) block_list; b != 0; b = b->next)
00177 nblocks++;
00178 printf("size %3d: %2d block(s), %3d requests (%3d from free list), %3d freed.\n",
00179 cell_size, nblocks, total_alloc, free_list_alloc, total_freed);
00180 }
00181
00182
00183 static const int cell_sizes[] = {
00184 0,
00185 8,
00186 16,
00187 24,
00188 32,
00189 48,
00190 64,
00191 80,
00192 96,
00193 128
00194 };
00195
00196 static const int cell_size_to_allocator[] = {
00197 0,
00198 1,
00199 2,
00200 3,
00201 4,
00202 5,
00203 5,
00204 6,
00205 6,
00206 7,
00207 7,
00208 8,
00209 8,
00210 9,
00211 9,
00212 9,
00213 9
00214 };
00215
00216
00217 class sc_mempool_int {
00218 friend class sc_mempool;
00219
00220 public:
00221 sc_mempool_int(int blksz, int npools, int incr);
00222 ~sc_mempool_int();
00223 void* do_allocate(std::size_t);
00224 void do_release(void*, std::size_t);
00225
00226 void display_statistics();
00227
00228 private:
00229 sc_allocator** allocators;
00230 int num_pools;
00231 int increment;
00232 int max_size;
00233 };
00234
00235
00236 static bool
00237 compute_use_default_new()
00238 {
00239 const char* e = getenv(dont_use_envstring);
00240 return (e != 0) && (atoi(e) != 0);
00241 }
00242
00243 sc_mempool_int::sc_mempool_int(int blksz, int npools, int incr)
00244 {
00245 use_default_new = compute_use_default_new();
00246 if (! use_default_new) {
00247 num_pools = npools;
00248 increment = incr;
00249 max_size = cell_sizes[sizeof(cell_sizes)/sizeof(cell_sizes[0]) - 1];
00250 allocators = new sc_allocator*[npools + 1];
00251 for (int i = 1; i <= npools; ++i)
00252 allocators[i] = new sc_allocator(blksz, cell_sizes[i]);
00253 allocators[0] = allocators[1];
00254 }
00255 }
00256
00257 sc_mempool_int::~sc_mempool_int()
00258 {
00259 for (int i = 1; i <= num_pools; ++i)
00260 delete allocators[i];
00261 delete[] allocators;
00262 }
00263
00264 static sc_mempool_int* the_mempool = 0;
00265
00266 void*
00267 sc_mempool_int::do_allocate(std::size_t sz)
00268 {
00269 int which_allocator = cell_size_to_allocator[(sz - 1) / increment + 1];
00270 void* p = allocators[which_allocator]->allocate();
00271 return p;
00272 }
00273
00274 void
00275 sc_mempool_int::do_release(void* p, std::size_t sz)
00276 {
00277 int which_allocator = cell_size_to_allocator[(sz - 1) / increment + 1];
00278 allocators[which_allocator]->release(p);
00279 }
00280
00281 void
00282 sc_mempool_int::display_statistics()
00283 {
00284 printf("*** Memory Pool Statistics ***\n");
00285 for (int i = 1; i <= num_pools; ++i)
00286 allocators[i]->display_statistics();
00287 }
00288
00289
00290
00291 void*
00292 sc_mempool::allocate(std::size_t sz)
00293 {
00294 if (use_default_new)
00295 return ::operator new(sz);
00296
00297 if (the_mempool == 0) {
00298 use_default_new = compute_use_default_new();
00299 if (use_default_new)
00300 return ::operator new(sz);
00301
00302
00303
00304 the_mempool = new sc_mempool_int( 1984, sizeof(cell_sizes)/sizeof(cell_sizes[0]) - 1, 8 );
00305 }
00306
00307 if (sz > (unsigned) the_mempool->max_size)
00308 return ::operator new(sz);
00309
00310 return the_mempool->do_allocate(sz);
00311 }
00312
00313 void
00314 sc_mempool::release(void* p, std::size_t sz)
00315 {
00316 if (p) {
00317
00318 if (use_default_new || sz > (unsigned) the_mempool->max_size) {
00319 ::operator delete(p);
00320 return;
00321 }
00322
00323 the_mempool->do_release(p, sz);
00324 }
00325 }
00326
00327 void
00328 sc_mempool::display_statistics()
00329 {
00330 if (the_mempool && !use_default_new) {
00331 the_mempool->display_statistics();
00332 } else {
00333 printf("SystemC info: no memory allocation was done through the memory pool.\n");
00334 }
00335 }
00336
00337 }