2
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
25
#include "precompiled.hpp"
26
#include "memory/allocation.inline.hpp"
27
#include "nmt/memTracker.hpp"
28
#include "runtime/javaThread.hpp"
30
// Lifecycle management for TSM ParkEvents.
31
// ParkEvents are type-stable (TSM).
32
// In our particular implementation they happen to be immortal.
34
// We manage concurrency on the FreeList with a CAS-based
35
// detach-modify-reattach idiom that avoids the ABA problems
36
// that would otherwise be present in a simple CAS-based
37
// push-pop implementation. (push-one and pop-all)
39
// Caveat: Allocate() and Release() may be called from threads
40
// other than the thread associated with the Event!
41
// If we need to call Allocate() when running as the thread in
42
// question then look for the PD calls to initialize native TLS.
43
// Native TLS (Win32/Linux/Solaris) can only be initialized or
44
// accessed by the associated thread.
45
// See also pd_initialize().
47
// Note that we could defer associating a ParkEvent with a thread
48
// until the 1st time the thread calls park(). unpark() calls to
49
// an unprovisioned thread would be ignored. The first park() call
50
// for a thread would allocate and associate a ParkEvent and return
53
volatile int ParkEvent::ListLock = 0 ;
54
ParkEvent * volatile ParkEvent::FreeList = nullptr ;
56
ParkEvent * ParkEvent::Allocate (Thread * t) {
59
// Start by trying to recycle an existing but unassociated
60
// ParkEvent from the global free list.
61
// Using a spin lock since we are part of the mutex impl.
62
// 8028280: using concurrent free list without memory management can leak
63
// pretty badly it turns out.
64
Thread::SpinAcquire(&ListLock, "ParkEventFreeListAllocate");
68
FreeList = ev->FreeNext;
71
Thread::SpinRelease(&ListLock);
74
guarantee (ev->AssociatedWith == nullptr, "invariant") ;
76
// Do this the hard way -- materialize a new ParkEvent.
77
ev = new ParkEvent () ;
78
guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
80
ev->reset() ; // courtesy to caller
81
ev->AssociatedWith = t ; // Associate ev with t
82
ev->FreeNext = nullptr ;
86
void ParkEvent::Release (ParkEvent * ev) {
87
if (ev == nullptr) return ;
88
guarantee (ev->FreeNext == nullptr , "invariant") ;
89
ev->AssociatedWith = nullptr ;
90
// Note that if we didn't have the TSM/immortal constraint, then
91
// when reattaching we could trim the list.
92
Thread::SpinAcquire(&ListLock, "ParkEventFreeListRelease");
94
ev->FreeNext = FreeList;
97
Thread::SpinRelease(&ListLock);
100
// Override operator new and delete so we can ensure that the
101
// least significant byte of ParkEvent addresses is 0.
102
// Beware that excessive address alignment is undesirable
103
// as it can result in D$ index usage imbalance as
104
// well as bank access imbalance on Niagara-like platforms,
105
// although Niagara's hash function should help.
107
void * ParkEvent::operator new (size_t sz) throw() {
108
return (void *) ((intptr_t (AllocateHeap(sz + 256, mtInternal, CALLER_PC)) + 256) & -256) ;
111
void ParkEvent::operator delete (void * a) {
112
// ParkEvents are type-stable and immortal ...
113
ShouldNotReachHere();