00001
00002
00003 #ifndef mapdb_i_h
00004 #define mapdb_i_h
00005
00006 #include "config.h"
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
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 #include <cassert>
00111 #include <cstring>
00112
00113 #include <auto_ptr.h>
00114
00115 #include "config.h"
00116 #include "globals.h"
00117 #include "helping_lock.h"
00118 #include "mapped_alloc.h"
00119 #include "kmem_slab.h"
00120 #include "std_macros.h"
00121
00122
00123
00124
00125 struct Mapping_tree
00126 {
00127
00128
00129 unsigned _count: 16;
00130 unsigned _size_id: 4;
00131 unsigned _empty_count: 11;
00132
00133
00134
00135 unsigned _unused: 1;
00136
00137 Mapping _mappings[0] __attribute__((packed));
00138
00139 public:
00140 inline void* operator new (size_t, unsigned size_factor);
00141
00142 inline void operator delete (void* block, size_t);
00143
00144
00145 Mapping_tree(unsigned size_factor, unsigned page_number);
00146
00147
00148 Mapping_tree(unsigned size_factor, Mapping_tree* from_tree);
00149
00150
00151 inline unsigned number_of_entries() const;
00152
00153 inline Mapping * mappings();
00154
00155 inline Mapping * end();
00156
00157 inline Mapping * last();
00158
00159
00160
00161
00162 static void copy_compact_tree(Mapping_tree *dst, Mapping_tree *src);
00163
00164 inline void check_integrity();
00165 };
00166
00167 enum Mapping_depth
00168 {
00169 Depth_root = 0, Depth_max = 252,
00170 Depth_subtree = 253, Depth_empty = 254, Depth_end = 255
00171 };
00172
00173
00174
00175
00176
00177
00178
00179 enum Mapping_tree_size
00180 {
00181 Size_factor = 4,
00182 Size_id_max = 8
00183 };
00184
00185 class mapping_tree_allocators
00186 {
00187 auto_ptr<Kmem_slab> _allocator [Size_id_max + 1];
00188
00189 friend class foo;
00190
00191 public:
00192 inline Kmem_slab * allocator_for_treesize(int size);
00193
00195 static inline mapping_tree_allocators& instance();
00196
00197 private:
00198 mapping_tree_allocators();
00199 };
00200
00201
00202
00203
00204
00206 class Physframe
00207 {
00208 friend class Mapdb;
00209 friend class Jdb_mapdb;
00210
00211
00212 auto_ptr<Mapping_tree> tree;
00213
00214 Helping_lock lock;
00215
00216
00217 Physframe ()
00218
00219
00220 {}
00221
00222 ~Physframe()
00223 {
00224 assert (! lock.test());
00225
00226 #if 0
00227 if (tree)
00228 {
00229
00230 for (Mapping* m = tree->mappings();
00231 m;
00232 m = m->next (tree->end()))
00233 {
00234 if (m->subtree())
00235 delete m->subtree();
00236 }
00237 }
00238 #endif
00239 }
00240
00241 void* operator new [] (size_t size)
00242 {
00243 size = (size + Config::PAGE_SIZE - 1) >> Config::PAGE_SHIFT;
00244 void* block = Mapped_allocator::allocator()->unaligned_alloc (size);
00245 if (block)
00246 memset(block, 0, size);
00247 return block;
00248 }
00249
00250 void operator delete [] (void* block, size_t size)
00251 {
00252 if (! block)
00253 return;
00254 size = (size + Config::PAGE_SIZE - 1) >> Config::PAGE_SHIFT;
00255 Mapped_allocator::allocator()->unaligned_free (size, block);
00256 }
00257 };
00258
00259
00260
00261
00262
00263
00264
00265
00266 inline Mapping::Mapping()
00267 {}
00268
00269
00274 inline bool
00275 Mapping::unused()
00276 {
00277 return data()->depth > Depth_subtree;
00278 }
00279
00280
00281
00282 inline bool
00283 Mapping::is_end_tag()
00284 {
00285 return data()->depth == Depth_end;
00286 }
00287
00288
00289
00290 inline Mapping *
00291 Mapping::next(const Mapping* end_of_tree)
00292 {
00293 for (Mapping* m = this + 1;
00294 m < end_of_tree && ! m->is_end_tag();
00295 m++)
00296 {
00297 if (! m->unused())
00298 return m;
00299 }
00300
00301 return 0;
00302 }
00303
00304
00305
00306 static inline Kmem_slab *
00307 allocator_for_treesize(int size)
00308 {
00309 return mapping_tree_allocators::instance().allocator_for_treesize(size);
00310 }
00311
00312
00313
00314 inline void*
00315 Mapping_tree::operator new (size_t, unsigned size_factor)
00316 {
00317 return allocator_for_treesize(size_factor)->alloc();
00318 }
00319
00320
00321
00322 inline void
00323 Mapping_tree::operator delete (void* block, size_t)
00324 {
00325 if (!block)
00326 return;
00327
00328
00329 Mapping_tree* t = static_cast<Mapping_tree*>(block);
00330
00331 t->check_integrity();
00332
00333 allocator_for_treesize(t->_size_id)->free(block);
00334 }
00335
00336
00337
00338
00339 inline unsigned
00340 Mapping_tree::number_of_entries() const
00341 {
00342 return Size_factor << _size_id;
00343 }
00344
00345
00346
00347 inline Mapping *
00348 Mapping_tree::mappings()
00349 {
00350 return & _mappings[0];
00351 }
00352
00353
00354
00355 inline Mapping *
00356 Mapping_tree::end()
00357 {
00358 return mappings() + number_of_entries();
00359 }
00360
00361
00362
00363 inline Mapping *
00364 Mapping_tree::last()
00365 {
00366 return end() - 1;
00367 }
00368
00369
00370
00371 inline void
00372 Mapping_tree::check_integrity()
00373 {
00374 #ifndef NDEBUG
00375
00376 assert (
00377 number_of_entries() == _count + _empty_count
00378
00379 || mappings()[_count + _empty_count].is_end_tag());
00380
00381 Mapping* m = mappings();
00382
00383 assert (! m->unused()
00384 && m->data()->space_is_sigma0()
00385 && m->data()->depth == 0);
00386
00387 unsigned
00388 used = 0,
00389 dead = 0;
00390
00391 while (m < end()
00392 && ! m->is_end_tag())
00393 {
00394 if (m->unused())
00395 dead++;
00396 else
00397 used++;
00398
00399 m++;
00400 }
00401
00402 assert (_count == used);
00403 assert (_empty_count == dead);
00404 #endif // ! NDEBUG
00405 }
00406
00407
00408
00409 inline Kmem_slab *
00410 mapping_tree_allocators::allocator_for_treesize(int size)
00411 {
00412 return _allocator[size].get();
00413 }
00414
00415
00418 inline mapping_tree_allocators&
00419 mapping_tree_allocators::instance()
00420 {
00421 static mapping_tree_allocators tree_allocators;
00422
00423 return tree_allocators;
00424 }
00425
00426 #endif // mapdb_i_h