]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/dbg_page_info.cpp
update
[l4.git] / kernel / fiasco / src / kern / dbg_page_info.cpp
1 INTERFACE [debug]:
2
3 #include "types.h"
4 #include "lock_guard.h"
5 #include "spin_lock.h"
6 #include "slab_cache.h"
7 #include <cxx/slist>
8
9 class Dbg_page_info_table;
10
11 class Dbg_page_info : public cxx::S_list_item
12 {
13   friend class Dbg_page_info_table;
14
15 private:
16   Page_number const _pfn;
17   typedef unsigned long Buf[5];
18   Buf _buf;
19
20   char *b() { return reinterpret_cast<char*>(_buf); }
21   char const *b() const { return reinterpret_cast<char const*>(_buf); }
22
23   typedef Slab_cache Allocator;
24
25 public:
26   void *operator new (size_t) throw() { return alloc()->alloc(); }
27   void operator delete (void *p, size_t) { alloc()->free(p); }
28
29   enum { Buffer_size = sizeof(Buf) };
30
31   Dbg_page_info(Page_number pfn) : _pfn(pfn) {}
32
33   bool match(Page_number p) { return _pfn == p; }
34
35   template<typename T>
36   T *info()
37   { return reinterpret_cast<T*>(b()); }
38
39   template<typename T>
40   T const *info() const
41   { return reinterpret_cast<T const*>(b()); }
42 };
43
44 class Dbg_page_info_table
45 {
46 private:
47   typedef cxx::S_list_bss<Dbg_page_info> List;
48
49 public:
50   struct Entry
51   {
52     List h;
53     Spin_lock<> l;
54   };
55   enum { Hash_tab_size = 1024 };
56
57 private:
58   Entry _tab[Hash_tab_size];
59   static unsigned hash(Page_number p)
60   { return cxx::int_value<Page_number>(p) % Hash_tab_size; }
61 };
62
63
64
65 IMPLEMENTATION [debug]:
66
67 #include "kmem_slab.h"
68
69
70 static Dbg_page_info_table _t;
71
72 PUBLIC static
73 Dbg_page_info_table &
74 Dbg_page_info::table()
75 {
76   return _t;
77 }
78
79 static Kmem_slab_t<Dbg_page_info> _dbg_page_info_allocator("Dbg_page_info");
80
81 PRIVATE static
82 Dbg_page_info::Allocator *
83 Dbg_page_info::alloc()
84 { return &_dbg_page_info_allocator; }
85
86
87 PUBLIC template<typename B, typename E> static inline
88 B
89 Dbg_page_info_table::find(B const &b, E const &e, Page_number p)
90 {
91   for (B i = b; i != e; ++i)
92     if (i->match(p))
93       return i;
94   return e;
95 }
96
97 PUBLIC
98 Dbg_page_info *
99 Dbg_page_info_table::operator [] (Page_number pfn) const
100 {
101   Entry &e = const_cast<Dbg_page_info_table*>(this)->_tab[hash(pfn)];
102   auto g = lock_guard(e.l);
103   // we know that *end() is NULL
104   return *find(e.h.begin(), e.h.end(), pfn);
105 }
106
107 PUBLIC
108 void
109 Dbg_page_info_table::insert(Dbg_page_info *i)
110 {
111   Entry *e = &_tab[hash(i->_pfn)];
112   auto g = lock_guard(e->l);
113   e->h.add(i);
114 }
115
116 PUBLIC
117 Dbg_page_info *
118 Dbg_page_info_table::remove(Page_number pfn)
119 {
120   Entry *e = &_tab[hash(pfn)];
121   auto g = lock_guard(e->l);
122
123   List::Iterator i = find(e->h.begin(), e->h.end(), pfn);
124   if (i == e->h.end())
125     return 0;
126
127   Dbg_page_info *r = *i;
128   e->h.erase(i);
129   return r;
130 }