src/hotspot/share/utilities/singleWriterSynchronizer.hpp
author stefank
Mon, 25 Nov 2019 12:31:39 +0100
changeset 59249 29b0d0b61615
parent 52332 d2a3503c72f7
permissions -rw-r--r--
8234737: Harmonize parameter order in Atomic - add Reviewed-by: rehn, dholmes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
51511
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     1
/*
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     2
 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     4
 *
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     7
 * published by the Free Software Foundation.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     8
 *
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    13
 * accompanied this code).
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    14
 *
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    18
 *
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    21
 * questions.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    22
 *
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    23
 */
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    24
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    25
#ifndef SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    26
#define SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    27
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    28
#include "memory/allocation.hpp"
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    29
#include "runtime/atomic.hpp"
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    30
#include "runtime/semaphore.hpp"
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    31
#include "utilities/globalDefinitions.hpp"
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    32
#include "utilities/macros.hpp"
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    33
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    34
// Synchronization primitive inspired by RCU.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    35
//
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    36
// Any number of threads may enter critical sections associated with a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    37
// synchronizer object.  One (at a time) other thread may wait for the
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    38
// completion of all critical sections for the synchronizer object
52332
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51511
diff changeset
    39
// that were extant when the wait was initiated.  Usage is that there
51511
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    40
// is some state that can be accessed either before or after some
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    41
// change.  An accessing thread performs the access within a critical
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    42
// section.  A writer thread performs the state change, and then waits
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    43
// for critical sections to complete, thereby ensuring there are no
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    44
// threads in a critical section that might have seen the old state.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    45
//
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    46
// Generally, GlobalCounter should be used instead of this class, as
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    47
// GlobalCounter has measurably better performance and doesn't have
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    48
// the single writer at a time restriction.  Use this only in
52332
d2a3503c72f7 8212827: GlobalCounter should support nested critical sections
kbarrett
parents: 51511
diff changeset
    49
// situations where GlobalCounter won't work for some reason.
51511
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    50
class SingleWriterSynchronizer {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    51
  volatile uint _enter;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    52
  volatile uint _exit[2];
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    53
  volatile uint _waiting_for;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    54
  Semaphore _wakeup;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    55
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    56
  DEBUG_ONLY(volatile uint _writers;)
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    57
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    58
  // Noncopyable.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    59
  SingleWriterSynchronizer(const SingleWriterSynchronizer&);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    60
  SingleWriterSynchronizer& operator=(const SingleWriterSynchronizer&);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    61
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    62
public:
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    63
  SingleWriterSynchronizer();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    64
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    65
  // Enter a critical section for this synchronizer.  Entering a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    66
  // critical section never blocks.  While in a critical section, a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    67
  // thread should avoid blocking, or even take a long time.  In
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    68
  // particular, a thread must never safepoint while in a critical
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    69
  // section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    70
  // Precondition: The current thread must not already be in a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    71
  // critical section for this synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    72
  inline uint enter();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    73
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    74
  // Exit a critical section for this synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    75
  // Precondition: enter_value must be the result of the corresponding
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    76
  // enter() for the critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    77
  inline void exit(uint enter_value);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    78
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    79
  // Wait until all threads currently in a critical section for this
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    80
  // synchronizer have exited their critical section.  Threads that
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    81
  // enter a critical section after the synchronization has started
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    82
  // are not considered in the wait.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    83
  // Precondition: No other thread may be synchronizing on this
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    84
  // synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    85
  void synchronize();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    86
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    87
  // RAII class for managing enter/exit pairs.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    88
  class CriticalSection;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    89
};
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    90
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    91
inline uint SingleWriterSynchronizer::enter() {
59249
29b0d0b61615 8234737: Harmonize parameter order in Atomic - add
stefank
parents: 52332
diff changeset
    92
  return Atomic::add(&_enter, 2u);
51511
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    93
}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    94
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    95
inline void SingleWriterSynchronizer::exit(uint enter_value) {
59249
29b0d0b61615 8234737: Harmonize parameter order in Atomic - add
stefank
parents: 52332
diff changeset
    96
  uint exit_value = Atomic::add(&_exit[enter_value & 1], 2u);
51511
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    97
  // If this exit completes a synchronize request, wakeup possibly
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    98
  // waiting synchronizer.  Read of _waiting_for must follow the _exit
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    99
  // update.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   100
  if (exit_value == _waiting_for) {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   101
    _wakeup.signal();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   102
  }
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   103
}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   104
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   105
class SingleWriterSynchronizer::CriticalSection : public StackObj {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   106
  SingleWriterSynchronizer* _synchronizer;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   107
  uint _enter_value;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   108
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   109
public:
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   110
  // Enter synchronizer's critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   111
  explicit CriticalSection(SingleWriterSynchronizer* synchronizer) :
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   112
    _synchronizer(synchronizer),
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   113
    _enter_value(synchronizer->enter())
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   114
  {}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   115
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   116
  // Exit synchronizer's critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   117
  ~CriticalSection() {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   118
    _synchronizer->exit(_enter_value);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   119
  }
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   120
};
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   121
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   122
#endif // SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP