91 }
92
93 #ifndef PRODUCT
94 // Helpful for debugging
95
96 static void print_satb_buffer(const char* name,
97 void** buf,
98 size_t index,
99 size_t capacity) {
100 tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " index: " SIZE_FORMAT
101 " capacity: " SIZE_FORMAT,
102 name, p2i(buf), index, capacity);
103 }
104
105 void SATBMarkQueue::print(const char* name) {
106 print_satb_buffer(name, _buf, index(), capacity());
107 }
108
109 #endif // PRODUCT
110
111 SATBMarkQueueSet::SATBMarkQueueSet() :
112 PtrQueueSet(),
113 _list(),
114 _count_and_process_flag(0),
115 _process_completed_buffers_threshold(SIZE_MAX),
116 _buffer_enqueue_threshold(0)
117 {}
118
119 SATBMarkQueueSet::~SATBMarkQueueSet() {
120 abandon_completed_buffers();
121 }
122
123 // _count_and_process_flag has flag in least significant bit, count in
124 // remaining bits. _process_completed_buffers_threshold is scaled
125 // accordingly, with the lsbit set, so a _count_and_process_flag value
126 // is directly comparable with the recorded threshold value. The
127 // process flag is set whenever the count exceeds the threshold, and
128 // remains set until the count is reduced to zero.
129
130 // Increment count. If count > threshold, set flag, else maintain flag.
131 static void increment_count(volatile size_t* cfptr, size_t threshold) {
132 size_t old;
136 value += 2;
137 assert(value > old, "overflow");
138 if (value > threshold) value |= 1;
139 value = Atomic::cmpxchg(value, cfptr, old);
140 } while (value != old);
141 }
142
143 // Decrement count. If count == 0, clear flag, else maintain flag.
144 static void decrement_count(volatile size_t* cfptr) {
145 size_t old;
146 size_t value = Atomic::load(cfptr);
147 do {
148 assert((value >> 1) != 0, "underflow");
149 old = value;
150 value -= 2;
151 if (value <= 1) value = 0;
152 value = Atomic::cmpxchg(value, cfptr, old);
153 } while (value != old);
154 }
155
156 // Scale requested threshold to align with count field. If scaling
157 // overflows, just use max value. Set process flag field to make
158 // comparison in increment_count exact.
159 static size_t scale_threshold(size_t value) {
160 size_t scaled_value = value << 1;
161 if ((scaled_value >> 1) != value) {
162 scaled_value = SIZE_MAX;
163 }
164 return scaled_value | 1;
165 }
166
167 void SATBMarkQueueSet::initialize(BufferNode::Allocator* allocator,
168 size_t process_completed_buffers_threshold,
169 uint buffer_enqueue_threshold_percentage) {
170 PtrQueueSet::initialize(allocator);
171 _process_completed_buffers_threshold =
172 scale_threshold(process_completed_buffers_threshold);
173 assert(buffer_size() != 0, "buffer size not initialized");
174 // Minimum threshold of 1 ensures enqueuing of completely full buffers.
175 size_t size = buffer_size();
176 size_t enqueue_qty = (size * buffer_enqueue_threshold_percentage) / 100;
177 _buffer_enqueue_threshold = MAX2(size - enqueue_qty, (size_t)1);
178 }
179
180 #ifdef ASSERT
181 void SATBMarkQueueSet::dump_active_states(bool expected_active) {
182 log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
183 log_error(gc, verify)("Actual SATB active states:");
184 log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
185
186 class DumpThreadStateClosure : public ThreadClosure {
187 SATBMarkQueueSet* _qset;
188 public:
189 DumpThreadStateClosure(SATBMarkQueueSet* qset) : _qset(qset) {}
190 virtual void do_thread(Thread* t) {
191 SATBMarkQueue& queue = _qset->satb_queue_for_thread(t);
192 log_error(gc, verify)(" Thread \"%s\" queue: %s",
193 t->name(),
194 queue.is_active() ? "ACTIVE" : "INACTIVE");
195 }
196 } closure(this);
|
91 }
92
93 #ifndef PRODUCT
94 // Helpful for debugging
95
96 static void print_satb_buffer(const char* name,
97 void** buf,
98 size_t index,
99 size_t capacity) {
100 tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " index: " SIZE_FORMAT
101 " capacity: " SIZE_FORMAT,
102 name, p2i(buf), index, capacity);
103 }
104
105 void SATBMarkQueue::print(const char* name) {
106 print_satb_buffer(name, _buf, index(), capacity());
107 }
108
109 #endif // PRODUCT
110
111 SATBMarkQueueSet::SATBMarkQueueSet(BufferNode::Allocator* allocator) :
112 PtrQueueSet(allocator),
113 _list(),
114 _count_and_process_flag(0),
115 _process_completed_buffers_threshold(SIZE_MAX),
116 _buffer_enqueue_threshold(0)
117 {}
118
119 SATBMarkQueueSet::~SATBMarkQueueSet() {
120 abandon_completed_buffers();
121 }
122
123 // _count_and_process_flag has flag in least significant bit, count in
124 // remaining bits. _process_completed_buffers_threshold is scaled
125 // accordingly, with the lsbit set, so a _count_and_process_flag value
126 // is directly comparable with the recorded threshold value. The
127 // process flag is set whenever the count exceeds the threshold, and
128 // remains set until the count is reduced to zero.
129
130 // Increment count. If count > threshold, set flag, else maintain flag.
131 static void increment_count(volatile size_t* cfptr, size_t threshold) {
132 size_t old;
136 value += 2;
137 assert(value > old, "overflow");
138 if (value > threshold) value |= 1;
139 value = Atomic::cmpxchg(value, cfptr, old);
140 } while (value != old);
141 }
142
143 // Decrement count. If count == 0, clear flag, else maintain flag.
144 static void decrement_count(volatile size_t* cfptr) {
145 size_t old;
146 size_t value = Atomic::load(cfptr);
147 do {
148 assert((value >> 1) != 0, "underflow");
149 old = value;
150 value -= 2;
151 if (value <= 1) value = 0;
152 value = Atomic::cmpxchg(value, cfptr, old);
153 } while (value != old);
154 }
155
156 void SATBMarkQueueSet::set_process_completed_buffers_threshold(size_t value) {
157 // Scale requested threshold to align with count field. If scaling
158 // overflows, just use max value. Set process flag field to make
159 // comparison in increment_count exact.
160 size_t scaled_value = value << 1;
161 if ((scaled_value >> 1) != value) {
162 scaled_value = SIZE_MAX;
163 }
164 _process_completed_buffers_threshold = scaled_value | 1;
165 }
166
167 void SATBMarkQueueSet::set_buffer_enqueue_threshold_percentage(uint value) {
168 // Minimum threshold of 1 ensures enqueuing of completely full buffers.
169 size_t size = buffer_size();
170 size_t enqueue_qty = (size * value) / 100;
171 _buffer_enqueue_threshold = MAX2(size - enqueue_qty, (size_t)1);
172 }
173
174 #ifdef ASSERT
175 void SATBMarkQueueSet::dump_active_states(bool expected_active) {
176 log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
177 log_error(gc, verify)("Actual SATB active states:");
178 log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
179
180 class DumpThreadStateClosure : public ThreadClosure {
181 SATBMarkQueueSet* _qset;
182 public:
183 DumpThreadStateClosure(SATBMarkQueueSet* qset) : _qset(qset) {}
184 virtual void do_thread(Thread* t) {
185 SATBMarkQueue& queue = _qset->satb_queue_for_thread(t);
186 log_error(gc, verify)(" Thread \"%s\" queue: %s",
187 t->name(),
188 queue.is_active() ? "ACTIVE" : "INACTIVE");
189 }
190 } closure(this);
|