1 /*
2 * Copyright (c) 1998, 2014, 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 *
1018 // code -- a "PlatformMutex". Alternatively, a simply layer over muxAcquire-muxRelease
1019 // would work too.
1020 //
1021 // Since the caller might be a foreign thread, we don't necessarily have a Thread.MutexEvent
1022 // instance available. Instead, we transiently allocate a ParkEvent on-demand if
1023 // we encounter contention. That ParkEvent remains associated with the thread
1024 // until it manages to acquire the lock, at which time we return the ParkEvent
1025 // to the global ParkEvent free list. This is correct and suffices for our purposes.
1026 //
1027 // Beware that the original jvm_raw_unlock() had a "_snuck" test but that
1028 // jvm_raw_lock() didn't have the corresponding test. I suspect that's an
1029 // oversight, but I've replicated the original suspect logic in the new code ...
1030
1031 void Monitor::jvm_raw_lock() {
1032 assert(rank() == native, "invariant");
1033
1034 if (TryLock()) {
1035 Exeunt:
1036 assert(ILocked(), "invariant");
1037 assert(_owner == NULL, "invariant");
1038 // This can potentially be called by non-java Threads. Thus, the ThreadLocalStorage
1039 // might return NULL. Don't call set_owner since it will break on an NULL owner
1040 // Consider installing a non-null "ANON" distinguished value instead of just NULL.
1041 _owner = ThreadLocalStorage::thread();
1042 return;
1043 }
1044
1045 if (TrySpin(NULL)) goto Exeunt;
1046
1047 // slow-path - apparent contention
1048 // Allocate a ParkEvent for transient use.
1049 // The ParkEvent remains associated with this thread until
1050 // the time the thread manages to acquire the lock.
1051 ParkEvent * const ESelf = ParkEvent::Allocate(NULL);
1052 ESelf->reset();
1053 OrderAccess::storeload();
1054
1055 // Either Enqueue Self on cxq or acquire the outer lock.
1056 if (AcquireOrPush (ESelf)) {
1057 ParkEvent::Release(ESelf); // surrender the ParkEvent
1058 goto Exeunt;
1059 }
1060
1061 // At any given time there is at most one ondeck thread.
|
1 /*
2 * Copyright (c) 1998, 2015, 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 *
1018 // code -- a "PlatformMutex". Alternatively, a simply layer over muxAcquire-muxRelease
1019 // would work too.
1020 //
1021 // Since the caller might be a foreign thread, we don't necessarily have a Thread.MutexEvent
1022 // instance available. Instead, we transiently allocate a ParkEvent on-demand if
1023 // we encounter contention. That ParkEvent remains associated with the thread
1024 // until it manages to acquire the lock, at which time we return the ParkEvent
1025 // to the global ParkEvent free list. This is correct and suffices for our purposes.
1026 //
1027 // Beware that the original jvm_raw_unlock() had a "_snuck" test but that
1028 // jvm_raw_lock() didn't have the corresponding test. I suspect that's an
1029 // oversight, but I've replicated the original suspect logic in the new code ...
1030
1031 void Monitor::jvm_raw_lock() {
1032 assert(rank() == native, "invariant");
1033
1034 if (TryLock()) {
1035 Exeunt:
1036 assert(ILocked(), "invariant");
1037 assert(_owner == NULL, "invariant");
1038 // This can potentially be called by non-java Threads. Thus, the Thread::current_or_null()
1039 // might return NULL. Don't call set_owner since it will break on an NULL owner
1040 // Consider installing a non-null "ANON" distinguished value instead of just NULL.
1041 _owner = Thread::current_or_null();
1042 return;
1043 }
1044
1045 if (TrySpin(NULL)) goto Exeunt;
1046
1047 // slow-path - apparent contention
1048 // Allocate a ParkEvent for transient use.
1049 // The ParkEvent remains associated with this thread until
1050 // the time the thread manages to acquire the lock.
1051 ParkEvent * const ESelf = ParkEvent::Allocate(NULL);
1052 ESelf->reset();
1053 OrderAccess::storeload();
1054
1055 // Either Enqueue Self on cxq or acquire the outer lock.
1056 if (AcquireOrPush (ESelf)) {
1057 ParkEvent::Release(ESelf); // surrender the ParkEvent
1058 goto Exeunt;
1059 }
1060
1061 // At any given time there is at most one ondeck thread.
|