1 /* 2 * Copyright (c) 2002, 2025, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import jdk.internal.access.JavaLangAccess; 29 import jdk.internal.access.SharedSecrets; 30 31 32 // Signalling operations on native threads 33 // 34 // On some operating systems (e.g., Linux), closing a channel while another 35 // thread is blocked in an I/O operation upon that channel does not cause that 36 // thread to be released. This class provides access to the native threads 37 // upon which Java threads are built, and defines a simple signal mechanism 38 // that can be used to release a native thread from a blocking I/O operation. 39 // On systems that do not require this type of signalling, the current() method 40 // always returns -1 and the signal(long) method has no effect. 41 42 public class NativeThread { 43 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); 44 private static final long VIRTUAL_THREAD_ID = -1L; 45 46 private final Thread thread; 47 private final long tid; 48 49 private NativeThread(Thread thread, long tid) { 50 this.thread = thread; 51 this.tid = tid; 52 } 53 54 Thread thread() { 55 return thread; 56 } 57 58 /** 59 * Return a NativeThread for the current thread. 60 */ 61 public static NativeThread current() { 62 Thread t = Thread.currentThread(); 63 if (t.isVirtual()) { 64 // return new object for now 65 return new NativeThread(t, VIRTUAL_THREAD_ID); 66 } else { 67 NativeThread nt = JLA.nativeThread(t); 68 if (nt == null) { 69 nt = new NativeThread(t, current0()); 70 JLA.setNativeThread(nt); 71 } 72 return nt; 73 } 74 } 75 76 /** 77 * Return a NativeThread for the current platform thread. Returns null if called 78 * from a virtual thread. 79 */ 80 public static NativeThread currentNativeThread() { 81 Thread t = Thread.currentThread(); 82 if (t.isVirtual()) { 83 return null; 84 } else { 85 NativeThread nt = JLA.nativeThread(t); 86 if (nt == null) { 87 nt = new NativeThread(t, current0()); 88 JLA.setNativeThread(nt); 89 } 90 return nt; 91 } 92 } 93 94 /** 95 * Return true if the given NativeThread is a platform thread. 96 */ 97 public static boolean isNativeThread(NativeThread nt) { 98 return nt != null && nt.tid != VIRTUAL_THREAD_ID; 99 } 100 101 /** 102 * Return true if the given NativeThread is a virtual thread. 103 */ 104 public static boolean isVirtualThread(NativeThread nt) { 105 return nt != null && nt.tid == VIRTUAL_THREAD_ID; 106 } 107 108 /** 109 * Signals this native thread. 110 * @throws UnsupportedOperationException if virtual thread 111 */ 112 public void signal() { 113 if (tid == VIRTUAL_THREAD_ID) 114 throw new UnsupportedOperationException(); 115 signal0(tid); 116 } 117 118 /** 119 * Return true if the operating system supports pending signals. If a signal is sent 120 * to a thread but cannot be delivered immediately then it will be delivered when the 121 * thread is in the appropriate state. 122 */ 123 static boolean supportPendingSignals() { 124 return supportPendingSignals0(); 125 } 126 127 private static native boolean supportPendingSignals0(); 128 129 // Returns an opaque token representing the native thread underlying the 130 // invoking Java thread. On systems that do not require signalling, this 131 // method always returns 0. 132 // 133 private static native long current0(); 134 135 // Signals the given native thread so as to release it from a blocking I/O 136 // operation. On systems that do not require signalling, this method has 137 // no effect. 138 // 139 private static native void signal0(long tid); 140 141 private static native void init(); 142 143 static { 144 IOUtil.load(); 145 init(); 146 } 147 148 }