cfad47cfa3/tads3/vmpool.cpp

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
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
 */
33
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
 */
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
 */
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
 */
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
 */
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 */