1 /* 2 * Copyright (c) 2018, 2019, 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 #ifndef SHARE_UTILITIES_GLOBALCOUNTER_HPP 26 #define SHARE_UTILITIES_GLOBALCOUNTER_HPP 27 28 #include "memory/allocation.hpp" 29 #include "memory/padded.hpp" 30 31 class Thread; 32 33 // The GlobalCounter provides a synchronization mechanism between threads for 34 // safe memory reclamation and other ABA problems. All readers must call 35 // critical_section_begin before reading the volatile data and 36 // critical_section_end afterwards. Such read-side critical sections may 37 // be properly nested. The write side must call write_synchronize 38 // before reclaming the memory. The read-path only does an uncontended store 39 // to a thread-local-storage and fence to stop any loads from floating up, thus 40 // light weight and wait-free. The write-side is more heavy since it must check 41 // all readers and wait until they have left the generation. (a system memory 42 // barrier can be used on write-side to remove fence in read-side, 43 // not implemented). 44 class GlobalCounter : public AllStatic { 45 private: 46 // Since do not know what we will end up next to in BSS, we make sure the 47 // counter is on a seperate cacheline. 48 struct PaddedCounter { 49 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); 50 volatile uintx _counter; 51 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uintx)); 52 }; 53 54 // The global counter 55 static PaddedCounter _global_counter; 56 57 // Bit 0 is active bit. 58 static const uintx COUNTER_ACTIVE = 1; 59 // Thus we increase counter by 2. 60 static const uintx COUNTER_INCREMENT = 2; 61 62 // The per thread scanning closure. 63 class CounterThreadCheck; 64 65 public: 66 // The type of the critical section context passed from 67 // critical_section_begin() to critical_section_end(). 68 typedef uintx CSContext; 69 70 // Must be called before accessing the data. The result must be passed 71 // to the associated call to critical_section_end(). Acts as a full 72 // memory barrier before the code within the critical section. 73 static CSContext critical_section_begin(Thread *thread); 74 75 // Must be called after finished accessing the data. The context 76 // must be the result of the associated initiating critical_section_begin(). 77 // Acts as a release memory barrier after the code within the critical 78 // section. 79 static void critical_section_end(Thread *thread, CSContext context); 80 81 // Make the data inaccessible to readers before calling. When this call 82 // returns it's safe to reclaim the data. Acts as a full memory barrier. 83 static void write_synchronize(); 84 85 // A scoped object for a read-side critical-section. 86 class CriticalSection; 87 }; 88 89 #endif // SHARE_UTILITIES_GLOBALCOUNTER_HPP 90