btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / vm / VMPageQueue.h
blob9f6f8877f4623db09e06bb9923eeddf6ae565a39
1 /*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
8 */
9 #ifndef VM_PAGE_QUEUE_H
10 #define VM_PAGE_QUEUE_H
13 #include <util/DoublyLinkedList.h>
15 #include <lock.h>
16 #include <int.h>
17 #include <util/AutoLock.h>
18 #include <vm/vm_types.h>
21 struct VMPageQueue {
22 public:
23 typedef DoublyLinkedList<vm_page,
24 DoublyLinkedListMemberGetLink<vm_page, &vm_page::queue_link> > PageList;
25 typedef PageList::ConstIterator Iterator;
27 public:
28 void Init(const char* name);
30 const char* Name() const { return fName; }
32 inline void Append(vm_page* page);
33 inline void Prepend(vm_page* page);
34 inline void InsertAfter(vm_page* insertAfter,
35 vm_page* page);
36 inline void Remove(vm_page* page);
37 inline vm_page* RemoveHead();
38 inline void Requeue(vm_page* page, bool tail);
40 inline void AppendUnlocked(vm_page* page);
41 inline void AppendUnlocked(PageList& pages, uint32 count);
42 inline void PrependUnlocked(vm_page* page);
43 inline void RemoveUnlocked(vm_page* page);
44 inline vm_page* RemoveHeadUnlocked();
45 inline void RequeueUnlocked(vm_page* page, bool tail);
47 inline vm_page* Head() const;
48 inline vm_page* Tail() const;
49 inline vm_page* Previous(vm_page* page) const;
50 inline vm_page* Next(vm_page* page) const;
52 inline phys_addr_t Count() const { return fCount; }
54 inline Iterator GetIterator() const;
56 inline spinlock& GetLock() { return fLock; }
58 protected:
59 const char* fName;
60 spinlock fLock;
61 phys_addr_t fCount;
62 PageList fPages;
66 // #pragma mark - VMPageQueue
69 void
70 VMPageQueue::Append(vm_page* page)
72 #if DEBUG_PAGE_QUEUE
73 if (page->queue != NULL) {
74 panic("%p->VMPageQueue::Append(page: %p): page thinks it is "
75 "already in queue %p", this, page, page->queue);
77 #endif // DEBUG_PAGE_QUEUE
79 fPages.Add(page);
80 fCount++;
82 #if DEBUG_PAGE_QUEUE
83 page->queue = this;
84 #endif
88 void
89 VMPageQueue::Prepend(vm_page* page)
91 #if DEBUG_PAGE_QUEUE
92 if (page->queue != NULL) {
93 panic("%p->VMPageQueue::Prepend(page: %p): page thinks it is "
94 "already in queue %p", this, page, page->queue);
96 #endif // DEBUG_PAGE_QUEUE
98 fPages.Add(page, false);
99 fCount++;
101 #if DEBUG_PAGE_QUEUE
102 page->queue = this;
103 #endif
107 void
108 VMPageQueue::InsertAfter(vm_page* insertAfter, vm_page* page)
110 #if DEBUG_PAGE_QUEUE
111 if (page->queue != NULL) {
112 panic("%p->VMPageQueue::InsertAfter(page: %p): page thinks it is "
113 "already in queue %p", this, page, page->queue);
115 #endif // DEBUG_PAGE_QUEUE
117 fPages.InsertAfter(insertAfter, page);
118 fCount++;
120 #if DEBUG_PAGE_QUEUE
121 page->queue = this;
122 #endif
126 void
127 VMPageQueue::Remove(vm_page* page)
129 #if DEBUG_PAGE_QUEUE
130 if (page->queue != this) {
131 panic("%p->VMPageQueue::Remove(page: %p): page thinks it "
132 "is in queue %p", this, page, page->queue);
134 #endif // DEBUG_PAGE_QUEUE
136 fPages.Remove(page);
137 fCount--;
139 #if DEBUG_PAGE_QUEUE
140 page->queue = NULL;
141 #endif
145 vm_page*
146 VMPageQueue::RemoveHead()
148 vm_page* page = fPages.RemoveHead();
149 if (page != NULL) {
150 fCount--;
152 #if DEBUG_PAGE_QUEUE
153 if (page->queue != this) {
154 panic("%p->VMPageQueue::RemoveHead(): page %p thinks it is in "
155 "queue %p", this, page, page->queue);
158 page->queue = NULL;
159 #endif // DEBUG_PAGE_QUEUE
162 return page;
166 void
167 VMPageQueue::Requeue(vm_page* page, bool tail)
169 #if DEBUG_PAGE_QUEUE
170 if (page->queue != this) {
171 panic("%p->VMPageQueue::Requeue(): page %p thinks it is in "
172 "queue %p", this, page, page->queue);
174 #endif
176 fPages.Remove(page);
177 fPages.Add(page, tail);
181 void
182 VMPageQueue::AppendUnlocked(vm_page* page)
184 InterruptsSpinLocker locker(fLock);
185 Append(page);
189 void
190 VMPageQueue::AppendUnlocked(PageList& pages, uint32 count)
192 #if DEBUG_PAGE_QUEUE
193 for (PageList::Iterator it = pages.GetIterator();
194 vm_page* page = it.next();) {
195 if (page->queue != NULL) {
196 panic("%p->VMPageQueue::AppendUnlocked(): page %p thinks it is "
197 "already in queue %p", this, page, page->queue);
200 page->queue = this;
203 #endif // DEBUG_PAGE_QUEUE
205 InterruptsSpinLocker locker(fLock);
207 fPages.MoveFrom(&pages);
208 fCount += count;
212 void
213 VMPageQueue::PrependUnlocked(vm_page* page)
215 InterruptsSpinLocker locker(fLock);
216 Prepend(page);
220 void
221 VMPageQueue::RemoveUnlocked(vm_page* page)
223 InterruptsSpinLocker locker(fLock);
224 return Remove(page);
228 vm_page*
229 VMPageQueue::RemoveHeadUnlocked()
231 InterruptsSpinLocker locker(fLock);
232 return RemoveHead();
236 void
237 VMPageQueue::RequeueUnlocked(vm_page* page, bool tail)
239 InterruptsSpinLocker locker(fLock);
240 Requeue(page, tail);
244 vm_page*
245 VMPageQueue::Head() const
247 return fPages.Head();
251 vm_page*
252 VMPageQueue::Tail() const
254 return fPages.Tail();
258 vm_page*
259 VMPageQueue::Previous(vm_page* page) const
261 return fPages.GetPrevious(page);
265 vm_page*
266 VMPageQueue::Next(vm_page* page) const
268 return fPages.GetNext(page);
272 VMPageQueue::Iterator
273 VMPageQueue::GetIterator() const
275 return fPages.GetIterator();
279 #endif // VM_PAGE_QUEUE_H