src/hotspot/share/utilities/singleWriterSynchronizer.hpp
author kbarrett
Thu, 23 Aug 2018 18:14:53 -0400
changeset 51511 eb8d5aeabab3
child 52332 d2a3503c72f7
permissions -rw-r--r--
8209850: Allow NamedThreads to use GlobalCounter critical sections Summary: Add NamedThreads iterator and make GlobalCounter use it. Reviewed-by: eosterlund, rehn
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
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    39
// that were extent when the wait was initiated.  Usage is that there
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
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    49
// situations where GlobalCounter won't work for some reason, such as
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    50
// nesting.  But note that nesting often indicates other problems, and
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    51
// may risk deadlock.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    52
class SingleWriterSynchronizer {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    53
  volatile uint _enter;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    54
  volatile uint _exit[2];
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    55
  volatile uint _waiting_for;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    56
  Semaphore _wakeup;
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
  DEBUG_ONLY(volatile uint _writers;)
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    59
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    60
  // Noncopyable.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    61
  SingleWriterSynchronizer(const SingleWriterSynchronizer&);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    62
  SingleWriterSynchronizer& operator=(const SingleWriterSynchronizer&);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    63
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    64
public:
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    65
  SingleWriterSynchronizer();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    66
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    67
  // Enter a critical section for this synchronizer.  Entering a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    68
  // critical section never blocks.  While in a critical section, a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    69
  // thread should avoid blocking, or even take a long time.  In
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    70
  // particular, a thread must never safepoint while in a critical
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    71
  // section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    72
  // Precondition: The current thread must not already be in a
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    73
  // critical section for this synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    74
  inline uint enter();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    75
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    76
  // Exit a critical section for this synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    77
  // Precondition: enter_value must be the result of the corresponding
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    78
  // enter() for the critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    79
  inline void exit(uint enter_value);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    80
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    81
  // Wait until all threads currently in a critical section for this
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    82
  // synchronizer have exited their critical section.  Threads that
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    83
  // enter a critical section after the synchronization has started
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    84
  // are not considered in the wait.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    85
  // Precondition: No other thread may be synchronizing on this
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    86
  // synchronizer.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    87
  void synchronize();
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    88
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    89
  // RAII class for managing enter/exit pairs.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    90
  class CriticalSection;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    91
};
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    92
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    93
inline uint SingleWriterSynchronizer::enter() {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    94
  return Atomic::add(2u, &_enter);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    95
}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    96
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    97
inline void SingleWriterSynchronizer::exit(uint enter_value) {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    98
  uint exit_value = Atomic::add(2u, &_exit[enter_value & 1]);
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
    99
  // If this exit completes a synchronize request, wakeup possibly
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   100
  // waiting synchronizer.  Read of _waiting_for must follow the _exit
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   101
  // update.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   102
  if (exit_value == _waiting_for) {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   103
    _wakeup.signal();
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
}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   106
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   107
class SingleWriterSynchronizer::CriticalSection : public StackObj {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   108
  SingleWriterSynchronizer* _synchronizer;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   109
  uint _enter_value;
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   110
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   111
public:
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   112
  // Enter synchronizer's critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   113
  explicit CriticalSection(SingleWriterSynchronizer* synchronizer) :
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   114
    _synchronizer(synchronizer),
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   115
    _enter_value(synchronizer->enter())
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   116
  {}
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   117
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   118
  // Exit synchronizer's critical section.
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   119
  ~CriticalSection() {
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   120
    _synchronizer->exit(_enter_value);
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
};
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   123
eb8d5aeabab3 8209850: Allow NamedThreads to use GlobalCounter critical sections
kbarrett
parents:
diff changeset
   124
#endif // SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP