1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6 #ifndef VM_ADDRESS_SPACE_LOCKING_H
7 #define VM_ADDRESS_SPACE_LOCKING_H
8
9
10 #include <OS.h>
11
12 #include <vm/VMAddressSpace.h>
13
14
15 struct VMAddressSpace;
16 struct VMArea;
17 struct VMCache;
18
19
20 class AddressSpaceLockerBase {
21 public:
22 static VMAddressSpace* GetAddressSpaceByAreaID(area_id id);
23 };
24
25
26 class AddressSpaceReadLocker : private AddressSpaceLockerBase {
27 public:
28 AddressSpaceReadLocker(team_id team);
29 AddressSpaceReadLocker(VMAddressSpace* space,
30 bool getNewReference);
31 AddressSpaceReadLocker();
32 ~AddressSpaceReadLocker();
33
34 status_t SetTo(team_id team);
35 void SetTo(VMAddressSpace* space,
36 bool getNewReference);
37 status_t SetFromArea(area_id areaID, VMArea*& area);
38
IsLocked()39 bool IsLocked() const { return fLocked; }
40 bool Lock();
41 void Unlock();
42
43 void Unset();
44
AddressSpace()45 VMAddressSpace* AddressSpace() const { return fSpace; }
46
47 private:
48 VMAddressSpace* fSpace;
49 bool fLocked;
50 };
51
52
53 class AddressSpaceWriteLocker : private AddressSpaceLockerBase {
54 public:
55 AddressSpaceWriteLocker(team_id team);
56 AddressSpaceWriteLocker(VMAddressSpace* space,
57 bool getNewReference);
58 AddressSpaceWriteLocker();
59 ~AddressSpaceWriteLocker();
60
61 status_t SetTo(team_id team);
62 void SetTo(VMAddressSpace* space,
63 bool getNewReference);
64 status_t SetFromArea(area_id areaID, VMArea*& area);
65 status_t SetFromArea(team_id team, area_id areaID,
66 bool allowKernel, VMArea*& area);
67 status_t SetFromArea(team_id team, area_id areaID,
68 VMArea*& area);
69
IsLocked()70 bool IsLocked() const { return fLocked; }
71 void Unlock();
72
73 void DegradeToReadLock();
74 void Unset();
75
AddressSpace()76 VMAddressSpace* AddressSpace() const { return fSpace; }
77
78 private:
79 VMAddressSpace* fSpace;
80 bool fLocked;
81 bool fDegraded;
82 };
83
84
85 class MultiAddressSpaceLocker : private AddressSpaceLockerBase {
86 public:
87 MultiAddressSpaceLocker();
88 ~MultiAddressSpaceLocker();
89
90 inline status_t AddTeam(team_id team, bool writeLock,
91 VMAddressSpace** _space = NULL);
92 inline status_t AddArea(area_id area, bool writeLock,
93 VMAddressSpace** _space = NULL);
94 inline status_t AddArea(VMArea* area, bool writeLock,
95 VMAddressSpace** _space = NULL);
96
97 status_t AddAreaCacheAndLock(area_id areaID,
98 bool writeLockThisOne, bool writeLockOthers,
99 VMArea*& _area, VMCache** _cache = NULL);
100
101 status_t Lock();
102 void Unlock();
IsLocked()103 bool IsLocked() const { return fLocked; }
104
105 void Unset();
106
107 private:
108 struct lock_item {
109 VMAddressSpace* space;
110 bool write_lock;
111 };
112
113 bool _ResizeIfNeeded();
114 int32 _IndexOfAddressSpace(VMAddressSpace* space)
115 const;
116 status_t _AddAddressSpace(VMAddressSpace* space,
117 bool writeLock, VMAddressSpace** _space);
118
119 static int _CompareItems(const void* _a, const void* _b);
120
121 lock_item* fItems;
122 int32 fCapacity;
123 int32 fCount;
124 bool fLocked;
125 };
126
127
128 inline status_t
AddTeam(team_id team,bool writeLock,VMAddressSpace ** _space)129 MultiAddressSpaceLocker::AddTeam(team_id team, bool writeLock,
130 VMAddressSpace** _space)
131 {
132 return _AddAddressSpace(VMAddressSpace::Get(team), writeLock, _space);
133 }
134
135
136 inline status_t
AddArea(area_id area,bool writeLock,VMAddressSpace ** _space)137 MultiAddressSpaceLocker::AddArea(area_id area, bool writeLock,
138 VMAddressSpace** _space)
139 {
140 return _AddAddressSpace(GetAddressSpaceByAreaID(area), writeLock, _space);
141 }
142
143
144 inline status_t
AddArea(VMArea * area,bool writeLock,VMAddressSpace ** _space)145 MultiAddressSpaceLocker::AddArea(VMArea* area, bool writeLock,
146 VMAddressSpace** _space)
147 {
148 area->address_space->Get();
149 return _AddAddressSpace(area->address_space, writeLock, _space);
150 }
151
152
153 #endif // VM_ADDRESS_SPACE_LOCKING_H
154