]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/dbg_page_info.cpp
92e7f35c3fb5bf2d0393ed9596243bf1db354608
[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 <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) { return p.value() % Hash_tab_size; }
60 };
61
62
63
64 IMPLEMENTATION [debug]:
65
66 #include "kmem_slab.h"
67
68
69 static Dbg_page_info_table _t;
70
71 PUBLIC static
72 Dbg_page_info_table &
73 Dbg_page_info::table()
74 {
75   return _t;
76 }
77
78 static Kmem_slab_t<Dbg_page_info> _dbg_page_info_allocator("Dbg_page_info");
79
80 PRIVATE static
81 Dbg_page_info::Allocator *
82 Dbg_page_info::alloc()
83 { return &_dbg_page_info_allocator; }
84
85
86 PUBLIC template<typename B, typename E> static inline
87 B
88 Dbg_page_info_table::find(B const &b, E const &e, Page_number p)
89 {
90   for (B i = b; i != e; ++i)
91     if (i->match(p))
92       return i;
93   return e;
94 }
95
96 PUBLIC
97 Dbg_page_info *
98 Dbg_page_info_table::operator [] (Page_number pfn) const
99 {
100   Entry &e = const_cast<Dbg_page_info_table*>(this)->_tab[hash(pfn)];
101   auto g = lock_guard(e.l);
102   // we know that *end() is NULL
103   return *find(e.h.begin(), e.h.end(), pfn);
104 }
105
106 PUBLIC
107 void
108 Dbg_page_info_table::insert(Dbg_page_info *i)
109 {
110   Entry *e = &_tab[hash(i->_pfn)];
111   auto g = lock_guard(e->l);
112   e->h.add(i);
113 }
114
115 PUBLIC
116 Dbg_page_info *
117 Dbg_page_info_table::remove(Page_number pfn)
118 {
119   Entry *e = &_tab[hash(pfn)];
120   auto g = lock_guard(e->l);
121
122   List::Iterator i = find(e->h.begin(), e->h.end(), pfn);
123   if (i == e->h.end())
124     return 0;
125
126   Dbg_page_info *r = *i;
127   e->h.erase(i);
128   return r;
129 }