The Pedigree Project  0.1
Cache.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef CACHE_H
21 #define CACHE_H
22 
23 #include "pedigree/kernel/Atomic.h"
24 #include "pedigree/kernel/Spinlock.h"
25 #include "pedigree/kernel/compiler.h"
26 #include "pedigree/kernel/machine/TimerHandler.h"
27 #include "pedigree/kernel/processor/state_forward.h"
28 #include "pedigree/kernel/processor/types.h"
29 #include "pedigree/kernel/utilities/BloomFilter.h"
30 #include "pedigree/kernel/utilities/CacheConstants.h"
31 #include "pedigree/kernel/utilities/List.h"
32 #include "pedigree/kernel/utilities/MemoryAllocator.h"
33 #include "pedigree/kernel/utilities/RequestQueue.h"
34 #include "pedigree/kernel/utilities/Tree.h"
35 #include "pedigree/kernel/utilities/new"
36 
37 class Thread;
38 class UnlikelyLock;
39 
42 #define CACHE_AGE_THRESHOLD 10
43 
46 #define CACHE_NUM_THRESHOLD 2
47 
49 #define CACHE_WRITEBACK_PERIOD 500
50 
51 // Forward declaration of Cache so CacheManager can be defined first
52 class Cache;
53 
55 class CacheManager :
56 #ifndef STANDALONE_CACHE
57  public TimerHandler,
58 #endif
59  public RequestQueue
60 {
61  public:
62  CacheManager();
63  virtual ~CacheManager();
64 
65  static CacheManager &instance()
66  {
67  return m_Instance;
68  }
69 
70  void initialise();
71 
72  void registerCache(Cache *pCache);
73  void unregisterCache(Cache *pCache);
74 
78  bool trimAll(size_t count = 1);
79 
80  virtual void timer(uint64_t delta, InterruptState &state);
81 
82 #ifdef THREADS
83  void trimThread();
84 #endif
85 
86  private:
91  virtual uint64_t executeRequest(
92  uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
93  uint64_t p6, uint64_t p7, uint64_t p8);
94 
100  virtual bool compareRequests(const Request &a, const Request &b)
101  {
102  // p2 = CallbackCause, p3 = key in m_Pages
103  return (a.p2 == b.p2) && (a.p3 == b.p3);
104  }
105 
106  static CacheManager m_Instance;
107 
108  List<Cache *> m_Caches;
109 
110 #ifdef THREADS
111  Thread *m_pTrimThread;
112 #endif
113 
114  bool m_bActive;
115 };
116 
119 {
120  private:
121  struct CachePage
122  {
124  uintptr_t key;
125 
127  uintptr_t location;
128 
131  size_t refcnt;
132 
134  uint64_t checksum[2];
135 
138 
140  enum Status
141  {
142  // The page is being edited and should not be considered for any
143  // writeback operation.
144  Editing,
145  // The page has been marked as no longer being edited and should
146  // only have a checksum calculated, but no writeback.
147  EditTransition,
148  // The checksum is in flux.
149  ChecksumChanging,
150  // The checksum was in flux but is now stable. A transition into
151  // this state will trigger a writeback.
152  ChecksumStable
153  } status;
154 
157  CachePage *pPrev;
158 
160  bool checkChecksum(uint64_t other[2]) const;
161 
163  bool checkZeroChecksum() const;
164  };
165 
166  public:
177  typedef void (*writeback_t)(
178  CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page,
179  void *meta);
180 
181  Cache(size_t pageConstraints = 0);
182  virtual ~Cache();
183 
185  void setCallback(writeback_t newCallback, void *meta);
186 
188  uintptr_t lookup(uintptr_t key);
189 
200  uintptr_t insert(uintptr_t key, bool *alreadyExisted = nullptr);
201 
210  uintptr_t
211  insert(uintptr_t key, size_t size, bool *alreadyExisted = nullptr);
212 
214  bool exists(uintptr_t key, size_t length);
215 
222  bool evict(uintptr_t key);
223 
229  void empty();
230 
232  void release(uintptr_t key);
233 
246  bool pin(uintptr_t key);
247 
259  size_t trim(size_t count = 1);
260 
265  void sync(uintptr_t key, bool async);
266 
272  void triggerChecksum(uintptr_t key);
273 
283  void startAtomic()
284  {
285  m_bInCritical = 1;
286  }
287 
291  void endAtomic()
292  {
293  m_bInCritical = 0;
294  }
295 
305  void markEditing(uintptr_t key, size_t length = 0);
306 
310  void markNoLongerEditing(uintptr_t key, size_t length = 0);
311 
312  private:
314  bool map(uintptr_t virt) const;
315 
319  bool evict(uintptr_t key, bool bLock, bool bPhysicalLock, bool bRemove);
320 
327  size_t lruEvict(bool force = false);
328 
332  void linkPage(CachePage *pPage);
333 
339  void promotePage(CachePage *pPage);
340 
344  void unlinkPage(CachePage *pPage);
345 
349  void calculateChecksum(CachePage *pPage);
350 
354  bool verifyChecksum(CachePage *pPage, bool replace = false);
355 
359  void checksum(const void *data, size_t len, uint64_t out[2]);
360 
362  {
363  CacheConstants::CallbackCause cause;
364  writeback_t callback;
365  uintptr_t loc;
366  uintptr_t page;
367  void *meta;
368  UnlikelyLock *cacheLock;
369  };
370 
371  public:
379  virtual void timer(uint64_t delta, InterruptState &state);
380 
384  virtual uint64_t executeRequest(
385  uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
386  uint64_t p6, uint64_t p7, uint64_t p8);
387 
388  private:
391 
394 
399  CachePage *m_pLruTail;
400 
404 
407 
410 
412  writeback_t m_Callback;
413 
416  uint64_t m_Nanoseconds;
417 
420 
423 
426 
427 #ifdef STANDALONE_CACHE
428 
429  static void discover_range(uintptr_t &start, uintptr_t &end);
430 #endif
431 };
432 
440 {
441  public:
442  CachePageGuard(Cache &cache, uintptr_t location);
443  virtual ~CachePageGuard();
444 
445  private:
446  Cache &m_Cache;
447  uintptr_t m_Location;
448 };
449 
450 #endif
uintptr_t key
Key for this page.
Definition: Cache.h:124
BloomFilter< uintptr_t > m_PageFilter
Definition: Cache.h:393
static Spinlock m_AllocatorLock
Definition: Cache.h:406
uintptr_t location
The location of this page in memory.
Definition: Cache.h:127
bool checksumChanging
Marker to check that a page&#39;s contents are in flux.
Definition: Cache.h:137
CachePage * m_pLruHead
Definition: Cache.h:398
bool trimAll(size_t count=1)
Definition: Cache.cc:117
virtual bool compareRequests(const Request &a, const Request &b)
Definition: Cache.h:100
virtual void timer(uint64_t delta, InterruptState &state)
Definition: Cache.cc:131
Definition: Cache.h:118
uint64_t m_Nanoseconds
Definition: Cache.h:416
virtual uint64_t executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)
Definition: Cache.cc:140
void * m_CallbackMeta
Definition: Cache.h:419
size_t m_PageConstraints
Definition: Cache.h:425
Status
Current page status.
Definition: Cache.h:140
A key/value dictionary.
Definition: Tree.h:33
static MemoryAllocator m_Allocator
Definition: Cache.h:403
void initialise()
Definition: Cache.cc:78
writeback_t m_Callback
Definition: Cache.h:412
void endAtomic()
Definition: Cache.h:291
CachePage * pNext
Linked list components for LRU.
Definition: Cache.h:156
Definition: Thread.h:54
Spinlock m_Lock
Definition: Cache.h:409
void startAtomic()
Definition: Cache.h:283
size_t refcnt
Definition: Cache.h:131
Tree< uintptr_t, CachePage * > m_Pages
Definition: Cache.h:390
Atomic< size_t > m_bInCritical
Definition: Cache.h:422