1/*
2 * Copyright (c) 2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20/*
21    Region.h
22    Contiguous range of subzones.
23    Copyright (c) 2004-2011 Apple Inc. All rights reserved.
24 */
25
26#pragma once
27#ifndef __AUTO_REGION__
28#define __AUTO_REGION__
29
30#include "Admin.h"
31#include "Configuration.h"
32#include "Definitions.h"
33#include "Range.h"
34#include "Statistics.h"
35#include "Locks.h"
36
37namespace Auto {
38
39    // Forward declarations
40
41    class Zone;
42    class Subzone;
43
44
45    //----- Region -----//
46
47    class Region : public Range {
48
49      private:
50
51        Region     *_next;                                  // next region in the list.
52        Zone       *_zone;                                  // reference back to main zone
53        spin_lock_t _subzone_lock;                          // protects add_subzone().
54        usword_t    _i_subzones;                            // number of active subzones
55        usword_t    _n_subzones;                            // total number of subzones
56        usword_t    _n_quantum;                             // total number of quantum avalable
57        Range       _scan_space;                            // space used during scanning - may be used as
58                                                            // a stack or pending bits
59        Bitmap      _pending;                               // "ready to use" bitmap overlayed on _scan_space
60        Bitmap      _marks;                                 // bitmap for the marks used during reachability analysis
61        Bitmap      _pinned;                                // bitmap for compaction
62
63      public:
64
65        //
66        // bytes_needed
67        //
68        // Return the number of bytes needed to represent a region object of the specified size.
69        //
70        static const usword_t bytes_needed() {
71            return align2(sizeof(Region), page_size_log2);
72        }
73
74        //
75        // managed_size
76        //
77        // Return the number of bytes needed for N subzones.
78        //
79        static usword_t managed_size(usword_t nsubzones) { return (nsubzones << subzone_quantum_log2) + nsubzones * bitmaps_per_region * subzone_bitmap_bytes; }
80
81        //
82        // allocator
83        //
84        inline void *operator new(const size_t size) {
85            // allocate admin data
86            return allocate_memory(Region::bytes_needed());
87        }
88
89
90
91        //
92        // deallocator
93        //
94        inline void operator delete(void *address) {
95            Region *region = (Region *)address;
96
97            // release subzone memory
98           // XXX region->_zone->arena_deallocate(region->address(), region->size());
99
100            // release C++ "Region::" data structure, including admin data
101            deallocate_memory(region, Region::bytes_needed());
102        }
103
104
105        //
106        // Constructor
107        //
108        Region(Zone *zone, void *address, usword_t size, usword_t nzones);
109
110
111        //
112        // Destructor
113        //
114        ~Region();
115
116
117        //
118        // Accessors
119        //
120        inline void set_next(Region *next)        { _next = next; }
121        inline Region *next()               const { return _next; }
122        inline Zone *zone()                 const { return _zone; }
123        inline Range scan_space()           const { return _scan_space; }
124        inline spin_lock_t *subzone_lock()        { return &_subzone_lock; }
125
126        inline Bitmap &pending()                  { return _pending; }
127        inline Bitmap &marks()                    { return _marks; }
128        inline Bitmap &pinned()                   { return _pinned; }
129
130        //
131        //
132        // number of subzones remaining
133        //
134        inline usword_t subzones_remaining() const { return _n_subzones - _i_subzones; }
135
136        inline usword_t active_subzones()    const { return _i_subzones; }
137
138        //
139        // new_region
140        //
141        // Construct and initialize a new region.
142        //
143        static Region *new_region(Zone *zone );
144
145        //
146        // subzone_index
147        //
148        // Returns a regional subzone index for an arbitrary pointer.  Note that this is relative to region memory.  subzone_index in
149        // Zone is absolute memory.
150        //
151        inline const usword_t subzone_index(void *address) const { return (const usword_t)((uintptr_t)relative_address(address) >> subzone_quantum_log2); }
152
153
154        //
155        // subzone_size
156        //
157        // Returns the size of n subzones.
158        //
159        static inline usword_t subzone_size(const usword_t n) { return n << subzone_quantum_log2; }
160
161
162        //
163        // subzone_count
164        //
165        // Returns a number of subzone quantum for a given size.
166        //
167        static inline usword_t subzone_count(const size_t size) { return partition2(size, subzone_quantum_log2); }
168
169
170        //
171        // subzone_address
172        //
173        // Returns the address of the ith subzone
174        //
175        inline Subzone *subzone_address(const usword_t i) const { return (Subzone *)displace(address(), i << subzone_quantum_log2); }
176
177
178        //
179        // subzone_range
180        //
181        // Returns the range of active subzones.
182        //
183        inline Range subzone_range() { SpinLock lock(&_subzone_lock); return Range(address(), subzone_size(_i_subzones)); }
184
185
186        //
187        // add_subzone
188        //
189        // Add a new subzone to one of the admin.
190        //
191        bool add_subzone(Admin *admin);
192
193
194        //
195        // test_and_set_mark
196        //
197        // Used by subzone to test and set mark bit for quantum.
198        //
199        inline bool test_and_set_mark(usword_t q) {
200            return (bool)_marks.test_set_bit_atomic(q);
201        }
202
203
204        //
205        // test_and_clear_mark
206        //
207        // Used by subzone to test and clear mark bit for quantum.
208        //
209        inline bool test_and_clear_mark(usword_t q) {
210            return (bool)_marks.test_clear_bit_atomic(q);
211        }
212
213
214        //
215        // clear_marks
216        //
217        // Used at the end of collection
218        //
219        inline void clear_marks() {
220            _marks.clear();
221        }
222    };
223
224
225};
226
227
228#endif // __AUTO_REGION__
229