1 /*
2 * Copyright (c) 1998, 2002 Michael J. Roberts. All Rights Reserved.
3 *
4 * Please see the accompanying license file, LICENSE.TXT, for information
5 * on using and copying this software.
6 */
7 /*
8 Name
9 vmpool.cpp - constant pool implementation
10 Function
11
12 Notes
13
14 Modified
15 10/20/98 MJRoberts - Creation
16 */
17
18 #include <stdlib.h>
19 #include <memory.h>
20
21 #include "t3std.h"
22 #include "vmpool.h"
23
24
25 /* ------------------------------------------------------------------------ */
26 /*
27 * Basic pool implementation
28 */
29
30 /*
31 * Get the number of pages in the pool
32 */
get_page_count() const33 size_t CVmPool::get_page_count() const
34 {
35 /* get the page count from the backing store */
36 return backing_store_->vmpbs_get_page_count();
37 }
38
39 /*
40 * Attach to a backing store
41 */
attach_backing_store(CVmPoolBackingStore * backing_store)42 void CVmPool::attach_backing_store(CVmPoolBackingStore *backing_store)
43 {
44 /* remember the backing store */
45 backing_store_ = backing_store;
46
47 /* get the page size from the backing store */
48 page_size_ = backing_store->vmpbs_get_common_page_size();
49 }
50
51 /* ------------------------------------------------------------------------ */
52 /*
53 * Base paged pool implementation
54 */
55
56 /*
57 * delete our page list
58 */
delete_page_list()59 void CVmPoolPaged::delete_page_list()
60 {
61 /* if there's a page list, delete it */
62 if (pages_ != 0)
63 {
64 /* free the page array */
65 t3free(pages_);
66
67 /* forget it */
68 pages_ = 0;
69 page_slots_ = 0;
70 page_slots_max_ = 0;
71 }
72
73 /* we can no longer have a backing store */
74 backing_store_ = 0;
75 }
76
77 /*
78 * Attach to a backing store
79 */
attach_backing_store(CVmPoolBackingStore * backing_store)80 void CVmPoolPaged::attach_backing_store(CVmPoolBackingStore *backing_store)
81 {
82 size_t cur;
83 size_t log2;
84
85 /* delete any existing page list */
86 delete_page_list();
87
88 /* inherit default handling */
89 CVmPool::attach_backing_store(backing_store);
90
91 /*
92 * if the page size is zero, there must not be any pages at all -
93 * use a dummy default page size
94 */
95 if (page_size_ == 0)
96 page_size_ = 1024;
97
98 /*
99 * Compute log2 of the page size. If the page size isn't a power of
100 * two, throw an error.
101 */
102 for (cur = page_size_, log2 = 0 ; (cur & 1) == 0 ; cur >>= 1, ++log2) ;
103 if (cur != 1)
104 err_throw(VMERR_BAD_POOL_PAGE_SIZE);
105
106 /* store log2(page_size_) in log2_page_size_ */
107 log2_page_size_ = log2;
108
109 /* allocate the pages */
110 alloc_page_slots(backing_store_->vmpbs_get_page_count());
111 }
112
113 /*
114 * Allocate a page slot
115 */
alloc_page_slots(size_t slots)116 void CVmPoolPaged::alloc_page_slots(size_t slots)
117 {
118 size_t old_slots;
119 size_t i;
120
121 /* note the old slot count */
122 old_slots = page_slots_;
123
124 /* if the new size isn't bigger than the old size, ignore the request */
125 if (slots <= page_slots_)
126 return;
127
128 /* if necessary, expand the master page array */
129 if (slots > page_slots_max_)
130 {
131 size_t siz;
132
133 /*
134 * Increase the maximum, leaving some room for dynamically added
135 * pages.
136 */
137 page_slots_max_ = slots + 10;
138
139 /* calculate the new allocation size */
140 siz = page_slots_max_ * sizeof(pages_[0]);
141
142 /* allocate or reallocate at the new size */
143 if (pages_ == 0)
144 pages_ = (CVmPool_pg *)t3malloc(siz);
145 else
146 pages_ = (CVmPool_pg *)t3realloc(pages_, siz);
147 }
148
149 /* set the new size */
150 page_slots_ = slots;
151
152 /* clear the new subarrays */
153 for (i = old_slots ; i < page_slots_ ; ++i)
154 pages_[i].mem = 0;
155 }
156
157 /* ------------------------------------------------------------------------ */
158 /*
159 * Two-level paged pool implementation. This is a variation of the regular
160 * paged pool that uses a two-level page table. This implementation is not
161 * currently used, because it is less efficient than the single-page pool
162 * and is not needed for modern machines with large contiguous address
163 * spaces; however, we retain it in the event it's needed for 16-bit
164 * segmented architectures, where it might not be possible or convenient to
165 * allocate a sufficiently large master page table and thus a two-level
166 * table is needed.
167 */
168 #if 0
169
170 /*
171 * delete the pool - deletes all allocated pages
172 */
173 CVmPoolPaged2::~CVmPoolPaged2()
174 {
175 /* free our page memory */
176 delete_page_list();
177 }
178
179 /*
180 * delete our page list
181 */
182 void CVmPoolPaged2::delete_page_list()
183 {
184 /* if there's a page list, delete it */
185 if (pages_ != 0)
186 {
187 size_t i;
188 size_t cnt;
189
190 /* free each subarray */
191 cnt = get_subarray_count();
192 for (i = 0 ; i < cnt ; ++i)
193 t3free(pages_[i]);
194
195 /* free the master array */
196 t3free(pages_);
197
198 /* forget about the page list */
199 pages_ = 0;
200 }
201 }
202
203 /*
204 * Attach to a backing store
205 */
206 void CVmPoolPaged2::attach_backing_store(CVmPoolBackingStore *backing_store)
207 {
208 size_t cur;
209 size_t log2;
210
211 /* delete any existing page list */
212 delete_page_list();
213
214 /* remember the backing store */
215 backing_store_ = backing_store;
216
217 /* get the page size from the backing store */
218 page_size_ = backing_store_->vmpbs_get_common_page_size();
219
220 /*
221 * if the page size is zero, there must not be any pages at all - use a
222 * dummy default page size
223 */
224 if (page_size_ == 0)
225 page_size_ = 1024;
226
227 /*
228 * Compute log2 of the page size. If the page size isn't a power of
229 * two, throw an error.
230 */
231 for (cur = page_size_, log2 = 0 ; (cur & 1) == 0 ; cur >>= 1, ++log2) ;
232 if (cur != 1)
233 err_throw(VMERR_BAD_POOL_PAGE_SIZE);
234
235 /* store log2(page_size_) in log2_page_size_ */
236 log2_page_size_ = log2;
237
238 /* allocate the pages */
239 alloc_page_slots(backing_store_->vmpbs_get_page_count());
240 }
241
242 /*
243 * Allocate a page slot
244 */
245 void CVmPoolPaged2::alloc_page_slots(size_t slots)
246 {
247 size_t old_slots;
248 size_t old_sub_cnt;
249 size_t new_sub_cnt;
250
251 /* note the old slot count */
252 old_slots = page_slots_;
253
254 /* if the new size isn't bigger than the old size, ignore the request */
255 if (slots <= page_slots_)
256 return;
257
258 /* note the original subarray count */
259 old_sub_cnt = get_subarray_count();
260
261 /* set the new size */
262 page_slots_ = slots;
263
264 /* note the new subarray count */
265 new_sub_cnt = get_subarray_count();
266
267 /* allocate or expand the master array */
268 if (new_sub_cnt > old_sub_cnt)
269 {
270 size_t siz;
271 size_t i;
272
273 /* figure the new size */
274 siz = new_sub_cnt * sizeof(pages_[0]);
275
276 /* allocate or re-allocate the master array */
277 if (pages_ == 0)
278 pages_ = (CVmPool_pg **)t3malloc(siz);
279 else
280 pages_ = (CVmPool_pg **)t3realloc(pages_, siz);
281
282 /* throw an error if that failed */
283 if (pages_ == 0)
284 err_throw(VMERR_OUT_OF_MEMORY);
285
286 /* clear the new slots */
287 memset(pages_ + old_sub_cnt, 0,
288 (new_sub_cnt - old_sub_cnt) * sizeof(pages_[0]));
289
290 /* allocate the subarrays */
291 for (i = old_sub_cnt ; i < new_sub_cnt ; ++i)
292 {
293 /* allocate this subarray */
294 pages_[i] = (CVmPool_pg *)t3malloc(VMPOOL_SUBARRAY_SIZE
295 * sizeof(pages_[i][0]));
296
297 /* make sure we got the space */
298 if (pages_[i] == 0)
299 err_throw(VMERR_OUT_OF_MEMORY);
300
301 /* clear the page */
302 memset(pages_[i], 0, VMPOOL_SUBARRAY_SIZE * sizeof(pages_[i][0]));
303 }
304 }
305 }
306
307 #endif /* removed 2-paged pool */
308