1 /* 2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jfr/recorder/storage/jfrStorageControl.hpp" 27 #include "runtime/atomic.inline.hpp" 28 #include "runtime/mutexLocker.hpp" 29 #include "runtime/orderAccess.inline.hpp" 30 31 // returns the updated value 32 static jlong atomic_add(size_t value, size_t volatile* const dest) { 33 size_t compare_value; 34 size_t exchange_value; 35 do { 36 compare_value = OrderAccess::load_ptr_acquire((intptr_t*)dest); 37 exchange_value = compare_value + value; 38 } while ((unsigned long)Atomic::cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value) != compare_value); 39 return exchange_value; 40 } 41 42 static jlong atomic_dec(size_t volatile* const dest) { 43 size_t compare_value; 44 size_t exchange_value; 45 do { 46 compare_value = OrderAccess::load_ptr_acquire((intptr_t*)dest); 47 assert(compare_value >= 1, "invariant"); 48 exchange_value = compare_value - 1; 49 } while ((unsigned long)Atomic::cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value) != compare_value); 50 return exchange_value; 51 } 52 53 const size_t max_lease_factor = 2; 54 JfrStorageControl::JfrStorageControl(size_t global_count_total, size_t in_memory_discard_threshold) : 55 _global_count_total(global_count_total), 56 _full_count(0), 57 _global_lease_count(0), 58 _dead_count(0), 59 _to_disk_threshold(0), 60 _in_memory_discard_threshold(in_memory_discard_threshold), 61 _global_lease_threshold(global_count_total / max_lease_factor), 62 _scavenge_threshold(0), 63 _to_disk(false) {} 64 65 bool JfrStorageControl::to_disk() const { 66 return _to_disk; 67 } 68 69 void JfrStorageControl::set_to_disk(bool enable) { 70 _to_disk = enable; 71 } 72 73 size_t JfrStorageControl::full_count() const { 74 return _full_count; 75 } 76 77 // mutexed access 78 size_t JfrStorageControl::increment_full() { 79 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 80 return ++_full_count; 81 } 82 83 size_t JfrStorageControl::decrement_full() { 84 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 85 assert(_full_count > 0, "invariant"); 86 return --_full_count; 87 } 88 89 void JfrStorageControl::reset_full() { 90 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 91 _full_count = 0; 92 } 93 94 bool JfrStorageControl::should_post_buffer_full_message() const { 95 return to_disk() && (full_count() > _to_disk_threshold); 96 } 97 98 bool JfrStorageControl::should_discard() const { 99 return !to_disk() && full_count() >= _in_memory_discard_threshold; 100 } 101 102 // concurrent with accuracy requirement 103 104 size_t JfrStorageControl::global_lease_count() const { 105 return (size_t)OrderAccess::load_ptr_acquire((intptr_t*)&_global_lease_count); 106 } 107 108 size_t JfrStorageControl::increment_leased() { 109 return atomic_add(1, &_global_lease_count); 110 } 111 112 size_t JfrStorageControl::decrement_leased() { 113 return atomic_dec(&_global_lease_count); 114 } 115 116 bool JfrStorageControl::is_global_lease_allowed() const { 117 return global_lease_count() <= _global_lease_threshold; 118 } 119 120 // concurrent with lax requirement 121 122 size_t JfrStorageControl::dead_count() const { 123 return _dead_count; 124 } 125 126 size_t JfrStorageControl::increment_dead() { 127 return atomic_add(1, &_dead_count); 128 } 129 130 size_t JfrStorageControl::decrement_dead() { 131 return atomic_dec(&_dead_count); 132 } 133 134 bool JfrStorageControl::should_scavenge() const { 135 return dead_count() >= _scavenge_threshold; 136 } 137 138 void JfrStorageControl::set_scavenge_threshold(size_t number_of_dead_buffers) { 139 _scavenge_threshold = number_of_dead_buffers; 140 } 141