179 return lease_free(size, manager._epoch_transition_mspace, lease_retry, thread); |
179 return lease_free(size, manager._epoch_transition_mspace, lease_retry, thread); |
180 } |
180 } |
181 return lease_free(size, manager._free_list_mspace, lease_retry, thread); |
181 return lease_free(size, manager._free_list_mspace, lease_retry, thread); |
182 } |
182 } |
183 |
183 |
|
184 JfrCheckpointMspace* JfrCheckpointManager::lookup(BufferPtr old) const { |
|
185 assert(old != NULL, "invariant"); |
|
186 return _free_list_mspace->in_free_list(old) ? _free_list_mspace : _epoch_transition_mspace; |
|
187 } |
|
188 |
|
189 BufferPtr JfrCheckpointManager::lease_buffer(BufferPtr old, Thread* thread, size_t size /* 0 */) { |
|
190 assert(old != NULL, "invariant"); |
|
191 JfrCheckpointMspace* mspace = instance().lookup(old); |
|
192 assert(mspace != NULL, "invariant"); |
|
193 return lease_free(size, mspace, lease_retry, thread); |
|
194 } |
|
195 |
184 /* |
196 /* |
185 * If the buffer was a "lease" from the free list, release back. |
197 * If the buffer was a "lease", release back. |
186 * |
198 * |
187 * The buffer is effectively invalidated for the thread post-return, |
199 * The buffer is effectively invalidated for the thread post-return, |
188 * and the caller should take means to ensure that it is not referenced. |
200 * and the caller should take means to ensure that it is not referenced. |
189 */ |
201 */ |
190 static void release(BufferPtr const buffer, Thread* thread) { |
202 static void release(BufferPtr const buffer, Thread* thread) { |
200 // indicates a lease is being returned |
212 // indicates a lease is being returned |
201 release(old, thread); |
213 release(old, thread); |
202 return NULL; |
214 return NULL; |
203 } |
215 } |
204 // migration of in-flight information |
216 // migration of in-flight information |
205 BufferPtr const new_buffer = lease_buffer(thread, used + requested); |
217 BufferPtr const new_buffer = lease_buffer(old, thread, used + requested); |
206 if (new_buffer != NULL) { |
218 if (new_buffer != NULL) { |
207 migrate_outstanding_writes(old, new_buffer, used, requested); |
219 migrate_outstanding_writes(old, new_buffer, used, requested); |
208 } |
220 } |
209 release(old, thread); |
221 release(old, thread); |
210 return new_buffer; // might be NULL |
222 return new_buffer; // might be NULL |
211 } |
223 } |
212 |
224 |
213 // offsets into the JfrCheckpointEntry |
225 // offsets into the JfrCheckpointEntry |
214 static const juint starttime_offset = sizeof(jlong); |
226 static const juint starttime_offset = sizeof(jlong); |
215 static const juint duration_offset = starttime_offset + sizeof(jlong); |
227 static const juint duration_offset = starttime_offset + sizeof(jlong); |
216 static const juint flushpoint_offset = duration_offset + sizeof(jlong); |
228 static const juint mode_offset = duration_offset + sizeof(jlong); |
217 static const juint types_offset = flushpoint_offset + sizeof(juint); |
229 static const juint types_offset = mode_offset + sizeof(juint); |
218 static const juint payload_offset = types_offset + sizeof(juint); |
230 static const juint payload_offset = types_offset + sizeof(juint); |
219 |
231 |
220 template <typename Return> |
232 template <typename Return> |
221 static Return read_data(const u1* data) { |
233 static Return read_data(const u1* data) { |
222 return JfrBigEndian::read<Return>(data); |
234 return JfrBigEndian::read<Return>(data); |
232 |
244 |
233 static jlong duration(const u1* data) { |
245 static jlong duration(const u1* data) { |
234 return read_data<jlong>(data + duration_offset); |
246 return read_data<jlong>(data + duration_offset); |
235 } |
247 } |
236 |
248 |
|
249 static u1 mode(const u1* data) { |
|
250 return read_data<u1>(data + mode_offset); |
|
251 } |
|
252 |
237 static juint number_of_types(const u1* data) { |
253 static juint number_of_types(const u1* data) { |
238 return read_data<juint>(data + types_offset); |
254 return read_data<juint>(data + types_offset); |
239 } |
255 } |
240 |
256 |
241 static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) { |
257 static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) { |
242 cw.reserve(sizeof(u4)); |
258 cw.reserve(sizeof(u4)); |
243 cw.write<u8>(EVENT_CHECKPOINT); |
259 cw.write<u8>(EVENT_CHECKPOINT); |
244 cw.write<u8>(starttime(data)); |
260 cw.write(starttime(data)); |
245 cw.write<u8>(duration(data)); |
261 cw.write(duration(data)); |
246 cw.write<u8>(offset_prev_cp_event); |
262 cw.write(offset_prev_cp_event); |
247 cw.write<bool>(false); // not a flushpoint |
263 cw.write(mode(data)); |
248 cw.write<juint>(number_of_types(data)); |
264 cw.write(number_of_types(data)); |
249 } |
265 } |
250 |
266 |
251 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) { |
267 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) { |
252 assert(data != NULL, "invariant"); |
268 assert(data != NULL, "invariant"); |
253 cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry)); |
269 cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry)); |
348 assert(_free_list_mspace->is_full_empty(), "invariant"); |
364 assert(_free_list_mspace->is_full_empty(), "invariant"); |
349 process_free_list(fo, _free_list_mspace); |
365 process_free_list(fo, _free_list_mspace); |
350 return wo.processed(); |
366 return wo.processed(); |
351 } |
367 } |
352 |
368 |
|
369 // Optimization for write_types() and write_threads() is to write |
|
370 // directly into the epoch transition mspace because we will immediately |
|
371 // serialize and reset this mspace post-write. |
|
372 static JfrBuffer* get_epoch_transition_buffer(JfrCheckpointMspace* mspace, Thread* t) { |
|
373 assert(mspace != NULL, "invariant"); |
|
374 JfrBuffer* const buffer = mspace->free_head(); |
|
375 assert(buffer != NULL, "invariant"); |
|
376 buffer->acquire(t); |
|
377 buffer->set_lease(); |
|
378 DEBUG_ONLY(assert_free_lease(buffer);) |
|
379 return buffer; |
|
380 } |
|
381 |
353 size_t JfrCheckpointManager::write_types() { |
382 size_t JfrCheckpointManager::write_types() { |
354 ResourceMark rm; |
383 ResourceMark rm; |
355 HandleMark hm; |
384 HandleMark hm; |
356 Thread* const t = Thread::current(); |
385 Thread* const t = Thread::current(); |
357 // Optimization here is to write the types directly into the epoch transition mspace |
386 JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), STATICS); |
358 // because the caller will immediately serialize and reset this mspace. |
|
359 JfrBuffer* const buffer = _epoch_transition_mspace->free_tail(); |
|
360 assert(buffer != NULL, "invariant"); |
|
361 buffer->acquire(t); |
|
362 buffer->set_lease(); |
|
363 DEBUG_ONLY(assert_free_lease(buffer);) |
|
364 JfrCheckpointWriter writer(t, buffer); |
|
365 JfrTypeManager::write_types(writer); |
387 JfrTypeManager::write_types(writer); |
366 return writer.used_size(); |
388 return writer.used_size(); |
367 } |
389 } |
368 |
390 |
|
391 size_t JfrCheckpointManager::write_threads() { |
|
392 ResourceMark rm; |
|
393 HandleMark hm; |
|
394 Thread* const t = Thread::current(); |
|
395 JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), THREADS); |
|
396 JfrTypeManager::write_threads(writer); |
|
397 return writer.used_size(); |
|
398 } |
|
399 |
369 size_t JfrCheckpointManager::write_epoch_transition_mspace() { |
400 size_t JfrCheckpointManager::write_epoch_transition_mspace() { |
370 return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter); |
401 return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter); |
371 } |
402 } |
372 |
403 |
373 size_t JfrCheckpointManager::write_constants() { |
404 size_t JfrCheckpointManager::write_constants() { |
374 write_types(); |
405 write_types(); |
|
406 write_threads(); |
375 return write_epoch_transition_mspace(); |
407 return write_epoch_transition_mspace(); |
376 } |
408 } |
377 |
409 |
378 class JfrNotifyClosure : public ThreadClosure { |
410 class JfrNotifyClosure : public ThreadClosure { |
379 public: |
411 public: |