parCardTableModRefBS.cpp revision 1753
1753N/A * Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A#
include "incls/_precompiled.incl" 845N/A "# worker threads != # requested!");
845N/A // Make sure the LNC array is valid for the space. 0N/A // Clear lowest_non_clean array for next time. 0N/A // We don't have to go downwards here; it wouldn't help anyway, 0N/A // because of parallelism. 0N/A // Find the first card address of the first chunk in the stride that is 0N/A // at least "bottom" of the used region. 0N/A // Go ahead to the next chunk group boundary, then to the requested stride. 0N/A // We don't have to go downwards here; it wouldn't help anyway, 0N/A // because of parallelism. (We take care with "min_done"; see below.) 0N/A // Invariant: chunk_mr should be fully contained within the "used" region. 0N/A // Process the chunk. 0N/A // Find the next chunk of the stride. 0N/A // We must worry about the chunk boundaries. 0N/A // First, set our max_to_do: 0N/A // This is not the last chunk in the used region. What is the last 0N/A // It is an object and starts before the end of the current chunk. 0N/A // last_obj_card is the card corresponding to the start of the last object 0N/A // in the chunk. Note that the last object may not start in 0N/A // The card containing the head is not dirty. Any marks in 0N/A // subsequent cards still in this chunk must have been made 0N/A // precisely; we can cap processing at the end. 0N/A // The last object must be considered dirty, and extends onto the 0N/A // following chunk. Look for a dirty card in that chunk that will 0N/A // bound our processing. 0N/A // This search potentially goes a long distance looking 0N/A // for the next card that will be scanned. For example, 0N/A // an object that is an array of primitives will not 0N/A // have any cards covering regions interior to the array 0N/A // that will need to be scanned. The scan can be terminated 0N/A // at the last card of the next chunk. That would leave 0N/A // limit_card as NULL and would result in "max_to_do" 0N/A // being set with the LNC value or with the end 0N/A // of the last block. 0N/A // LNC for the next chunk 0N/A // Now we can set the closure we're using so it doesn't to beyond 0N/A // Now we set *our" lowest_non_clean entry. 0N/A // Find the object that spans our boundary, if one exists. 0N/A // Nothing to do on the first chunk. 0N/A // first_block is the block possibly spanning the chunk start 0N/A // Does the block span the start of the chunk and is it 0N/A // Only the first thread to obtain the lock will resize the 0N/A // LNC array for the covered region. Any later expansion can't affect 0N/A // the used_at_save_marks region. 0N/A // (I observed a bug in which the first thread to execute this would 0N/A // resize, and then it would cause "expand_and_allocates" that would 0N/A // Increase the number of chunks in the covered region. Then a second 0N/A // thread would come and execute this, see that the size didn't match, 0N/A // and free and allocate again. So the first thread would be using a 0N/A // freed "_lowest_non_clean" array.) 0N/A // Do a dirty read here. If we pass the conditional then take the rare 0N/A // event lock and do the read again in case some other thread had already 0N/A // succeeded and done the resize. 0N/A // Should we delete the old? 0N/A "logical consequence");
0N/A // Now allocate a new one if necessary. 0N/A // In any case, now do the initialization.