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