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.hpp" 28 #include "runtime/mutexLocker.hpp" 29 30 // returns the updated value 31 static jlong atomic_add(size_t value, size_t volatile* const dest) { 32 size_t compare_value; 33 size_t exchange_value; 34 do { 35 compare_value = *dest; 36 exchange_value = compare_value + value; 37 } while (Atomic::cmpxchg(exchange_value, dest, compare_value) != compare_value); 38 return exchange_value; 39 } 40 41 static jlong atomic_dec(size_t volatile* const dest) { 42 size_t compare_value; 43 size_t exchange_value; 44 do { 45 compare_value = *dest; 46 assert(compare_value >= 1, "invariant"); 47 exchange_value = compare_value - 1; 48 } while (Atomic::cmpxchg(exchange_value, dest, compare_value) != compare_value); 49 return exchange_value; 50 } 51 52 const size_t max_lease_factor = 2; 53 JfrStorageControl::JfrStorageControl(size_t global_count_total, size_t in_memory_discard_threshold) : 54 _global_count_total(global_count_total), 55 _full_count(0), 56 _global_lease_count(0), 57 _dead_count(0), 58 _to_disk_threshold(0), 59 _in_memory_discard_threshold(in_memory_discard_threshold), 60 _global_lease_threshold(global_count_total / max_lease_factor), 61 _scavenge_threshold(0), 62 _to_disk(false) {} 63 64 bool JfrStorageControl::to_disk() const { 65 return _to_disk; 66 } 67 68 void JfrStorageControl::set_to_disk(bool enable) { 69 _to_disk = enable; 70 } 71 72 size_t JfrStorageControl::full_count() const { 73 return _full_count; 74 } 75 76 // mutexed access 77 size_t JfrStorageControl::increment_full() { 78 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 79 return ++_full_count; 80 } 81 82 size_t JfrStorageControl::decrement_full() { 83 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 84 assert(_full_count > 0, "invariant"); 85 return --_full_count; 86 } 87 88 void JfrStorageControl::reset_full() { 89 assert(JfrBuffer_lock->owned_by_self(), "invariant"); 90 _full_count = 0; 91 } 92 93 bool JfrStorageControl::should_post_buffer_full_message() const { 94 return to_disk() && (full_count() > _to_disk_threshold); 95 } 96 97 bool JfrStorageControl::should_discard() const { 98 return !to_disk() && full_count() >= _in_memory_discard_threshold; 99 } 100 101 // concurrent with accuracy requirement 102 103 size_t JfrStorageControl::global_lease_count() const { 104 return Atomic::load(&_global_lease_count); 105 } 106 107 size_t JfrStorageControl::increment_leased() { 108 return atomic_add(1, &_global_lease_count); 109 } 110 111 size_t JfrStorageControl::decrement_leased() { 112 return atomic_dec(&_global_lease_count); 113 } 114 115 bool JfrStorageControl::is_global_lease_allowed() const { 116 return global_lease_count() <= _global_lease_threshold; 117 } 118 119 // concurrent with lax requirement 120 121 size_t JfrStorageControl::dead_count() const { 122 return _dead_count; 123 } 124 125 size_t JfrStorageControl::increment_dead() { 126 return atomic_add(1, &_dead_count); 127 } 128 129 size_t JfrStorageControl::decrement_dead() { 130 return atomic_dec(&_dead_count); 131 } 132 133 bool JfrStorageControl::should_scavenge() const { 134 return dead_count() >= _scavenge_threshold; 135 } 136 137 void JfrStorageControl::set_scavenge_threshold(size_t number_of_dead_buffers) { 138 _scavenge_threshold = number_of_dead_buffers; 139 } 140