Path: blob/master/src/hotspot/share/logging/logOutputList.cpp
40930 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/23#include "precompiled.hpp"24#include "logging/logLevel.hpp"25#include "logging/logOutputList.hpp"26#include "memory/allocation.inline.hpp"27#include "runtime/atomic.hpp"28#include "runtime/orderAccess.hpp"29#include "utilities/globalDefinitions.hpp"3031jint LogOutputList::increase_readers() {32jint result = Atomic::add(&_active_readers, 1);33assert(_active_readers > 0, "Ensure we have consistent state");34return result;35}3637jint LogOutputList::decrease_readers() {38jint result = Atomic::add(&_active_readers, -1);39assert(result >= 0, "Ensure we have consistent state");40return result;41}4243void LogOutputList::wait_until_no_readers() const {44OrderAccess::storeload();45while (_active_readers != 0) {46// Busy wait47}48}4950void LogOutputList::set_output_level(LogOutput* output, LogLevelType level) {51LogOutputNode* node = find(output);52if (level == LogLevel::Off && node != NULL) {53remove_output(node);54} else if (level != LogLevel::Off && node == NULL) {55add_output(output, level);56} else if (node != NULL) {57update_output_level(node, level);58}59}6061LogOutputList::LogOutputNode* LogOutputList::find(const LogOutput* output) const {62for (LogOutputNode* node = _level_start[LogLevel::Last]; node != NULL; node = node->_next) {63if (output == node->_value) {64return node;65}66}67return NULL;68}6970void LogOutputList::clear() {7172// Grab the linked list73LogOutputNode* cur = _level_start[LogLevel::Last];7475// Clear _level_start76for (uint level = LogLevel::First; level < LogLevel::Count; level++) {77_level_start[level] = NULL;78}7980// Delete all nodes from the linked list81wait_until_no_readers();82while (cur != NULL) {83LogOutputNode* next = cur->_next;84delete cur;85cur = next;86}87}8889void LogOutputList::remove_output(LogOutputList::LogOutputNode* node) {90assert(node != NULL, "Node must be non-null");9192// Remove node from _level_start first93bool found = false;94for (uint level = LogLevel::First; level < LogLevel::Count; level++) {95if (_level_start[level] == node) {96found = true;97_level_start[level] = node->_next;98}99}100101// Now remove it from the linked list102for (LogOutputNode* cur = _level_start[LogLevel::Last]; cur != NULL; cur = cur->_next) {103if (cur->_next == node) {104found = true;105cur->_next = node->_next;106break;107}108}109assert(found, "Node to be removed should always be found");110111wait_until_no_readers();112delete node;113}114115void LogOutputList::add_output(LogOutput* output, LogLevelType level) {116LogOutputNode* node = new LogOutputNode();117node->_value = output;118node->_level = level;119120// Set the next pointer to the first node of a lower level121for (node->_next = _level_start[level];122node->_next != NULL && node->_next->_level == level;123node->_next = node->_next->_next) {124}125126// Update the _level_start index127for (int l = LogLevel::Last; l >= level; l--) {128if (_level_start[l] == NULL || _level_start[l]->_level < level) {129_level_start[l] = node;130}131}132133// Add the node the list134for (LogOutputNode* cur = _level_start[LogLevel::Last]; cur != NULL; cur = cur->_next) {135if (cur != node && cur->_next == node->_next) {136cur->_next = node;137break;138}139}140}141142void LogOutputList::update_output_level(LogOutputList::LogOutputNode* node, LogLevelType level) {143add_output(node->_value, level);144wait_until_no_readers();145remove_output(node);146}147148149